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

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

Issue 17033004: Tell IDB frontend about data loss (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove debug Created 7 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/indexed_db_database.h" 5 #include "content/browser/indexed_db/indexed_db_database.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/auto_reset.h" 10 #include "base/auto_reset.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 }; 56 };
57 57
58 class IndexedDBDatabase::VersionChangeOperation 58 class IndexedDBDatabase::VersionChangeOperation
59 : public IndexedDBTransaction::Operation { 59 : public IndexedDBTransaction::Operation {
60 public: 60 public:
61 VersionChangeOperation( 61 VersionChangeOperation(
62 scoped_refptr<IndexedDBDatabase> database, 62 scoped_refptr<IndexedDBDatabase> database,
63 int64 transaction_id, 63 int64 transaction_id,
64 int64 version, 64 int64 version,
65 scoped_refptr<IndexedDBCallbacksWrapper> callbacks, 65 scoped_refptr<IndexedDBCallbacksWrapper> callbacks,
66 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks) 66 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks,
67 bool data_loss)
jsbell 2013/06/14 20:42:58 Pluming this through VersionChangeOperation seems
dgrogan 2013/06/14 22:06:43 I considered keeping some state like you describe
67 : database_(database), 68 : database_(database),
68 transaction_id_(transaction_id), 69 transaction_id_(transaction_id),
69 version_(version), 70 version_(version),
70 callbacks_(callbacks), 71 callbacks_(callbacks),
71 database_callbacks_(database_callbacks) {} 72 database_callbacks_(database_callbacks),
73 data_loss_(data_loss) {}
72 virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; 74 virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
73 75
74 private: 76 private:
75 scoped_refptr<IndexedDBDatabase> database_; 77 scoped_refptr<IndexedDBDatabase> database_;
76 int64 transaction_id_; 78 int64 transaction_id_;
77 int64 version_; 79 int64 version_;
78 scoped_refptr<IndexedDBCallbacksWrapper> callbacks_; 80 scoped_refptr<IndexedDBCallbacksWrapper> callbacks_;
79 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks_; 81 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks_;
82 bool data_loss_;
80 }; 83 };
81 84
82 class CreateObjectStoreAbortOperation : public IndexedDBTransaction::Operation { 85 class CreateObjectStoreAbortOperation : public IndexedDBTransaction::Operation {
83 public: 86 public:
84 CreateObjectStoreAbortOperation(scoped_refptr<IndexedDBDatabase> database, 87 CreateObjectStoreAbortOperation(scoped_refptr<IndexedDBDatabase> database,
85 int64 object_store_id) 88 int64 object_store_id)
86 : database_(database), object_store_id_(object_store_id) {} 89 : database_(database), object_store_id_(object_store_id) {}
87 virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE; 90 virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
88 91
89 private: 92 private:
(...skipping 1297 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 WebKit::WebIDBDatabaseExceptionUnknownError, 1390 WebKit::WebIDBDatabaseExceptionUnknownError,
1388 ASCIIToUTF16("Internal error writing data to stable storage when " 1391 ASCIIToUTF16("Internal error writing data to stable storage when "
1389 "updating version.")); 1392 "updating version."));
1390 callbacks_->OnError(error); 1393 callbacks_->OnError(error);
1391 transaction->Abort(error); 1394 transaction->Abort(error);
1392 return; 1395 return;
1393 } 1396 }
1394 DCHECK(!database_->pending_second_half_open_); 1397 DCHECK(!database_->pending_second_half_open_);
1395 database_->pending_second_half_open_.reset(new PendingOpenCall( 1398 database_->pending_second_half_open_.reset(new PendingOpenCall(
1396 callbacks_, database_callbacks_, transaction_id_, version_)); 1399 callbacks_, database_callbacks_, transaction_id_, version_));
1397 callbacks_->OnUpgradeNeeded(old_version, database_, database_->metadata()); 1400 callbacks_->OnUpgradeNeeded(
1401 old_version, database_, database_->metadata(), data_loss_);
1398 } 1402 }
1399 1403
1400 void IndexedDBDatabase::TransactionStarted(IndexedDBTransaction* transaction) { 1404 void IndexedDBDatabase::TransactionStarted(IndexedDBTransaction* transaction) {
1401 1405
1402 if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) { 1406 if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
1403 DCHECK(!running_version_change_transaction_); 1407 DCHECK(!running_version_change_transaction_);
1404 running_version_change_transaction_ = transaction; 1408 running_version_change_transaction_ = transaction;
1405 } 1409 }
1406 } 1410 }
1407 1411
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1460 } 1464 }
1461 1465
1462 if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) { 1466 if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) {
1463 DCHECK(pending_run_version_change_transaction_call_->Version() > 1467 DCHECK(pending_run_version_change_transaction_call_->Version() >
1464 metadata_.int_version); 1468 metadata_.int_version);
1465 scoped_ptr<PendingOpenCall> pending_call = 1469 scoped_ptr<PendingOpenCall> pending_call =
1466 pending_run_version_change_transaction_call_.Pass(); 1470 pending_run_version_change_transaction_call_.Pass();
1467 RunVersionChangeTransactionFinal(pending_call->Callbacks(), 1471 RunVersionChangeTransactionFinal(pending_call->Callbacks(),
1468 pending_call->DatabaseCallbacks(), 1472 pending_call->DatabaseCallbacks(),
1469 pending_call->TransactionId(), 1473 pending_call->TransactionId(),
1470 pending_call->Version()); 1474 pending_call->Version(),
1475 false);
jsbell 2013/06/14 20:42:58 Can you give the argument a default value instead
dgrogan 2013/06/14 22:06:43 Done.
1471 DCHECK_EQ(static_cast<size_t>(1), ConnectionCount()); 1476 DCHECK_EQ(static_cast<size_t>(1), ConnectionCount());
1472 // Fall through would be a no-op, since transaction must complete 1477 // Fall through would be a no-op, since transaction must complete
1473 // asynchronously. 1478 // asynchronously.
1474 DCHECK(IsDeleteDatabaseBlocked()); 1479 DCHECK(IsDeleteDatabaseBlocked());
1475 DCHECK(IsOpenConnectionBlocked()); 1480 DCHECK(IsOpenConnectionBlocked());
1476 return; 1481 return;
1477 } 1482 }
1478 1483
1479 if (!IsDeleteDatabaseBlocked()) { 1484 if (!IsDeleteDatabaseBlocked()) {
1480 PendingDeleteCallList pending_delete_calls; 1485 PendingDeleteCallList pending_delete_calls;
(...skipping 13 matching lines...) Expand all
1494 1499
1495 if (!IsOpenConnectionBlocked()) { 1500 if (!IsOpenConnectionBlocked()) {
1496 PendingOpenCallList pending_open_calls; 1501 PendingOpenCallList pending_open_calls;
1497 pending_open_calls_.swap(pending_open_calls); 1502 pending_open_calls_.swap(pending_open_calls);
1498 while (!pending_open_calls.empty()) { 1503 while (!pending_open_calls.empty()) {
1499 scoped_ptr<PendingOpenCall> pending_open_call(pending_open_calls.front()); 1504 scoped_ptr<PendingOpenCall> pending_open_call(pending_open_calls.front());
1500 pending_open_calls.pop_front(); 1505 pending_open_calls.pop_front();
1501 OpenConnection(pending_open_call->Callbacks(), 1506 OpenConnection(pending_open_call->Callbacks(),
1502 pending_open_call->DatabaseCallbacks(), 1507 pending_open_call->DatabaseCallbacks(),
1503 pending_open_call->TransactionId(), 1508 pending_open_call->TransactionId(),
1504 pending_open_call->Version()); 1509 pending_open_call->Version(),
1510 false);
jsbell 2013/06/14 20:42:58 Ditto.
dgrogan 2013/06/14 22:06:43 Done.
1505 } 1511 }
1506 } 1512 }
1507 } 1513 }
1508 1514
1509 void IndexedDBDatabase::CreateTransaction( 1515 void IndexedDBDatabase::CreateTransaction(
1510 int64 transaction_id, 1516 int64 transaction_id,
1511 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> callbacks, 1517 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> callbacks,
1512 const std::vector<int64>& object_store_ids, 1518 const std::vector<int64>& object_store_ids,
1513 uint16 mode) { 1519 uint16 mode) {
1514 1520
(...skipping 13 matching lines...) Expand all
1528 bool IndexedDBDatabase::IsOpenConnectionBlocked() const { 1534 bool IndexedDBDatabase::IsOpenConnectionBlocked() const {
1529 return !pending_delete_calls_.empty() || 1535 return !pending_delete_calls_.empty() ||
1530 running_version_change_transaction_ || 1536 running_version_change_transaction_ ||
1531 pending_run_version_change_transaction_call_; 1537 pending_run_version_change_transaction_call_;
1532 } 1538 }
1533 1539
1534 void IndexedDBDatabase::OpenConnection( 1540 void IndexedDBDatabase::OpenConnection(
1535 scoped_refptr<IndexedDBCallbacksWrapper> callbacks, 1541 scoped_refptr<IndexedDBCallbacksWrapper> callbacks,
1536 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks, 1542 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks,
1537 int64 transaction_id, 1543 int64 transaction_id,
1538 int64 version) { 1544 int64 version,
1545 bool data_loss) {
1539 DCHECK(backing_store_.get()); 1546 DCHECK(backing_store_.get());
1540 1547
1541 // TODO(jsbell): Should have a priority queue so that higher version 1548 // TODO(jsbell): Should have a priority queue so that higher version
1542 // requests are processed first. http://crbug.com/225850 1549 // requests are processed first. http://crbug.com/225850
1543 if (IsOpenConnectionBlocked()) { 1550 if (IsOpenConnectionBlocked()) {
1551 // The backing store only detects data loss when it is first opened. The
1552 // presence of existing connections means we didn't even check for data loss
1553 // so there'd better not be any.
1554 DCHECK(!data_loss);
1544 pending_open_calls_.push_back(new PendingOpenCall( 1555 pending_open_calls_.push_back(new PendingOpenCall(
1545 callbacks, database_callbacks, transaction_id, version)); 1556 callbacks, database_callbacks, transaction_id, version));
1546 return; 1557 return;
1547 } 1558 }
1548 1559
1549 if (metadata_.id == kInvalidId) { 1560 if (metadata_.id == kInvalidId) {
1550 // The database was deleted then immediately re-opened; OpenInternal() 1561 // The database was deleted then immediately re-opened; OpenInternal()
1551 // recreates it in the backing store. 1562 // recreates it in the backing store.
1552 if (OpenInternal()) { 1563 if (OpenInternal()) {
1553 DCHECK_EQ(metadata_.int_version, 1564 DCHECK_EQ(metadata_.int_version,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1590 return; 1601 return;
1591 } 1602 }
1592 // Spec says: If no version is specified and no database exists, set 1603 // Spec says: If no version is specified and no database exists, set
1593 // database version to 1. 1604 // database version to 1.
1594 version = 1; 1605 version = 1;
1595 } 1606 }
1596 1607
1597 if (version > metadata_.int_version) { 1608 if (version > metadata_.int_version) {
1598 database_callbacks_set_.insert(database_callbacks); 1609 database_callbacks_set_.insert(database_callbacks);
1599 RunVersionChangeTransaction( 1610 RunVersionChangeTransaction(
1600 callbacks, database_callbacks, transaction_id, version); 1611 callbacks, database_callbacks, transaction_id, version, data_loss);
1601 return; 1612 return;
1602 } 1613 }
1603 if (version < metadata_.int_version) { 1614 if (version < metadata_.int_version) {
1604 callbacks->OnError(IndexedDBDatabaseError( 1615 callbacks->OnError(IndexedDBDatabaseError(
1605 WebKit::WebIDBDatabaseExceptionVersionError, 1616 WebKit::WebIDBDatabaseExceptionVersionError,
1606 ASCIIToUTF16("The requested version (") + Int64ToString16(version) + 1617 ASCIIToUTF16("The requested version (") + Int64ToString16(version) +
1607 ASCIIToUTF16(") is less than the existing version (") + 1618 ASCIIToUTF16(") is less than the existing version (") +
1608 Int64ToString16(metadata_.int_version) + ASCIIToUTF16(")."))); 1619 Int64ToString16(metadata_.int_version) + ASCIIToUTF16(").")));
1609 return; 1620 return;
1610 } 1621 }
1611 DCHECK_EQ(version, metadata_.int_version); 1622 DCHECK_EQ(version, metadata_.int_version);
1612 database_callbacks_set_.insert(database_callbacks); 1623 database_callbacks_set_.insert(database_callbacks);
1613 callbacks->OnSuccess(this, this->metadata()); 1624 callbacks->OnSuccess(this, this->metadata());
1614 } 1625 }
1615 1626
1616 void IndexedDBDatabase::RunVersionChangeTransaction( 1627 void IndexedDBDatabase::RunVersionChangeTransaction(
1617 scoped_refptr<IndexedDBCallbacksWrapper> callbacks, 1628 scoped_refptr<IndexedDBCallbacksWrapper> callbacks,
1618 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks, 1629 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks,
1619 int64 transaction_id, 1630 int64 transaction_id,
1620 int64 requested_version) { 1631 int64 requested_version,
1632 bool data_loss) {
1621 1633
1622 DCHECK(callbacks.get()); 1634 DCHECK(callbacks.get());
1623 DCHECK(database_callbacks_set_.has(database_callbacks)); 1635 DCHECK(database_callbacks_set_.has(database_callbacks));
1624 if (ConnectionCount() > 1) { 1636 if (ConnectionCount() > 1) {
1637 DCHECK(!data_loss);
1625 // Front end ensures the event is not fired at connections that have 1638 // Front end ensures the event is not fired at connections that have
1626 // close_pending set. 1639 // close_pending set.
1627 for (DatabaseCallbacksSet::const_iterator it = 1640 for (DatabaseCallbacksSet::const_iterator it =
1628 database_callbacks_set_.begin(); 1641 database_callbacks_set_.begin();
1629 it != database_callbacks_set_.end(); 1642 it != database_callbacks_set_.end();
1630 ++it) { 1643 ++it) {
1631 if (it->get() != database_callbacks.get()) 1644 if (it->get() != database_callbacks.get())
1632 (*it)->OnVersionChange(metadata_.int_version, requested_version); 1645 (*it)->OnVersionChange(metadata_.int_version, requested_version);
1633 } 1646 }
1634 // TODO(jsbell): Remove the call to on_blocked and instead wait 1647 // TODO(jsbell): Remove the call to on_blocked and instead wait
1635 // until the frontend tells us that all the "versionchange" events 1648 // until the frontend tells us that all the "versionchange" events
1636 // have been delivered. http://crbug.com/100123 1649 // have been delivered. http://crbug.com/100123
1637 callbacks->OnBlocked(metadata_.int_version); 1650 callbacks->OnBlocked(metadata_.int_version);
1638 1651
1639 DCHECK(!pending_run_version_change_transaction_call_); 1652 DCHECK(!pending_run_version_change_transaction_call_);
1640 pending_run_version_change_transaction_call_.reset(new PendingOpenCall( 1653 pending_run_version_change_transaction_call_.reset(new PendingOpenCall(
1641 callbacks, database_callbacks, transaction_id, requested_version)); 1654 callbacks, database_callbacks, transaction_id, requested_version));
1642 return; 1655 return;
1643 } 1656 }
1644 RunVersionChangeTransactionFinal( 1657 RunVersionChangeTransactionFinal(callbacks,
1645 callbacks, database_callbacks, transaction_id, requested_version); 1658 database_callbacks,
1659 transaction_id,
1660 requested_version,
1661 data_loss);
1646 } 1662 }
1647 1663
1648 void IndexedDBDatabase::RunVersionChangeTransactionFinal( 1664 void IndexedDBDatabase::RunVersionChangeTransactionFinal(
1649 scoped_refptr<IndexedDBCallbacksWrapper> callbacks, 1665 scoped_refptr<IndexedDBCallbacksWrapper> callbacks,
1650 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks, 1666 scoped_refptr<IndexedDBDatabaseCallbacksWrapper> database_callbacks,
1651 int64 transaction_id, 1667 int64 transaction_id,
1652 int64 requested_version) { 1668 int64 requested_version,
1669 bool data_loss) {
1653 1670
1654 std::vector<int64> object_store_ids; 1671 std::vector<int64> object_store_ids;
1655 CreateTransaction(transaction_id, 1672 CreateTransaction(transaction_id,
1656 database_callbacks, 1673 database_callbacks,
1657 object_store_ids, 1674 object_store_ids,
1658 indexed_db::TRANSACTION_VERSION_CHANGE); 1675 indexed_db::TRANSACTION_VERSION_CHANGE);
1659 scoped_refptr<IndexedDBTransaction> transaction = 1676 scoped_refptr<IndexedDBTransaction> transaction =
1660 transactions_[transaction_id]; 1677 transactions_[transaction_id];
1661 1678
1662 transaction->ScheduleTask( 1679 transaction->ScheduleTask(
1663 new VersionChangeOperation(this, 1680 new VersionChangeOperation(this,
1664 transaction_id, 1681 transaction_id,
1665 requested_version, 1682 requested_version,
1666 callbacks, 1683 callbacks,
1667 database_callbacks), 1684 database_callbacks,
1685 data_loss),
1668 new VersionChangeAbortOperation( 1686 new VersionChangeAbortOperation(
1669 this, metadata_.version, metadata_.int_version)); 1687 this, metadata_.version, metadata_.int_version));
1670 1688
1671 DCHECK(!pending_second_half_open_); 1689 DCHECK(!pending_second_half_open_);
1672 } 1690 }
1673 1691
1674 void IndexedDBDatabase::DeleteDatabase( 1692 void IndexedDBDatabase::DeleteDatabase(
1675 scoped_refptr<IndexedDBCallbacksWrapper> callbacks) { 1693 scoped_refptr<IndexedDBCallbacksWrapper> callbacks) {
1676 1694
1677 if (IsDeleteDatabaseBlocked()) { 1695 if (IsDeleteDatabaseBlocked()) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1788 1806
1789 void IndexedDBDatabase::VersionChangeAbortOperation::Perform( 1807 void IndexedDBDatabase::VersionChangeAbortOperation::Perform(
1790 IndexedDBTransaction* transaction) { 1808 IndexedDBTransaction* transaction) {
1791 IDB_TRACE("VersionChangeAbortOperation"); 1809 IDB_TRACE("VersionChangeAbortOperation");
1792 DCHECK(!transaction); 1810 DCHECK(!transaction);
1793 database_->metadata_.version = previous_version_; 1811 database_->metadata_.version = previous_version_;
1794 database_->metadata_.int_version = previous_int_version_; 1812 database_->metadata_.int_version = previous_int_version_;
1795 } 1813 }
1796 1814
1797 } // namespace content 1815 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698