| 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 | 8 |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <memory> | 10 #include <memory> |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 &metadata_.object_stores); | 226 &metadata_.object_stores); |
| 227 | 227 |
| 228 return backing_store_->CreateIDBDatabaseMetaData( | 228 return backing_store_->CreateIDBDatabaseMetaData( |
| 229 metadata_.name, metadata_.version, &metadata_.id); | 229 metadata_.name, metadata_.version, &metadata_.id); |
| 230 } | 230 } |
| 231 | 231 |
| 232 IndexedDBDatabase::~IndexedDBDatabase() { | 232 IndexedDBDatabase::~IndexedDBDatabase() { |
| 233 DCHECK(transactions_.empty()); | 233 DCHECK(transactions_.empty()); |
| 234 DCHECK(pending_open_calls_.empty()); | 234 DCHECK(pending_open_calls_.empty()); |
| 235 DCHECK(pending_delete_calls_.empty()); | 235 DCHECK(pending_delete_calls_.empty()); |
| 236 DCHECK(blocked_delete_calls_.empty()); |
| 236 } | 237 } |
| 237 | 238 |
| 238 size_t IndexedDBDatabase::GetMaxMessageSizeInBytes() const { | 239 size_t IndexedDBDatabase::GetMaxMessageSizeInBytes() const { |
| 239 return kMaxIDBMessageSizeInBytes; | 240 return kMaxIDBMessageSizeInBytes; |
| 240 } | 241 } |
| 241 | 242 |
| 242 std::unique_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection( | 243 std::unique_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection( |
| 243 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks, | 244 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks, |
| 244 int child_process_id) { | 245 int child_process_id) { |
| 245 std::unique_ptr<IndexedDBConnection> connection( | 246 std::unique_ptr<IndexedDBConnection> connection( |
| (...skipping 1383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1629 metadata_.version); | 1630 metadata_.version); |
| 1630 std::unique_ptr<PendingUpgradeCall> pending_call = | 1631 std::unique_ptr<PendingUpgradeCall> pending_call = |
| 1631 std::move(pending_run_version_change_transaction_call_); | 1632 std::move(pending_run_version_change_transaction_call_); |
| 1632 RunVersionChangeTransactionFinal(pending_call->callbacks(), | 1633 RunVersionChangeTransactionFinal(pending_call->callbacks(), |
| 1633 pending_call->ReleaseConnection(), | 1634 pending_call->ReleaseConnection(), |
| 1634 pending_call->transaction_id(), | 1635 pending_call->transaction_id(), |
| 1635 pending_call->version()); | 1636 pending_call->version()); |
| 1636 DCHECK_EQ(1u, ConnectionCount()); | 1637 DCHECK_EQ(1u, ConnectionCount()); |
| 1637 // Fall through would be a no-op, since transaction must complete | 1638 // Fall through would be a no-op, since transaction must complete |
| 1638 // asynchronously. | 1639 // asynchronously. |
| 1640 DCHECK(IsUpgradeRunning()); |
| 1639 DCHECK(IsDeleteDatabaseBlocked()); | 1641 DCHECK(IsDeleteDatabaseBlocked()); |
| 1640 DCHECK(IsOpenConnectionBlocked()); | 1642 DCHECK(IsOpenConnectionBlocked()); |
| 1641 return; | 1643 return; |
| 1642 } | 1644 } |
| 1643 | 1645 |
| 1644 if (!IsDeleteDatabaseBlocked()) { | 1646 if (IsUpgradeRunning()) { |
| 1645 std::list<PendingDeleteCall*> pending_delete_calls; | 1647 DCHECK_EQ(ConnectionCount(), 1UL); |
| 1648 return; |
| 1649 } |
| 1650 |
| 1651 // These delete calls were blocked by a running upgrade, and did not even |
| 1652 // get as far as broadcasting OnVersionChange (if needed). |
| 1653 { |
| 1654 std::list<std::unique_ptr<PendingDeleteCall>> pending_delete_calls; |
| 1646 pending_delete_calls_.swap(pending_delete_calls); | 1655 pending_delete_calls_.swap(pending_delete_calls); |
| 1647 while (!pending_delete_calls.empty()) { | 1656 while (!pending_delete_calls.empty()) { |
| 1657 std::unique_ptr<PendingDeleteCall> pending_delete_call( |
| 1658 std::move(pending_delete_calls.front())); |
| 1659 pending_delete_calls.pop_front(); |
| 1660 DeleteDatabase(pending_delete_call->callbacks()); |
| 1661 } |
| 1662 // DeleteDatabase should never re-queue these calls. |
| 1663 DCHECK(pending_delete_calls_.empty()); |
| 1664 // Fall through when complete, as pending deletes/opens may be unblocked. |
| 1665 } |
| 1666 |
| 1667 // These delete calls broadcast OnVersionChange (if needed) but were blocked |
| 1668 // by open connections. |
| 1669 if (!IsDeleteDatabaseBlocked()) { |
| 1670 std::list<std::unique_ptr<PendingDeleteCall>> blocked_delete_calls; |
| 1671 blocked_delete_calls_.swap(blocked_delete_calls); |
| 1672 while (!blocked_delete_calls.empty()) { |
| 1648 // Only the first delete call will delete the database, but each must fire | 1673 // Only the first delete call will delete the database, but each must fire |
| 1649 // callbacks. | 1674 // callbacks. |
| 1650 std::unique_ptr<PendingDeleteCall> pending_delete_call( | 1675 std::unique_ptr<PendingDeleteCall> pending_delete_call( |
| 1651 pending_delete_calls.front()); | 1676 std::move(blocked_delete_calls.front())); |
| 1652 pending_delete_calls.pop_front(); | 1677 blocked_delete_calls.pop_front(); |
| 1653 DeleteDatabaseFinal(pending_delete_call->callbacks()); | 1678 DeleteDatabaseFinal(pending_delete_call->callbacks()); |
| 1654 } | 1679 } |
| 1655 // delete_database_final should never re-queue calls. | 1680 // DeleteDatabaseFinal should never re-queue these calls. |
| 1656 DCHECK(pending_delete_calls_.empty()); | 1681 DCHECK(blocked_delete_calls_.empty()); |
| 1657 // Fall through when complete, as pending opens may be unblocked. | 1682 // Fall through when complete, as pending opens may be unblocked. |
| 1658 } | 1683 } |
| 1659 | 1684 |
| 1685 // These open calls were blocked by a pending/running upgrade or a pending |
| 1686 // delete. |
| 1660 if (!IsOpenConnectionBlocked()) { | 1687 if (!IsOpenConnectionBlocked()) { |
| 1661 std::queue<IndexedDBPendingConnection> pending_open_calls; | 1688 std::queue<IndexedDBPendingConnection> pending_open_calls; |
| 1662 pending_open_calls_.swap(pending_open_calls); | 1689 pending_open_calls_.swap(pending_open_calls); |
| 1663 while (!pending_open_calls.empty()) { | 1690 while (!pending_open_calls.empty()) { |
| 1691 // This may re-queue open calls if an upgrade is necessary. |
| 1664 OpenConnection(pending_open_calls.front()); | 1692 OpenConnection(pending_open_calls.front()); |
| 1665 pending_open_calls.pop(); | 1693 pending_open_calls.pop(); |
| 1666 } | 1694 } |
| 1667 } | 1695 } |
| 1668 } | 1696 } |
| 1669 | 1697 |
| 1670 void IndexedDBDatabase::CreateTransaction( | 1698 void IndexedDBDatabase::CreateTransaction( |
| 1671 int64_t transaction_id, | 1699 int64_t transaction_id, |
| 1672 IndexedDBConnection* connection, | 1700 IndexedDBConnection* connection, |
| 1673 const std::vector<int64_t>& object_store_ids, | 1701 const std::vector<int64_t>& object_store_ids, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1687 TransactionCreated(IndexedDBClassFactory::Get()->CreateIndexedDBTransaction( | 1715 TransactionCreated(IndexedDBClassFactory::Get()->CreateIndexedDBTransaction( |
| 1688 transaction_id, connection->GetWeakPtr(), | 1716 transaction_id, connection->GetWeakPtr(), |
| 1689 std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), mode, | 1717 std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), mode, |
| 1690 new IndexedDBBackingStore::Transaction(backing_store_.get()))); | 1718 new IndexedDBBackingStore::Transaction(backing_store_.get()))); |
| 1691 } | 1719 } |
| 1692 | 1720 |
| 1693 void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) { | 1721 void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) { |
| 1694 transactions_[transaction->id()] = transaction; | 1722 transactions_[transaction->id()] = transaction; |
| 1695 } | 1723 } |
| 1696 | 1724 |
| 1725 bool IndexedDBDatabase::IsUpgradeRunning() const { |
| 1726 return transaction_coordinator_.IsRunningVersionChangeTransaction(); |
| 1727 } |
| 1728 |
| 1729 bool IndexedDBDatabase::IsUpgradePendingOrRunning() const { |
| 1730 return pending_run_version_change_transaction_call_ || IsUpgradeRunning(); |
| 1731 } |
| 1732 |
| 1697 bool IndexedDBDatabase::IsOpenConnectionBlocked() const { | 1733 bool IndexedDBDatabase::IsOpenConnectionBlocked() const { |
| 1698 return !pending_delete_calls_.empty() || | 1734 return IsUpgradePendingOrRunning() || !blocked_delete_calls_.empty(); |
| 1699 transaction_coordinator_.IsRunningVersionChangeTransaction() || | |
| 1700 pending_run_version_change_transaction_call_; | |
| 1701 } | 1735 } |
| 1702 | 1736 |
| 1703 void IndexedDBDatabase::OpenConnection( | 1737 void IndexedDBDatabase::OpenConnection( |
| 1704 const IndexedDBPendingConnection& connection) { | 1738 const IndexedDBPendingConnection& connection) { |
| 1705 DCHECK(backing_store_.get()); | 1739 DCHECK(backing_store_.get()); |
| 1706 | 1740 |
| 1707 // TODO(jsbell): Should have a priority queue so that higher version | |
| 1708 // requests are processed first. http://crbug.com/225850 | |
| 1709 if (IsOpenConnectionBlocked()) { | 1741 if (IsOpenConnectionBlocked()) { |
| 1710 // The backing store only detects data loss when it is first opened. The | 1742 // The backing store only detects data loss when it is first opened. The |
| 1711 // presence of existing connections means we didn't even check for data loss | 1743 // presence of existing connections means we didn't even check for data loss |
| 1712 // so there'd better not be any. | 1744 // so there'd better not be any. |
| 1713 DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss()); | 1745 DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss()); |
| 1714 pending_open_calls_.push(connection); | 1746 pending_open_calls_.push(connection); |
| 1715 return; | 1747 return; |
| 1716 } | 1748 } |
| 1717 | 1749 |
| 1718 if (metadata_.id == kInvalidId) { | 1750 if (metadata_.id == kInvalidId) { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1825 scoped_refptr<IndexedDBCallbacks> callbacks, | 1857 scoped_refptr<IndexedDBCallbacks> callbacks, |
| 1826 std::unique_ptr<IndexedDBConnection> connection, | 1858 std::unique_ptr<IndexedDBConnection> connection, |
| 1827 int64_t transaction_id, | 1859 int64_t transaction_id, |
| 1828 int64_t requested_version) { | 1860 int64_t requested_version) { |
| 1829 std::vector<int64_t> object_store_ids; | 1861 std::vector<int64_t> object_store_ids; |
| 1830 CreateTransaction(transaction_id, | 1862 CreateTransaction(transaction_id, |
| 1831 connection.get(), | 1863 connection.get(), |
| 1832 object_store_ids, | 1864 object_store_ids, |
| 1833 blink::WebIDBTransactionModeVersionChange); | 1865 blink::WebIDBTransactionModeVersionChange); |
| 1834 | 1866 |
| 1867 DCHECK(transaction_coordinator_.IsRunningVersionChangeTransaction()); |
| 1835 transactions_[transaction_id]->ScheduleTask( | 1868 transactions_[transaction_id]->ScheduleTask( |
| 1836 base::Bind(&IndexedDBDatabase::VersionChangeOperation, | 1869 base::Bind(&IndexedDBDatabase::VersionChangeOperation, |
| 1837 this, | 1870 this, |
| 1838 requested_version, | 1871 requested_version, |
| 1839 callbacks, | 1872 callbacks, |
| 1840 base::Passed(&connection))); | 1873 base::Passed(&connection))); |
| 1841 DCHECK(!pending_second_half_open_); | 1874 DCHECK(!pending_second_half_open_); |
| 1842 } | 1875 } |
| 1843 | 1876 |
| 1844 void IndexedDBDatabase::DeleteDatabase( | 1877 void IndexedDBDatabase::DeleteDatabase( |
| 1845 scoped_refptr<IndexedDBCallbacks> callbacks) { | 1878 scoped_refptr<IndexedDBCallbacks> callbacks) { |
| 1879 // If there's a running upgrade, the delete calls should be deferred so that |
| 1880 // "versionchange" is seen after "success" fires. |
| 1881 if (IsUpgradeRunning()) { |
| 1882 pending_delete_calls_.push_back( |
| 1883 std::unique_ptr<PendingDeleteCall>(new PendingDeleteCall(callbacks))); |
| 1884 return; |
| 1885 } |
| 1846 | 1886 |
| 1847 if (IsDeleteDatabaseBlocked()) { | 1887 if (IsDeleteDatabaseBlocked()) { |
| 1848 for (const auto* connection : connections_) { | 1888 for (const auto* connection : connections_) { |
| 1849 // Front end ensures the event is not fired at connections that have | 1889 // Front end ensures the event is not fired at connections that have |
| 1850 // close_pending set. | 1890 // close_pending set. |
| 1851 connection->callbacks()->OnVersionChange( | 1891 connection->callbacks()->OnVersionChange( |
| 1852 metadata_.version, IndexedDBDatabaseMetadata::NO_VERSION); | 1892 metadata_.version, IndexedDBDatabaseMetadata::NO_VERSION); |
| 1853 } | 1893 } |
| 1854 // OnBlocked will be fired at the request when one of the other | 1894 // OnBlocked will be fired at the request when one of the other |
| 1855 // connections acks that the OnVersionChange was ignored. | 1895 // connections acks that the OnVersionChange was ignored. |
| 1856 | 1896 |
| 1857 pending_delete_calls_.push_back(new PendingDeleteCall(callbacks)); | 1897 blocked_delete_calls_.push_back( |
| 1898 std::unique_ptr<PendingDeleteCall>(new PendingDeleteCall(callbacks))); |
| 1858 return; | 1899 return; |
| 1859 } | 1900 } |
| 1860 DeleteDatabaseFinal(callbacks); | 1901 DeleteDatabaseFinal(callbacks); |
| 1861 } | 1902 } |
| 1862 | 1903 |
| 1863 bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const { | 1904 bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const { |
| 1864 return !!ConnectionCount(); | 1905 return IsUpgradePendingOrRunning() || !!ConnectionCount(); |
| 1865 } | 1906 } |
| 1866 | 1907 |
| 1867 void IndexedDBDatabase::DeleteDatabaseFinal( | 1908 void IndexedDBDatabase::DeleteDatabaseFinal( |
| 1868 scoped_refptr<IndexedDBCallbacks> callbacks) { | 1909 scoped_refptr<IndexedDBCallbacks> callbacks) { |
| 1869 DCHECK(!IsDeleteDatabaseBlocked()); | 1910 DCHECK(!IsDeleteDatabaseBlocked()); |
| 1870 DCHECK(backing_store_.get()); | 1911 DCHECK(backing_store_.get()); |
| 1871 leveldb::Status s = backing_store_->DeleteDatabase(metadata_.name); | 1912 leveldb::Status s = backing_store_->DeleteDatabase(metadata_.name); |
| 1872 if (!s.ok()) { | 1913 if (!s.ok()) { |
| 1873 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1914 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1874 "Internal error deleting database."); | 1915 "Internal error deleting database."); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1893 scoped_refptr<IndexedDBDatabase> protect(this); | 1934 scoped_refptr<IndexedDBDatabase> protect(this); |
| 1894 ConnectionSet::const_iterator it = connections_.begin(); | 1935 ConnectionSet::const_iterator it = connections_.begin(); |
| 1895 while (it != connections_.end()) { | 1936 while (it != connections_.end()) { |
| 1896 IndexedDBConnection* connection = *it++; | 1937 IndexedDBConnection* connection = *it++; |
| 1897 connection->ForceClose(); | 1938 connection->ForceClose(); |
| 1898 } | 1939 } |
| 1899 DCHECK(connections_.empty()); | 1940 DCHECK(connections_.empty()); |
| 1900 } | 1941 } |
| 1901 | 1942 |
| 1902 void IndexedDBDatabase::VersionChangeIgnored() { | 1943 void IndexedDBDatabase::VersionChangeIgnored() { |
| 1903 if (pending_run_version_change_transaction_call_) | 1944 if (pending_run_version_change_transaction_call_) { |
| 1904 pending_run_version_change_transaction_call_->callbacks()->OnBlocked( | 1945 pending_run_version_change_transaction_call_->callbacks()->OnBlocked( |
| 1905 metadata_.version); | 1946 metadata_.version); |
| 1947 } |
| 1906 | 1948 |
| 1907 for (const auto& pending_delete_call : pending_delete_calls_) | 1949 for (const auto& pending_delete_call : blocked_delete_calls_) |
| 1908 pending_delete_call->callbacks()->OnBlocked(metadata_.version); | 1950 pending_delete_call->callbacks()->OnBlocked(metadata_.version); |
| 1909 } | 1951 } |
| 1910 | 1952 |
| 1911 | |
| 1912 void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) { | 1953 void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) { |
| 1913 DCHECK(connections_.count(connection)); | 1954 DCHECK(connections_.count(connection)); |
| 1914 DCHECK(connection->IsConnected()); | 1955 DCHECK(connection->IsConnected()); |
| 1915 DCHECK(connection->database() == this); | 1956 DCHECK(connection->database() == this); |
| 1916 | 1957 |
| 1917 IDB_TRACE("IndexedDBDatabase::Close"); | 1958 IDB_TRACE("IndexedDBDatabase::Close"); |
| 1918 | 1959 |
| 1919 connections_.erase(connection); | 1960 connections_.erase(connection); |
| 1920 | 1961 |
| 1921 // Abort outstanding transactions from the closing connection. This | 1962 // Abort outstanding transactions from the closing connection. This |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1937 pending_second_half_open_->callbacks()->OnError( | 1978 pending_second_half_open_->callbacks()->OnError( |
| 1938 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError, | 1979 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError, |
| 1939 "The connection was closed.")); | 1980 "The connection was closed.")); |
| 1940 pending_second_half_open_.reset(); | 1981 pending_second_half_open_.reset(); |
| 1941 } | 1982 } |
| 1942 | 1983 |
| 1943 ProcessPendingCalls(); | 1984 ProcessPendingCalls(); |
| 1944 | 1985 |
| 1945 // TODO(jsbell): Add a test for the pending_open_calls_ cases below. | 1986 // TODO(jsbell): Add a test for the pending_open_calls_ cases below. |
| 1946 if (!ConnectionCount() && pending_open_calls_.empty() && | 1987 if (!ConnectionCount() && pending_open_calls_.empty() && |
| 1947 pending_delete_calls_.empty()) { | 1988 blocked_delete_calls_.empty()) { |
| 1948 DCHECK(transactions_.empty()); | 1989 DCHECK(transactions_.empty()); |
| 1949 backing_store_ = NULL; | 1990 backing_store_ = NULL; |
| 1950 factory_->ReleaseDatabase(identifier_, forced); | 1991 factory_->ReleaseDatabase(identifier_, forced); |
| 1951 } | 1992 } |
| 1952 } | 1993 } |
| 1953 | 1994 |
| 1954 void IndexedDBDatabase::CreateObjectStoreAbortOperation( | 1995 void IndexedDBDatabase::CreateObjectStoreAbortOperation( |
| 1955 int64_t object_store_id, | 1996 int64_t object_store_id, |
| 1956 IndexedDBTransaction* transaction) { | 1997 IndexedDBTransaction* transaction) { |
| 1957 DCHECK(!transaction); | 1998 DCHECK(!transaction); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1970 | 2011 |
| 1971 void IndexedDBDatabase::VersionChangeAbortOperation( | 2012 void IndexedDBDatabase::VersionChangeAbortOperation( |
| 1972 int64_t previous_version, | 2013 int64_t previous_version, |
| 1973 IndexedDBTransaction* transaction) { | 2014 IndexedDBTransaction* transaction) { |
| 1974 DCHECK(!transaction); | 2015 DCHECK(!transaction); |
| 1975 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); | 2016 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); |
| 1976 metadata_.version = previous_version; | 2017 metadata_.version = previous_version; |
| 1977 } | 2018 } |
| 1978 | 2019 |
| 1979 } // namespace content | 2020 } // namespace content |
| OLD | NEW |