OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |