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 11 matching lines...) Expand all Loading... |
22 #include "base/stl_util.h" | 22 #include "base/stl_util.h" |
23 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" |
24 #include "base/strings/utf_string_conversions.h" | 24 #include "base/strings/utf_string_conversions.h" |
25 #include "content/browser/indexed_db/indexed_db_blob_info.h" | 25 #include "content/browser/indexed_db/indexed_db_blob_info.h" |
26 #include "content/browser/indexed_db/indexed_db_class_factory.h" | 26 #include "content/browser/indexed_db/indexed_db_class_factory.h" |
27 #include "content/browser/indexed_db/indexed_db_connection.h" | 27 #include "content/browser/indexed_db/indexed_db_connection.h" |
28 #include "content/browser/indexed_db/indexed_db_context_impl.h" | 28 #include "content/browser/indexed_db/indexed_db_context_impl.h" |
29 #include "content/browser/indexed_db/indexed_db_cursor.h" | 29 #include "content/browser/indexed_db/indexed_db_cursor.h" |
30 #include "content/browser/indexed_db/indexed_db_factory.h" | 30 #include "content/browser/indexed_db/indexed_db_factory.h" |
31 #include "content/browser/indexed_db/indexed_db_index_writer.h" | 31 #include "content/browser/indexed_db/indexed_db_index_writer.h" |
| 32 #include "content/browser/indexed_db/indexed_db_observation.h" |
| 33 #include "content/browser/indexed_db/indexed_db_observer_changes.h" |
32 #include "content/browser/indexed_db/indexed_db_pending_connection.h" | 34 #include "content/browser/indexed_db/indexed_db_pending_connection.h" |
33 #include "content/browser/indexed_db/indexed_db_return_value.h" | 35 #include "content/browser/indexed_db/indexed_db_return_value.h" |
34 #include "content/browser/indexed_db/indexed_db_tracing.h" | 36 #include "content/browser/indexed_db/indexed_db_tracing.h" |
35 #include "content/browser/indexed_db/indexed_db_transaction.h" | 37 #include "content/browser/indexed_db/indexed_db_transaction.h" |
36 #include "content/browser/indexed_db/indexed_db_value.h" | 38 #include "content/browser/indexed_db/indexed_db_value.h" |
37 #include "content/common/indexed_db/indexed_db_constants.h" | 39 #include "content/common/indexed_db/indexed_db_constants.h" |
38 #include "content/common/indexed_db/indexed_db_key_path.h" | 40 #include "content/common/indexed_db/indexed_db_key_path.h" |
39 #include "content/common/indexed_db/indexed_db_key_range.h" | 41 #include "content/common/indexed_db/indexed_db_key_range.h" |
40 #include "content/public/common/content_switches.h" | 42 #include "content/public/common/content_switches.h" |
41 #include "storage/browser/blob/blob_data_handle.h" | 43 #include "storage/browser/blob/blob_data_handle.h" |
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 const IndexedDBDatabaseError& error) { | 756 const IndexedDBDatabaseError& error) { |
755 IDB_TRACE1("IndexedDBDatabase::Abort(error)", "txn.id", transaction_id); | 757 IDB_TRACE1("IndexedDBDatabase::Abort(error)", "txn.id", transaction_id); |
756 // If the transaction is unknown, then it has already been aborted by the | 758 // If the transaction is unknown, then it has already been aborted by the |
757 // backend before this call so it is safe to ignore it. | 759 // backend before this call so it is safe to ignore it. |
758 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 760 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
759 if (transaction) | 761 if (transaction) |
760 transaction->Abort(error); | 762 transaction->Abort(error); |
761 } | 763 } |
762 | 764 |
763 void IndexedDBDatabase::AddPendingObserver(int64_t transaction_id, | 765 void IndexedDBDatabase::AddPendingObserver(int64_t transaction_id, |
764 int32_t observer_id) { | 766 int32_t observer_id, |
| 767 IndexedDBObserver::Options options) { |
765 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 768 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
766 if (!transaction) | 769 if (!transaction) |
767 return; | 770 return; |
768 transaction->AddPendingObserver(observer_id); | 771 transaction->AddPendingObserver(observer_id, options); |
769 } | 772 } |
770 | 773 |
771 void IndexedDBDatabase::RemovePendingObservers( | 774 void IndexedDBDatabase::RemovePendingObservers( |
772 IndexedDBConnection* connection, | 775 IndexedDBConnection* connection, |
773 const std::vector<int32_t>& pending_observer_ids) { | 776 const std::vector<int32_t>& pending_observer_ids) { |
774 for (const auto& it : transactions_) { | 777 for (const auto& it : transactions_) { |
775 // Avoid call to RemovePendingObservers for transactions on other | 778 // Avoid call to RemovePendingObservers for transactions on other |
776 // connections. | 779 // connections. |
777 if (it.second->connection() == connection) | 780 if (it.second->connection() == connection) |
778 it.second->RemovePendingObservers(pending_observer_ids); | 781 it.second->RemovePendingObservers(pending_observer_ids); |
779 } | 782 } |
780 } | 783 } |
781 | 784 |
| 785 // TODO(palakj): Augment the function with IDBValue later. Issue |
| 786 // crbug.com/609934. |
| 787 void IndexedDBDatabase::FilterObservation(IndexedDBTransaction* transaction, |
| 788 int64_t object_store_id, |
| 789 blink::WebIDBOperationType type, |
| 790 const IndexedDBKeyRange& key_range) { |
| 791 for (const auto& connection : connections_) { |
| 792 bool recorded = false; |
| 793 for (const auto& observer : connection->active_observers()) { |
| 794 if (!observer->IsRecordingType(type) || |
| 795 !observer->IsRecordingObjectStore(object_store_id)) |
| 796 continue; |
| 797 if (!recorded) { |
| 798 if (type == blink::WebIDBClear) { |
| 799 transaction->AddObservation(connection->id(), |
| 800 base::WrapUnique(new IndexedDBObservation( |
| 801 object_store_id, type))); |
| 802 } else { |
| 803 transaction->AddObservation(connection->id(), |
| 804 base::WrapUnique(new IndexedDBObservation( |
| 805 object_store_id, type, key_range))); |
| 806 } |
| 807 recorded = true; |
| 808 } |
| 809 transaction->RecordObserverForLastObservation(connection->id(), |
| 810 observer->id()); |
| 811 } |
| 812 } |
| 813 } |
| 814 |
| 815 void IndexedDBDatabase::SendObservations( |
| 816 std::map<int32_t, std::unique_ptr<IndexedDBObserverChanges>> changes_map) { |
| 817 for (const auto& conn : connections_) { |
| 818 auto it = changes_map.find(conn->id()); |
| 819 if (it != changes_map.end()) |
| 820 conn->callbacks()->OnDatabaseChange(it->first, std::move(it->second)); |
| 821 } |
| 822 } |
| 823 |
782 void IndexedDBDatabase::GetAll(int64_t transaction_id, | 824 void IndexedDBDatabase::GetAll(int64_t transaction_id, |
783 int64_t object_store_id, | 825 int64_t object_store_id, |
784 int64_t index_id, | 826 int64_t index_id, |
785 std::unique_ptr<IndexedDBKeyRange> key_range, | 827 std::unique_ptr<IndexedDBKeyRange> key_range, |
786 bool key_only, | 828 bool key_only, |
787 int64_t max_count, | 829 int64_t max_count, |
788 scoped_refptr<IndexedDBCallbacks> callbacks) { | 830 scoped_refptr<IndexedDBCallbacks> callbacks) { |
789 IDB_TRACE1("IndexedDBDatabase::GetAll", "txn.id", transaction_id); | 831 IDB_TRACE1("IndexedDBDatabase::GetAll", "txn.id", transaction_id); |
790 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 832 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
791 if (!transaction) | 833 if (!transaction) |
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1326 if (s.IsCorruption()) | 1368 if (s.IsCorruption()) |
1327 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | 1369 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); |
1328 return; | 1370 return; |
1329 } | 1371 } |
1330 } | 1372 } |
1331 { | 1373 { |
1332 IDB_TRACE1("IndexedDBDatabase::PutOperation.Callbacks", "txn.id", | 1374 IDB_TRACE1("IndexedDBDatabase::PutOperation.Callbacks", "txn.id", |
1333 transaction->id()); | 1375 transaction->id()); |
1334 params->callbacks->OnSuccess(*key); | 1376 params->callbacks->OnSuccess(*key); |
1335 } | 1377 } |
| 1378 FilterObservation(transaction, params->object_store_id, |
| 1379 params->put_mode == blink::WebIDBPutModeAddOnly |
| 1380 ? blink::WebIDBAdd |
| 1381 : blink::WebIDBPut, |
| 1382 IndexedDBKeyRange(*key)); |
1336 } | 1383 } |
1337 | 1384 |
1338 void IndexedDBDatabase::SetIndexKeys(int64_t transaction_id, | 1385 void IndexedDBDatabase::SetIndexKeys(int64_t transaction_id, |
1339 int64_t object_store_id, | 1386 int64_t object_store_id, |
1340 std::unique_ptr<IndexedDBKey> primary_key, | 1387 std::unique_ptr<IndexedDBKey> primary_key, |
1341 const std::vector<IndexKeys>& index_keys) { | 1388 const std::vector<IndexKeys>& index_keys) { |
1342 IDB_TRACE1("IndexedDBDatabase::SetIndexKeys", "txn.id", transaction_id); | 1389 IDB_TRACE1("IndexedDBDatabase::SetIndexKeys", "txn.id", transaction_id); |
1343 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 1390 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
1344 if (!transaction) | 1391 if (!transaction) |
1345 return; | 1392 return; |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1669 if (s.IsCorruption()) { | 1716 if (s.IsCorruption()) { |
1670 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | 1717 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); |
1671 } | 1718 } |
1672 return; | 1719 return; |
1673 } | 1720 } |
1674 if (experimental_web_platform_features_enabled_) { | 1721 if (experimental_web_platform_features_enabled_) { |
1675 callbacks->OnSuccess(base::checked_cast<int64_t>(delete_count)); | 1722 callbacks->OnSuccess(base::checked_cast<int64_t>(delete_count)); |
1676 } else { | 1723 } else { |
1677 callbacks->OnSuccess(); | 1724 callbacks->OnSuccess(); |
1678 } | 1725 } |
| 1726 FilterObservation(transaction, object_store_id, blink::WebIDBDelete, |
| 1727 *key_range); |
1679 } | 1728 } |
1680 | 1729 |
1681 void IndexedDBDatabase::Clear(int64_t transaction_id, | 1730 void IndexedDBDatabase::Clear(int64_t transaction_id, |
1682 int64_t object_store_id, | 1731 int64_t object_store_id, |
1683 scoped_refptr<IndexedDBCallbacks> callbacks) { | 1732 scoped_refptr<IndexedDBCallbacks> callbacks) { |
1684 IDB_TRACE1("IndexedDBDatabase::Clear", "txn.id", transaction_id); | 1733 IDB_TRACE1("IndexedDBDatabase::Clear", "txn.id", transaction_id); |
1685 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 1734 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
1686 if (!transaction) | 1735 if (!transaction) |
1687 return; | 1736 return; |
1688 DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly); | 1737 DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly); |
(...skipping 15 matching lines...) Expand all Loading... |
1704 if (!s.ok()) { | 1753 if (!s.ok()) { |
1705 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1754 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
1706 "Internal error clearing object store"); | 1755 "Internal error clearing object store"); |
1707 callbacks->OnError(error); | 1756 callbacks->OnError(error); |
1708 if (s.IsCorruption()) { | 1757 if (s.IsCorruption()) { |
1709 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | 1758 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); |
1710 } | 1759 } |
1711 return; | 1760 return; |
1712 } | 1761 } |
1713 callbacks->OnSuccess(); | 1762 callbacks->OnSuccess(); |
| 1763 |
| 1764 FilterObservation(transaction, object_store_id, blink::WebIDBClear, |
| 1765 IndexedDBKeyRange()); |
1714 } | 1766 } |
1715 | 1767 |
1716 void IndexedDBDatabase::DeleteObjectStoreOperation( | 1768 void IndexedDBDatabase::DeleteObjectStoreOperation( |
1717 int64_t object_store_id, | 1769 int64_t object_store_id, |
1718 IndexedDBTransaction* transaction) { | 1770 IndexedDBTransaction* transaction) { |
1719 IDB_TRACE1("IndexedDBDatabase::DeleteObjectStoreOperation", | 1771 IDB_TRACE1("IndexedDBDatabase::DeleteObjectStoreOperation", |
1720 "txn.id", | 1772 "txn.id", |
1721 transaction->id()); | 1773 transaction->id()); |
1722 | 1774 |
1723 const IndexedDBObjectStoreMetadata object_store_metadata = | 1775 const IndexedDBObjectStoreMetadata object_store_metadata = |
(...skipping 17 matching lines...) Expand all Loading... |
1741 RemoveObjectStore(object_store_id); | 1793 RemoveObjectStore(object_store_id); |
1742 transaction->ScheduleAbortTask( | 1794 transaction->ScheduleAbortTask( |
1743 base::Bind(&IndexedDBDatabase::DeleteObjectStoreAbortOperation, | 1795 base::Bind(&IndexedDBDatabase::DeleteObjectStoreAbortOperation, |
1744 this, | 1796 this, |
1745 object_store_metadata)); | 1797 object_store_metadata)); |
1746 } | 1798 } |
1747 | 1799 |
1748 void IndexedDBDatabase::VersionChangeOperation( | 1800 void IndexedDBDatabase::VersionChangeOperation( |
1749 int64_t version, | 1801 int64_t version, |
1750 scoped_refptr<IndexedDBCallbacks> callbacks, | 1802 scoped_refptr<IndexedDBCallbacks> callbacks, |
| 1803 std::unique_ptr<IndexedDBConnection> connection, |
1751 IndexedDBTransaction* transaction) { | 1804 IndexedDBTransaction* transaction) { |
1752 IDB_TRACE1( | 1805 IDB_TRACE1( |
1753 "IndexedDBDatabase::VersionChangeOperation", "txn.id", transaction->id()); | 1806 "IndexedDBDatabase::VersionChangeOperation", "txn.id", transaction->id()); |
1754 int64_t old_version = metadata_.version; | 1807 int64_t old_version = metadata_.version; |
1755 DCHECK_GT(version, old_version); | 1808 DCHECK_GT(version, old_version); |
1756 | 1809 |
1757 if (!backing_store_->UpdateIDBDatabaseIntVersion( | 1810 if (!backing_store_->UpdateIDBDatabaseIntVersion( |
1758 transaction->BackingStoreTransaction(), id(), version)) { | 1811 transaction->BackingStoreTransaction(), id(), version)) { |
1759 IndexedDBDatabaseError error( | 1812 IndexedDBDatabaseError error( |
1760 blink::WebIDBDatabaseExceptionUnknownError, | 1813 blink::WebIDBDatabaseExceptionUnknownError, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1815 if (!pending_requests_.empty()) | 1868 if (!pending_requests_.empty()) |
1816 ProcessRequestQueue(); | 1869 ProcessRequestQueue(); |
1817 } | 1870 } |
1818 | 1871 |
1819 void IndexedDBDatabase::ProcessRequestQueue() { | 1872 void IndexedDBDatabase::ProcessRequestQueue() { |
1820 // Don't run re-entrantly to avoid exploding call stacks for requests that | 1873 // Don't run re-entrantly to avoid exploding call stacks for requests that |
1821 // complete synchronously. The loop below will process requests until one is | 1874 // complete synchronously. The loop below will process requests until one is |
1822 // blocked. | 1875 // blocked. |
1823 if (processing_pending_requests_) | 1876 if (processing_pending_requests_) |
1824 return; | 1877 return; |
| 1878 } |
1825 | 1879 |
1826 DCHECK(!active_request_); | 1880 DCHECK(!active_request_); |
1827 DCHECK(!pending_requests_.empty()); | 1881 DCHECK(!pending_requests_.empty()); |
1828 | 1882 |
1829 base::AutoReset<bool> processing(&processing_pending_requests_, true); | 1883 base::AutoReset<bool> processing(&processing_pending_requests_, true); |
1830 do { | 1884 do { |
1831 active_request_ = std::move(pending_requests_.front()); | 1885 active_request_ = std::move(pending_requests_.front()); |
1832 pending_requests_.pop(); | 1886 pending_requests_.pop(); |
1833 active_request_->Perform(); | 1887 active_request_->Perform(); |
1834 // If the active request completed synchronously, keep going. | 1888 // If the active request completed synchronously, keep going. |
1835 } while (!active_request_ && !pending_requests_.empty()); | 1889 } while (!active_request_ && !pending_requests_.empty()); |
1836 } | 1890 } |
1837 | 1891 |
1838 IndexedDBTransaction* IndexedDBDatabase::CreateTransaction( | 1892 IndexedDBTransaction* IndexedDBDatabase::CreateTransaction( |
1839 int64_t transaction_id, | 1893 int64_t transaction_id, |
1840 IndexedDBConnection* connection, | 1894 IndexedDBConnection* connection, |
1841 const std::vector<int64_t>& object_store_ids, | 1895 const std::vector<int64_t>& object_store_ids, |
1842 blink::WebIDBTransactionMode mode) { | 1896 blink::WebIDBTransactionMode mode) { |
1843 IDB_TRACE1("IndexedDBDatabase::CreateTransaction", "txn.id", transaction_id); | 1897 IDB_TRACE1("IndexedDBDatabase::CreateTransaction", "txn.id", transaction_id); |
1844 DCHECK(connections_.count(connection)); | 1898 DCHECK(connections_.count(connection)); |
(...skipping 13 matching lines...) Expand all Loading... |
1858 std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), | 1912 std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), |
1859 mode, new IndexedDBBackingStore::Transaction(backing_store_.get())); | 1913 mode, new IndexedDBBackingStore::Transaction(backing_store_.get())); |
1860 TransactionCreated(transaction); | 1914 TransactionCreated(transaction); |
1861 return transaction; | 1915 return transaction; |
1862 } | 1916 } |
1863 | 1917 |
1864 void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) { | 1918 void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) { |
1865 transactions_[transaction->id()] = transaction; | 1919 transactions_[transaction->id()] = transaction; |
1866 } | 1920 } |
1867 | 1921 |
| 1922 bool IndexedDBDatabase::IsOpenConnectionBlocked() const { |
| 1923 return !pending_delete_calls_.empty() || |
| 1924 transaction_coordinator_.IsRunningVersionChangeTransaction() || |
| 1925 pending_run_version_change_transaction_call_; |
| 1926 } |
| 1927 |
1868 void IndexedDBDatabase::OpenConnection( | 1928 void IndexedDBDatabase::OpenConnection( |
1869 const IndexedDBPendingConnection& connection) { | 1929 const IndexedDBPendingConnection& connection) { |
1870 AppendRequest(base::MakeUnique<OpenRequest>(this, connection)); | 1930 AppendRequest(base::MakeUnique<OpenRequest>(this, connection)); |
1871 } | 1931 } |
1872 | 1932 |
1873 void IndexedDBDatabase::DeleteDatabase( | 1933 void IndexedDBDatabase::DeleteDatabase( |
1874 scoped_refptr<IndexedDBCallbacks> callbacks) { | 1934 scoped_refptr<IndexedDBCallbacks> callbacks) { |
1875 AppendRequest(base::MakeUnique<DeleteRequest>(this, callbacks)); | 1935 AppendRequest(base::MakeUnique<DeleteRequest>(this, callbacks)); |
1876 } | 1936 } |
1877 | 1937 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1952 | 2012 |
1953 void IndexedDBDatabase::VersionChangeAbortOperation( | 2013 void IndexedDBDatabase::VersionChangeAbortOperation( |
1954 int64_t previous_version, | 2014 int64_t previous_version, |
1955 IndexedDBTransaction* transaction) { | 2015 IndexedDBTransaction* transaction) { |
1956 DCHECK(!transaction); | 2016 DCHECK(!transaction); |
1957 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); | 2017 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); |
1958 metadata_.version = previous_version; | 2018 metadata_.version = previous_version; |
1959 } | 2019 } |
1960 | 2020 |
1961 } // namespace content | 2021 } // namespace content |
OLD | NEW |