Chromium Code Reviews| 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 |