| 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 <set> | 10 #include <set> |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #include "storage/browser/blob/blob_data_handle.h" | 37 #include "storage/browser/blob/blob_data_handle.h" |
| 38 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc
eption.h" | 38 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc
eption.h" |
| 39 #include "third_party/leveldatabase/env_chromium.h" | 39 #include "third_party/leveldatabase/env_chromium.h" |
| 40 #include "url/origin.h" | 40 #include "url/origin.h" |
| 41 | 41 |
| 42 using base::ASCIIToUTF16; | 42 using base::ASCIIToUTF16; |
| 43 using base::Int64ToString16; | 43 using base::Int64ToString16; |
| 44 using blink::WebIDBKeyTypeNumber; | 44 using blink::WebIDBKeyTypeNumber; |
| 45 | 45 |
| 46 namespace content { | 46 namespace content { |
| 47 | |
| 48 namespace { | 47 namespace { |
| 49 | 48 |
| 50 // Used for WebCore.IndexedDB.Schema.ObjectStore.KeyPathType and | 49 // Used for WebCore.IndexedDB.Schema.ObjectStore.KeyPathType and |
| 51 // WebCore.IndexedDB.Schema.Index.KeyPathType histograms. Do not | 50 // WebCore.IndexedDB.Schema.Index.KeyPathType histograms. Do not |
| 52 // modify (delete, re-order, renumber) these values other than | 51 // modify (delete, re-order, renumber) these values other than |
| 53 // the _MAX value. | 52 // the _MAX value. |
| 54 enum HistogramIDBKeyPathType { | 53 enum HistogramIDBKeyPathType { |
| 55 KEY_PATH_TYPE_NONE = 0, | 54 KEY_PATH_TYPE_NONE = 0, |
| 56 KEY_PATH_TYPE_STRING = 1, | 55 KEY_PATH_TYPE_STRING = 1, |
| 57 KEY_PATH_TYPE_ARRAY = 2, | 56 KEY_PATH_TYPE_ARRAY = 2, |
| (...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 } | 701 } |
| 703 | 702 |
| 704 AddIndex(object_store_id, index_metadata, index_id); | 703 AddIndex(object_store_id, index_metadata, index_id); |
| 705 transaction->ScheduleAbortTask( | 704 transaction->ScheduleAbortTask( |
| 706 base::Bind(&IndexedDBDatabase::CreateIndexAbortOperation, | 705 base::Bind(&IndexedDBDatabase::CreateIndexAbortOperation, |
| 707 this, | 706 this, |
| 708 object_store_id, | 707 object_store_id, |
| 709 index_id)); | 708 index_id)); |
| 710 } | 709 } |
| 711 | 710 |
| 712 void IndexedDBDatabase::CreateIndexAbortOperation( | 711 void IndexedDBDatabase::CreateIndexAbortOperation(int64_t object_store_id, |
| 713 int64_t object_store_id, | 712 int64_t index_id) { |
| 714 int64_t index_id, | |
| 715 IndexedDBTransaction* transaction) { | |
| 716 DCHECK(!transaction); | |
| 717 IDB_TRACE("IndexedDBDatabase::CreateIndexAbortOperation"); | 713 IDB_TRACE("IndexedDBDatabase::CreateIndexAbortOperation"); |
| 718 RemoveIndex(object_store_id, index_id); | 714 RemoveIndex(object_store_id, index_id); |
| 719 } | 715 } |
| 720 | 716 |
| 721 void IndexedDBDatabase::DeleteIndex(int64_t transaction_id, | 717 void IndexedDBDatabase::DeleteIndex(int64_t transaction_id, |
| 722 int64_t object_store_id, | 718 int64_t object_store_id, |
| 723 int64_t index_id) { | 719 int64_t index_id) { |
| 724 IDB_TRACE1("IndexedDBDatabase::DeleteIndex", "txn.id", transaction_id); | 720 IDB_TRACE1("IndexedDBDatabase::DeleteIndex", "txn.id", transaction_id); |
| 725 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 721 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
| 726 if (!transaction) | 722 if (!transaction) |
| 727 return; | 723 return; |
| 728 DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange); | 724 DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange); |
| 729 | 725 |
| 730 if (!ValidateObjectStoreIdAndIndexId(object_store_id, index_id)) | 726 if (!ValidateObjectStoreIdAndIndexId(object_store_id, index_id)) |
| 731 return; | 727 return; |
| 732 | 728 |
| 733 transaction->ScheduleTask( | 729 transaction->ScheduleTask( |
| 734 base::Bind(&IndexedDBDatabase::DeleteIndexOperation, | 730 base::Bind(&IndexedDBDatabase::DeleteIndexOperation, |
| 735 this, | 731 this, |
| 736 object_store_id, | 732 object_store_id, |
| 737 index_id)); | 733 index_id)); |
| 738 } | 734 } |
| 739 | 735 |
| 740 void IndexedDBDatabase::DeleteIndexOperation( | 736 leveldb::Status IndexedDBDatabase::DeleteIndexOperation( |
| 741 int64_t object_store_id, | 737 int64_t object_store_id, |
| 742 int64_t index_id, | 738 int64_t index_id, |
| 743 IndexedDBTransaction* transaction) { | 739 IndexedDBTransaction* transaction) { |
| 744 IDB_TRACE1( | 740 IDB_TRACE1( |
| 745 "IndexedDBDatabase::DeleteIndexOperation", "txn.id", transaction->id()); | 741 "IndexedDBDatabase::DeleteIndexOperation", "txn.id", transaction->id()); |
| 746 | 742 |
| 747 const IndexedDBIndexMetadata index_metadata = | 743 const IndexedDBIndexMetadata index_metadata = |
| 748 metadata_.object_stores[object_store_id].indexes[index_id]; | 744 metadata_.object_stores[object_store_id].indexes[index_id]; |
| 749 | 745 |
| 750 leveldb::Status s = | 746 leveldb::Status s = |
| 751 backing_store_->DeleteIndex(transaction->BackingStoreTransaction(), | 747 backing_store_->DeleteIndex(transaction->BackingStoreTransaction(), |
| 752 transaction->database()->id(), | 748 transaction->database()->id(), |
| 753 object_store_id, | 749 object_store_id, |
| 754 index_id); | 750 index_id); |
| 755 if (!s.ok()) { | 751 if (!s.ok()) { |
| 756 base::string16 error_string = | 752 base::string16 error_string = |
| 757 ASCIIToUTF16("Internal error deleting index '") + | 753 ASCIIToUTF16("Internal error deleting index '") + |
| 758 index_metadata.name + ASCIIToUTF16("'."); | 754 index_metadata.name + ASCIIToUTF16("'."); |
| 759 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 755 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 760 error_string); | 756 error_string); |
| 761 transaction->Abort(error); | 757 transaction->Abort(error); |
| 762 if (s.IsCorruption()) | 758 return s; |
| 763 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 764 return; | |
| 765 } | 759 } |
| 766 | 760 |
| 767 RemoveIndex(object_store_id, index_id); | 761 RemoveIndex(object_store_id, index_id); |
| 768 transaction->ScheduleAbortTask( | 762 transaction->ScheduleAbortTask( |
| 769 base::Bind(&IndexedDBDatabase::DeleteIndexAbortOperation, | 763 base::Bind(&IndexedDBDatabase::DeleteIndexAbortOperation, |
| 770 this, | 764 this, |
| 771 object_store_id, | 765 object_store_id, |
| 772 index_metadata)); | 766 index_metadata)); |
| 767 return s; |
| 773 } | 768 } |
| 774 | 769 |
| 775 void IndexedDBDatabase::DeleteIndexAbortOperation( | 770 void IndexedDBDatabase::DeleteIndexAbortOperation( |
| 776 int64_t object_store_id, | 771 int64_t object_store_id, |
| 777 const IndexedDBIndexMetadata& index_metadata, | 772 const IndexedDBIndexMetadata& index_metadata) { |
| 778 IndexedDBTransaction* transaction) { | |
| 779 DCHECK(!transaction); | |
| 780 IDB_TRACE("IndexedDBDatabase::DeleteIndexAbortOperation"); | 773 IDB_TRACE("IndexedDBDatabase::DeleteIndexAbortOperation"); |
| 781 AddIndex(object_store_id, index_metadata, IndexedDBIndexMetadata::kInvalidId); | 774 AddIndex(object_store_id, index_metadata, IndexedDBIndexMetadata::kInvalidId); |
| 782 } | 775 } |
| 783 | 776 |
| 784 void IndexedDBDatabase::RenameIndex(int64_t transaction_id, | 777 void IndexedDBDatabase::RenameIndex(int64_t transaction_id, |
| 785 int64_t object_store_id, | 778 int64_t object_store_id, |
| 786 int64_t index_id, | 779 int64_t index_id, |
| 787 const base::string16& new_name) { | 780 const base::string16& new_name) { |
| 788 IDB_TRACE1("IndexedDBDatabase::RenameIndex", "txn.id", transaction_id); | 781 IDB_TRACE1("IndexedDBDatabase::RenameIndex", "txn.id", transaction_id); |
| 789 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 782 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 804 backing_store_->RenameIndex(transaction->BackingStoreTransaction(), | 797 backing_store_->RenameIndex(transaction->BackingStoreTransaction(), |
| 805 transaction->database()->id(), | 798 transaction->database()->id(), |
| 806 object_store_id, | 799 object_store_id, |
| 807 index_id, | 800 index_id, |
| 808 new_name); | 801 new_name); |
| 809 if (!s.ok()) { | 802 if (!s.ok()) { |
| 810 base::string16 error_string = | 803 base::string16 error_string = |
| 811 ASCIIToUTF16("Internal error renaming index '") + | 804 ASCIIToUTF16("Internal error renaming index '") + |
| 812 index_metadata.name + ASCIIToUTF16("' to '") + new_name + | 805 index_metadata.name + ASCIIToUTF16("' to '") + new_name + |
| 813 ASCIIToUTF16("'."); | 806 ASCIIToUTF16("'."); |
| 814 transaction->Abort(IndexedDBDatabaseError( | 807 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 815 blink::WebIDBDatabaseExceptionUnknownError, error_string)); | 808 error_string); |
| 809 transaction->Abort(error); |
| 810 if (s.IsCorruption()) |
| 811 factory_->HandleBackingStoreCorruption(origin(), error); |
| 812 else |
| 813 factory_->HandleBackingStoreFailure(origin()); |
| 816 return; | 814 return; |
| 817 } | 815 } |
| 818 | 816 |
| 819 transaction->ScheduleAbortTask( | 817 transaction->ScheduleAbortTask( |
| 820 base::Bind(&IndexedDBDatabase::RenameIndexAbortOperation, | 818 base::Bind(&IndexedDBDatabase::RenameIndexAbortOperation, |
| 821 this, | 819 this, |
| 822 object_store_id, | 820 object_store_id, |
| 823 index_id, | 821 index_id, |
| 824 index_metadata.name)); | 822 index_metadata.name)); |
| 825 SetIndexName(object_store_id, index_id, new_name); | 823 SetIndexName(object_store_id, index_id, new_name); |
| 826 } | 824 } |
| 827 | 825 |
| 828 void IndexedDBDatabase::RenameIndexAbortOperation( | 826 void IndexedDBDatabase::RenameIndexAbortOperation( |
| 829 int64_t object_store_id, | 827 int64_t object_store_id, |
| 830 int64_t index_id, | 828 int64_t index_id, |
| 831 const base::string16& old_name, | 829 const base::string16& old_name) { |
| 832 IndexedDBTransaction* transaction) { | |
| 833 DCHECK(!transaction); | |
| 834 IDB_TRACE("IndexedDBDatabase::RenameIndexAbortOperation"); | 830 IDB_TRACE("IndexedDBDatabase::RenameIndexAbortOperation"); |
| 835 SetIndexName(object_store_id, index_id, old_name); | 831 SetIndexName(object_store_id, index_id, old_name); |
| 836 } | 832 } |
| 837 | 833 |
| 838 void IndexedDBDatabase::Commit(int64_t transaction_id) { | 834 void IndexedDBDatabase::Commit(int64_t transaction_id) { |
| 839 // The frontend suggests that we commit, but we may have previously initiated | 835 // The frontend suggests that we commit, but we may have previously initiated |
| 840 // an abort, and so have disposed of the transaction. on_abort has already | 836 // an abort, and so have disposed of the transaction. on_abort has already |
| 841 // been dispatched to the frontend, so it will find out about that | 837 // been dispatched to the frontend, so it will find out about that |
| 842 // asynchronously. | 838 // asynchronously. |
| 843 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 839 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
| 844 if (transaction) { | 840 if (transaction) { |
| 845 scoped_refptr<IndexedDBFactory> factory = factory_; | 841 scoped_refptr<IndexedDBFactory> factory = factory_; |
| 846 leveldb::Status s = transaction->Commit(); | 842 leveldb::Status result = transaction->Commit(); |
| 847 if (s.IsCorruption()) { | 843 if (!result.ok()) { |
| 848 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 844 if (result.IsCorruption()) { |
| 849 "Internal error committing transaction."); | 845 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 850 factory->HandleBackingStoreCorruption(identifier_.first, error); | 846 base::ASCIIToUTF16(result.ToString())); |
| 847 factory->HandleBackingStoreCorruption(origin(), error); |
| 848 } else { |
| 849 factory->HandleBackingStoreFailure(origin()); |
| 850 } |
| 851 } | 851 } |
| 852 } | 852 } |
| 853 } | 853 } |
| 854 | 854 |
| 855 void IndexedDBDatabase::Abort(int64_t transaction_id) { | 855 void IndexedDBDatabase::Abort(int64_t transaction_id) { |
| 856 // If the transaction is unknown, then it has already been aborted by the | 856 // If the transaction is unknown, then it has already been aborted by the |
| 857 // backend before this call so it is safe to ignore it. | 857 // backend before this call so it is safe to ignore it. |
| 858 IDB_TRACE1("IndexedDBDatabase::Abort", "txn.id", transaction_id); | 858 IDB_TRACE1("IndexedDBDatabase::Abort", "txn.id", transaction_id); |
| 859 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 859 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
| 860 if (transaction) | 860 if (transaction) |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 964 if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id)) | 964 if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id)) |
| 965 return; | 965 return; |
| 966 | 966 |
| 967 transaction->ScheduleTask(base::Bind( | 967 transaction->ScheduleTask(base::Bind( |
| 968 &IndexedDBDatabase::GetOperation, this, object_store_id, index_id, | 968 &IndexedDBDatabase::GetOperation, this, object_store_id, index_id, |
| 969 base::Passed(&key_range), | 969 base::Passed(&key_range), |
| 970 key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE, | 970 key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE, |
| 971 callbacks)); | 971 callbacks)); |
| 972 } | 972 } |
| 973 | 973 |
| 974 void IndexedDBDatabase::GetOperation( | 974 leveldb::Status IndexedDBDatabase::GetOperation( |
| 975 int64_t object_store_id, | 975 int64_t object_store_id, |
| 976 int64_t index_id, | 976 int64_t index_id, |
| 977 std::unique_ptr<IndexedDBKeyRange> key_range, | 977 std::unique_ptr<IndexedDBKeyRange> key_range, |
| 978 indexed_db::CursorType cursor_type, | 978 indexed_db::CursorType cursor_type, |
| 979 scoped_refptr<IndexedDBCallbacks> callbacks, | 979 scoped_refptr<IndexedDBCallbacks> callbacks, |
| 980 IndexedDBTransaction* transaction) { | 980 IndexedDBTransaction* transaction) { |
| 981 IDB_TRACE1("IndexedDBDatabase::GetOperation", "txn.id", transaction->id()); | 981 IDB_TRACE1("IndexedDBDatabase::GetOperation", "txn.id", transaction->id()); |
| 982 | 982 |
| 983 DCHECK(metadata_.object_stores.find(object_store_id) != | 983 DCHECK(metadata_.object_stores.find(object_store_id) != |
| 984 metadata_.object_stores.end()); | 984 metadata_.object_stores.end()); |
| 985 const IndexedDBObjectStoreMetadata& object_store_metadata = | 985 const IndexedDBObjectStoreMetadata& object_store_metadata = |
| 986 metadata_.object_stores[object_store_id]; | 986 metadata_.object_stores[object_store_id]; |
| 987 | 987 |
| 988 const IndexedDBKey* key; | 988 const IndexedDBKey* key; |
| 989 | 989 |
| 990 leveldb::Status s; | 990 leveldb::Status s = leveldb::Status::OK(); |
| 991 std::unique_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; | 991 std::unique_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; |
| 992 if (key_range->IsOnlyKey()) { | 992 if (key_range->IsOnlyKey()) { |
| 993 key = &key_range->lower(); | 993 key = &key_range->lower(); |
| 994 } else { | 994 } else { |
| 995 if (index_id == IndexedDBIndexMetadata::kInvalidId) { | 995 if (index_id == IndexedDBIndexMetadata::kInvalidId) { |
| 996 // ObjectStore Retrieval Operation | 996 // ObjectStore Retrieval Operation |
| 997 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { | 997 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { |
| 998 backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor( | 998 backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor( |
| 999 transaction->BackingStoreTransaction(), id(), object_store_id, | 999 transaction->BackingStoreTransaction(), id(), object_store_id, |
| 1000 *key_range, blink::WebIDBCursorDirectionNext, &s); | 1000 *key_range, blink::WebIDBCursorDirectionNext, &s); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1022 index_id, | 1022 index_id, |
| 1023 *key_range, | 1023 *key_range, |
| 1024 blink::WebIDBCursorDirectionNext, | 1024 blink::WebIDBCursorDirectionNext, |
| 1025 &s); | 1025 &s); |
| 1026 } | 1026 } |
| 1027 | 1027 |
| 1028 if (!s.ok()) { | 1028 if (!s.ok()) { |
| 1029 DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString(); | 1029 DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString(); |
| 1030 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1030 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1031 "Internal error deleting data in range"); | 1031 "Internal error deleting data in range"); |
| 1032 if (s.IsCorruption()) { | 1032 callbacks->OnError(error); |
| 1033 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | 1033 return s; |
| 1034 } | |
| 1035 } | 1034 } |
| 1036 | 1035 |
| 1037 if (!backing_store_cursor) { | 1036 if (!backing_store_cursor) { |
| 1037 // This means we've run out of data. |
| 1038 callbacks->OnSuccess(); | 1038 callbacks->OnSuccess(); |
| 1039 return; | 1039 return s; |
| 1040 } | 1040 } |
| 1041 | 1041 |
| 1042 key = &backing_store_cursor->key(); | 1042 key = &backing_store_cursor->key(); |
| 1043 } | 1043 } |
| 1044 | 1044 |
| 1045 std::unique_ptr<IndexedDBKey> primary_key; | 1045 std::unique_ptr<IndexedDBKey> primary_key; |
| 1046 if (index_id == IndexedDBIndexMetadata::kInvalidId) { | 1046 if (index_id == IndexedDBIndexMetadata::kInvalidId) { |
| 1047 // Object Store Retrieval Operation | 1047 // Object Store Retrieval Operation |
| 1048 IndexedDBReturnValue value; | 1048 IndexedDBReturnValue value; |
| 1049 s = backing_store_->GetRecord(transaction->BackingStoreTransaction(), | 1049 s = backing_store_->GetRecord(transaction->BackingStoreTransaction(), |
| 1050 id(), | 1050 id(), |
| 1051 object_store_id, | 1051 object_store_id, |
| 1052 *key, | 1052 *key, |
| 1053 &value); | 1053 &value); |
| 1054 if (!s.ok()) { | 1054 if (!s.ok()) { |
| 1055 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1055 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1056 "Internal error in GetRecord."); | 1056 "Internal error in GetRecord."); |
| 1057 callbacks->OnError(error); | 1057 callbacks->OnError(error); |
| 1058 | 1058 return s; |
| 1059 if (s.IsCorruption()) | |
| 1060 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1061 return; | |
| 1062 } | 1059 } |
| 1063 | 1060 |
| 1064 if (value.empty()) { | 1061 if (value.empty()) { |
| 1065 callbacks->OnSuccess(); | 1062 callbacks->OnSuccess(); |
| 1066 return; | 1063 return s; |
| 1067 } | 1064 } |
| 1068 | 1065 |
| 1069 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { | 1066 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { |
| 1070 callbacks->OnSuccess(*key); | 1067 callbacks->OnSuccess(*key); |
| 1071 return; | 1068 return s; |
| 1072 } | 1069 } |
| 1073 | 1070 |
| 1074 if (object_store_metadata.auto_increment && | 1071 if (object_store_metadata.auto_increment && |
| 1075 !object_store_metadata.key_path.IsNull()) { | 1072 !object_store_metadata.key_path.IsNull()) { |
| 1076 value.primary_key = *key; | 1073 value.primary_key = *key; |
| 1077 value.key_path = object_store_metadata.key_path; | 1074 value.key_path = object_store_metadata.key_path; |
| 1078 } | 1075 } |
| 1079 | 1076 |
| 1080 callbacks->OnSuccess(&value); | 1077 callbacks->OnSuccess(&value); |
| 1081 return; | 1078 return s; |
| 1082 } | 1079 } |
| 1083 | 1080 |
| 1084 // From here we are dealing only with indexes. | 1081 // From here we are dealing only with indexes. |
| 1085 s = backing_store_->GetPrimaryKeyViaIndex( | 1082 s = backing_store_->GetPrimaryKeyViaIndex( |
| 1086 transaction->BackingStoreTransaction(), | 1083 transaction->BackingStoreTransaction(), |
| 1087 id(), | 1084 id(), |
| 1088 object_store_id, | 1085 object_store_id, |
| 1089 index_id, | 1086 index_id, |
| 1090 *key, | 1087 *key, |
| 1091 &primary_key); | 1088 &primary_key); |
| 1092 if (!s.ok()) { | 1089 if (!s.ok()) { |
| 1093 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1090 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1094 "Internal error in GetPrimaryKeyViaIndex."); | 1091 "Internal error in GetPrimaryKeyViaIndex."); |
| 1095 callbacks->OnError(error); | 1092 callbacks->OnError(error); |
| 1096 if (s.IsCorruption()) | 1093 return s; |
| 1097 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1098 return; | |
| 1099 } | 1094 } |
| 1100 if (!primary_key) { | 1095 if (!primary_key) { |
| 1101 callbacks->OnSuccess(); | 1096 callbacks->OnSuccess(); |
| 1102 return; | 1097 return s; |
| 1103 } | 1098 } |
| 1104 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { | 1099 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { |
| 1105 // Index Value Retrieval Operation | 1100 // Index Value Retrieval Operation |
| 1106 callbacks->OnSuccess(*primary_key); | 1101 callbacks->OnSuccess(*primary_key); |
| 1107 return; | 1102 return s; |
| 1108 } | 1103 } |
| 1109 | 1104 |
| 1110 // Index Referenced Value Retrieval Operation | 1105 // Index Referenced Value Retrieval Operation |
| 1111 IndexedDBReturnValue value; | 1106 IndexedDBReturnValue value; |
| 1112 s = backing_store_->GetRecord(transaction->BackingStoreTransaction(), | 1107 s = backing_store_->GetRecord(transaction->BackingStoreTransaction(), |
| 1113 id(), | 1108 id(), |
| 1114 object_store_id, | 1109 object_store_id, |
| 1115 *primary_key, | 1110 *primary_key, |
| 1116 &value); | 1111 &value); |
| 1117 if (!s.ok()) { | 1112 if (!s.ok()) { |
| 1118 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1113 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1119 "Internal error in GetRecord."); | 1114 "Internal error in GetRecord."); |
| 1120 callbacks->OnError(error); | 1115 callbacks->OnError(error); |
| 1121 if (s.IsCorruption()) | 1116 return s; |
| 1122 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1123 return; | |
| 1124 } | 1117 } |
| 1125 | 1118 |
| 1126 if (value.empty()) { | 1119 if (value.empty()) { |
| 1127 callbacks->OnSuccess(); | 1120 callbacks->OnSuccess(); |
| 1128 return; | 1121 return s; |
| 1129 } | 1122 } |
| 1130 if (object_store_metadata.auto_increment && | 1123 if (object_store_metadata.auto_increment && |
| 1131 !object_store_metadata.key_path.IsNull()) { | 1124 !object_store_metadata.key_path.IsNull()) { |
| 1132 value.primary_key = *primary_key; | 1125 value.primary_key = *primary_key; |
| 1133 value.key_path = object_store_metadata.key_path; | 1126 value.key_path = object_store_metadata.key_path; |
| 1134 } | 1127 } |
| 1135 callbacks->OnSuccess(&value); | 1128 callbacks->OnSuccess(&value); |
| 1129 return s; |
| 1136 } | 1130 } |
| 1137 | 1131 |
| 1138 void IndexedDBDatabase::GetAllOperation( | 1132 leveldb::Status IndexedDBDatabase::GetAllOperation( |
| 1139 int64_t object_store_id, | 1133 int64_t object_store_id, |
| 1140 int64_t index_id, | 1134 int64_t index_id, |
| 1141 std::unique_ptr<IndexedDBKeyRange> key_range, | 1135 std::unique_ptr<IndexedDBKeyRange> key_range, |
| 1142 indexed_db::CursorType cursor_type, | 1136 indexed_db::CursorType cursor_type, |
| 1143 int64_t max_count, | 1137 int64_t max_count, |
| 1144 scoped_refptr<IndexedDBCallbacks> callbacks, | 1138 scoped_refptr<IndexedDBCallbacks> callbacks, |
| 1145 IndexedDBTransaction* transaction) { | 1139 IndexedDBTransaction* transaction) { |
| 1146 IDB_TRACE1("IndexedDBDatabase::GetAllOperation", "txn.id", transaction->id()); | 1140 IDB_TRACE1("IndexedDBDatabase::GetAllOperation", "txn.id", transaction->id()); |
| 1147 | 1141 |
| 1148 DCHECK_GT(max_count, 0); | 1142 DCHECK_GT(max_count, 0); |
| 1149 | 1143 |
| 1150 DCHECK(metadata_.object_stores.find(object_store_id) != | 1144 DCHECK(metadata_.object_stores.find(object_store_id) != |
| 1151 metadata_.object_stores.end()); | 1145 metadata_.object_stores.end()); |
| 1152 const IndexedDBObjectStoreMetadata& object_store_metadata = | 1146 const IndexedDBObjectStoreMetadata& object_store_metadata = |
| 1153 metadata_.object_stores[object_store_id]; | 1147 metadata_.object_stores[object_store_id]; |
| 1154 | 1148 |
| 1155 leveldb::Status s; | 1149 leveldb::Status s = leveldb::Status::OK(); |
| 1156 | 1150 |
| 1157 std::unique_ptr<IndexedDBBackingStore::Cursor> cursor; | 1151 std::unique_ptr<IndexedDBBackingStore::Cursor> cursor; |
| 1158 | 1152 |
| 1159 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { | 1153 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { |
| 1160 // Retrieving keys | 1154 // Retrieving keys |
| 1161 if (index_id == IndexedDBIndexMetadata::kInvalidId) { | 1155 if (index_id == IndexedDBIndexMetadata::kInvalidId) { |
| 1162 // Object Store: Key Retrieval Operation | 1156 // Object Store: Key Retrieval Operation |
| 1163 cursor = backing_store_->OpenObjectStoreKeyCursor( | 1157 cursor = backing_store_->OpenObjectStoreKeyCursor( |
| 1164 transaction->BackingStoreTransaction(), id(), object_store_id, | 1158 transaction->BackingStoreTransaction(), id(), object_store_id, |
| 1165 *key_range, blink::WebIDBCursorDirectionNext, &s); | 1159 *key_range, blink::WebIDBCursorDirectionNext, &s); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1182 transaction->BackingStoreTransaction(), id(), object_store_id, | 1176 transaction->BackingStoreTransaction(), id(), object_store_id, |
| 1183 index_id, *key_range, blink::WebIDBCursorDirectionNext, &s); | 1177 index_id, *key_range, blink::WebIDBCursorDirectionNext, &s); |
| 1184 } | 1178 } |
| 1185 } | 1179 } |
| 1186 | 1180 |
| 1187 if (!s.ok()) { | 1181 if (!s.ok()) { |
| 1188 DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString(); | 1182 DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString(); |
| 1189 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1183 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1190 "Internal error in GetAllOperation"); | 1184 "Internal error in GetAllOperation"); |
| 1191 callbacks->OnError(error); | 1185 callbacks->OnError(error); |
| 1192 if (s.IsCorruption()) { | 1186 return s; |
| 1193 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1194 } | |
| 1195 return; | |
| 1196 } | 1187 } |
| 1197 | 1188 |
| 1198 std::vector<IndexedDBKey> found_keys; | 1189 std::vector<IndexedDBKey> found_keys; |
| 1199 std::vector<IndexedDBReturnValue> found_values; | 1190 std::vector<IndexedDBReturnValue> found_values; |
| 1200 if (!cursor) { | 1191 if (!cursor) { |
| 1201 // Doesn't matter if key or value array here - will be empty array when it | 1192 // Doesn't matter if key or value array here - will be empty array when it |
| 1202 // hits JavaScript. | 1193 // hits JavaScript. |
| 1203 callbacks->OnSuccessArray(&found_values); | 1194 callbacks->OnSuccessArray(&found_values); |
| 1204 return; | 1195 return s; |
| 1205 } | 1196 } |
| 1206 | 1197 |
| 1207 bool did_first_seek = false; | 1198 bool did_first_seek = false; |
| 1208 bool generated_key = object_store_metadata.auto_increment && | 1199 bool generated_key = object_store_metadata.auto_increment && |
| 1209 !object_store_metadata.key_path.IsNull(); | 1200 !object_store_metadata.key_path.IsNull(); |
| 1210 | 1201 |
| 1211 size_t response_size = kMaxIDBMessageOverhead; | 1202 size_t response_size = kMaxIDBMessageOverhead; |
| 1212 int64_t num_found_items = 0; | 1203 int64_t num_found_items = 0; |
| 1213 while (num_found_items++ < max_count) { | 1204 while (num_found_items++ < max_count) { |
| 1214 bool cursor_valid; | 1205 bool cursor_valid; |
| 1215 if (did_first_seek) { | 1206 if (did_first_seek) { |
| 1216 cursor_valid = cursor->Continue(&s); | 1207 cursor_valid = cursor->Continue(&s); |
| 1217 } else { | 1208 } else { |
| 1218 cursor_valid = cursor->FirstSeek(&s); | 1209 cursor_valid = cursor->FirstSeek(&s); |
| 1219 did_first_seek = true; | 1210 did_first_seek = true; |
| 1220 } | 1211 } |
| 1221 if (!s.ok()) { | 1212 if (!s.ok()) { |
| 1222 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1213 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1223 "Internal error in GetAllOperation."); | 1214 "Internal error in GetAllOperation."); |
| 1224 callbacks->OnError(error); | 1215 callbacks->OnError(error); |
| 1225 if (s.IsCorruption()) | 1216 return s; |
| 1226 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1227 return; | |
| 1228 } | 1217 } |
| 1229 | 1218 |
| 1230 if (!cursor_valid) | 1219 if (!cursor_valid) |
| 1231 break; | 1220 break; |
| 1232 | 1221 |
| 1233 IndexedDBReturnValue return_value; | 1222 IndexedDBReturnValue return_value; |
| 1234 IndexedDBKey return_key; | 1223 IndexedDBKey return_key; |
| 1235 | 1224 |
| 1236 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { | 1225 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { |
| 1237 return_key = cursor->primary_key(); | 1226 return_key = cursor->primary_key(); |
| 1238 } else { | 1227 } else { |
| 1239 // Retrieving values | 1228 // Retrieving values |
| 1240 return_value.swap(*cursor->value()); | 1229 return_value.swap(*cursor->value()); |
| 1241 if (!return_value.empty() && generated_key) { | 1230 if (!return_value.empty() && generated_key) { |
| 1242 return_value.primary_key = cursor->primary_key(); | 1231 return_value.primary_key = cursor->primary_key(); |
| 1243 return_value.key_path = object_store_metadata.key_path; | 1232 return_value.key_path = object_store_metadata.key_path; |
| 1244 } | 1233 } |
| 1245 } | 1234 } |
| 1246 | 1235 |
| 1247 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) | 1236 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) |
| 1248 response_size += return_key.size_estimate(); | 1237 response_size += return_key.size_estimate(); |
| 1249 else | 1238 else |
| 1250 response_size += return_value.SizeEstimate(); | 1239 response_size += return_value.SizeEstimate(); |
| 1251 if (response_size > GetMaxMessageSizeInBytes()) { | 1240 if (response_size > GetMaxMessageSizeInBytes()) { |
| 1252 callbacks->OnError( | 1241 callbacks->OnError( |
| 1253 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, | 1242 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, |
| 1254 "Maximum IPC message size exceeded.")); | 1243 "Maximum IPC message size exceeded.")); |
| 1255 return; | 1244 return s; |
| 1256 } | 1245 } |
| 1257 | 1246 |
| 1258 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) | 1247 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) |
| 1259 found_keys.push_back(return_key); | 1248 found_keys.push_back(return_key); |
| 1260 else | 1249 else |
| 1261 found_values.push_back(return_value); | 1250 found_values.push_back(return_value); |
| 1262 } | 1251 } |
| 1263 | 1252 |
| 1264 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { | 1253 if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { |
| 1265 // IndexedDBKey already supports an array of values so we can leverage this | 1254 // IndexedDBKey already supports an array of values so we can leverage this |
| 1266 // to return an array of keys - no need to create our own array of keys. | 1255 // to return an array of keys - no need to create our own array of keys. |
| 1267 callbacks->OnSuccess(IndexedDBKey(found_keys)); | 1256 callbacks->OnSuccess(IndexedDBKey(found_keys)); |
| 1268 } else { | 1257 } else { |
| 1269 callbacks->OnSuccessArray(&found_values); | 1258 callbacks->OnSuccessArray(&found_values); |
| 1270 } | 1259 } |
| 1260 return s; |
| 1271 } | 1261 } |
| 1272 | 1262 |
| 1273 static std::unique_ptr<IndexedDBKey> GenerateKey( | 1263 static std::unique_ptr<IndexedDBKey> GenerateKey( |
| 1274 IndexedDBBackingStore* backing_store, | 1264 IndexedDBBackingStore* backing_store, |
| 1275 IndexedDBTransaction* transaction, | 1265 IndexedDBTransaction* transaction, |
| 1276 int64_t database_id, | 1266 int64_t database_id, |
| 1277 int64_t object_store_id) { | 1267 int64_t object_store_id) { |
| 1278 const int64_t max_generator_value = | 1268 const int64_t max_generator_value = |
| 1279 9007199254740992LL; // Maximum integer storable as ECMAScript number. | 1269 9007199254740992LL; // Maximum integer storable as ECMAScript number. |
| 1280 int64_t current_number; | 1270 int64_t current_number; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1345 params->value.swap(*value); | 1335 params->value.swap(*value); |
| 1346 params->handles.swap(*handles); | 1336 params->handles.swap(*handles); |
| 1347 params->key = std::move(key); | 1337 params->key = std::move(key); |
| 1348 params->put_mode = put_mode; | 1338 params->put_mode = put_mode; |
| 1349 params->callbacks = callbacks; | 1339 params->callbacks = callbacks; |
| 1350 params->index_keys = index_keys; | 1340 params->index_keys = index_keys; |
| 1351 transaction->ScheduleTask(base::Bind( | 1341 transaction->ScheduleTask(base::Bind( |
| 1352 &IndexedDBDatabase::PutOperation, this, base::Passed(¶ms))); | 1342 &IndexedDBDatabase::PutOperation, this, base::Passed(¶ms))); |
| 1353 } | 1343 } |
| 1354 | 1344 |
| 1355 void IndexedDBDatabase::PutOperation(std::unique_ptr<PutOperationParams> params, | 1345 leveldb::Status IndexedDBDatabase::PutOperation( |
| 1356 IndexedDBTransaction* transaction) { | 1346 std::unique_ptr<PutOperationParams> params, |
| 1347 IndexedDBTransaction* transaction) { |
| 1357 IDB_TRACE1("IndexedDBDatabase::PutOperation", "txn.id", transaction->id()); | 1348 IDB_TRACE1("IndexedDBDatabase::PutOperation", "txn.id", transaction->id()); |
| 1358 DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly); | 1349 DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly); |
| 1359 bool key_was_generated = false; | 1350 bool key_was_generated = false; |
| 1351 leveldb::Status s = leveldb::Status::OK(); |
| 1360 | 1352 |
| 1361 DCHECK(metadata_.object_stores.find(params->object_store_id) != | 1353 DCHECK(metadata_.object_stores.find(params->object_store_id) != |
| 1362 metadata_.object_stores.end()); | 1354 metadata_.object_stores.end()); |
| 1363 const IndexedDBObjectStoreMetadata& object_store = | 1355 const IndexedDBObjectStoreMetadata& object_store = |
| 1364 metadata_.object_stores[params->object_store_id]; | 1356 metadata_.object_stores[params->object_store_id]; |
| 1365 DCHECK(object_store.auto_increment || params->key->IsValid()); | 1357 DCHECK(object_store.auto_increment || params->key->IsValid()); |
| 1366 | 1358 |
| 1367 std::unique_ptr<IndexedDBKey> key; | 1359 std::unique_ptr<IndexedDBKey> key; |
| 1368 if (params->put_mode != blink::WebIDBPutModeCursorUpdate && | 1360 if (params->put_mode != blink::WebIDBPutModeCursorUpdate && |
| 1369 object_store.auto_increment && !params->key->IsValid()) { | 1361 object_store.auto_increment && !params->key->IsValid()) { |
| 1370 std::unique_ptr<IndexedDBKey> auto_inc_key = GenerateKey( | 1362 std::unique_ptr<IndexedDBKey> auto_inc_key = GenerateKey( |
| 1371 backing_store_.get(), transaction, id(), params->object_store_id); | 1363 backing_store_.get(), transaction, id(), params->object_store_id); |
| 1372 key_was_generated = true; | 1364 key_was_generated = true; |
| 1373 if (!auto_inc_key->IsValid()) { | 1365 if (!auto_inc_key->IsValid()) { |
| 1374 params->callbacks->OnError( | 1366 params->callbacks->OnError( |
| 1375 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError, | 1367 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError, |
| 1376 "Maximum key generator value reached.")); | 1368 "Maximum key generator value reached.")); |
| 1377 return; | 1369 return s; |
| 1378 } | 1370 } |
| 1379 key = std::move(auto_inc_key); | 1371 key = std::move(auto_inc_key); |
| 1380 } else { | 1372 } else { |
| 1381 key = std::move(params->key); | 1373 key = std::move(params->key); |
| 1382 } | 1374 } |
| 1383 | 1375 |
| 1384 DCHECK(key->IsValid()); | 1376 DCHECK(key->IsValid()); |
| 1385 | 1377 |
| 1386 IndexedDBBackingStore::RecordIdentifier record_identifier; | 1378 IndexedDBBackingStore::RecordIdentifier record_identifier; |
| 1387 if (params->put_mode == blink::WebIDBPutModeAddOnly) { | 1379 if (params->put_mode == blink::WebIDBPutModeAddOnly) { |
| 1388 bool found = false; | 1380 bool found = false; |
| 1389 leveldb::Status s = backing_store_->KeyExistsInObjectStore( | 1381 leveldb::Status s = backing_store_->KeyExistsInObjectStore( |
| 1390 transaction->BackingStoreTransaction(), | 1382 transaction->BackingStoreTransaction(), |
| 1391 id(), | 1383 id(), |
| 1392 params->object_store_id, | 1384 params->object_store_id, |
| 1393 *key, | 1385 *key, |
| 1394 &record_identifier, | 1386 &record_identifier, |
| 1395 &found); | 1387 &found); |
| 1396 if (!s.ok()) { | 1388 if (!s.ok()) { |
| 1397 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1389 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1398 "Internal error checking key existence."); | 1390 "Internal error checking key existence."); |
| 1399 params->callbacks->OnError(error); | 1391 params->callbacks->OnError(error); |
| 1400 if (s.IsCorruption()) | 1392 return s; |
| 1401 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1402 return; | |
| 1403 } | 1393 } |
| 1404 if (found) { | 1394 if (found) { |
| 1405 params->callbacks->OnError( | 1395 params->callbacks->OnError( |
| 1406 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError, | 1396 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionConstraintError, |
| 1407 "Key already exists in the object store.")); | 1397 "Key already exists in the object store.")); |
| 1408 return; | 1398 return s; |
| 1409 } | 1399 } |
| 1410 } | 1400 } |
| 1411 | 1401 |
| 1412 std::vector<std::unique_ptr<IndexWriter>> index_writers; | 1402 std::vector<std::unique_ptr<IndexWriter>> index_writers; |
| 1413 base::string16 error_message; | 1403 base::string16 error_message; |
| 1414 bool obeys_constraints = false; | 1404 bool obeys_constraints = false; |
| 1415 bool backing_store_success = MakeIndexWriters(transaction, | 1405 bool backing_store_success = MakeIndexWriters(transaction, |
| 1416 backing_store_.get(), | 1406 backing_store_.get(), |
| 1417 id(), | 1407 id(), |
| 1418 object_store, | 1408 object_store, |
| 1419 *key, | 1409 *key, |
| 1420 key_was_generated, | 1410 key_was_generated, |
| 1421 params->index_keys, | 1411 params->index_keys, |
| 1422 &index_writers, | 1412 &index_writers, |
| 1423 &error_message, | 1413 &error_message, |
| 1424 &obeys_constraints); | 1414 &obeys_constraints); |
| 1425 if (!backing_store_success) { | 1415 if (!backing_store_success) { |
| 1426 params->callbacks->OnError(IndexedDBDatabaseError( | 1416 params->callbacks->OnError(IndexedDBDatabaseError( |
| 1427 blink::WebIDBDatabaseExceptionUnknownError, | 1417 blink::WebIDBDatabaseExceptionUnknownError, |
| 1428 "Internal error: backing store error updating index keys.")); | 1418 "Internal error: backing store error updating index keys.")); |
| 1429 return; | 1419 return s; |
| 1430 } | 1420 } |
| 1431 if (!obeys_constraints) { | 1421 if (!obeys_constraints) { |
| 1432 params->callbacks->OnError(IndexedDBDatabaseError( | 1422 params->callbacks->OnError(IndexedDBDatabaseError( |
| 1433 blink::WebIDBDatabaseExceptionConstraintError, error_message)); | 1423 blink::WebIDBDatabaseExceptionConstraintError, error_message)); |
| 1434 return; | 1424 return s; |
| 1435 } | 1425 } |
| 1436 | 1426 |
| 1437 // Before this point, don't do any mutation. After this point, rollback the | 1427 // Before this point, don't do any mutation. After this point, rollback the |
| 1438 // transaction in case of error. | 1428 // transaction in case of error. |
| 1439 leveldb::Status s = | 1429 s = backing_store_->PutRecord(transaction->BackingStoreTransaction(), id(), |
| 1440 backing_store_->PutRecord(transaction->BackingStoreTransaction(), | 1430 params->object_store_id, *key, ¶ms->value, |
| 1441 id(), | 1431 ¶ms->handles, &record_identifier); |
| 1442 params->object_store_id, | |
| 1443 *key, | |
| 1444 ¶ms->value, | |
| 1445 ¶ms->handles, | |
| 1446 &record_identifier); | |
| 1447 if (!s.ok()) { | 1432 if (!s.ok()) { |
| 1448 IndexedDBDatabaseError error( | 1433 IndexedDBDatabaseError error( |
| 1449 blink::WebIDBDatabaseExceptionUnknownError, | 1434 blink::WebIDBDatabaseExceptionUnknownError, |
| 1450 "Internal error: backing store error performing put/add."); | 1435 "Internal error: backing store error performing put/add."); |
| 1451 params->callbacks->OnError(error); | 1436 params->callbacks->OnError(error); |
| 1452 if (s.IsCorruption()) | 1437 return s; |
| 1453 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1454 return; | |
| 1455 } | 1438 } |
| 1456 { | 1439 { |
| 1457 IDB_TRACE1("IndexedDBDatabase::PutOperation.UpdateIndexes", "txn.id", | 1440 IDB_TRACE1("IndexedDBDatabase::PutOperation.UpdateIndexes", "txn.id", |
| 1458 transaction->id()); | 1441 transaction->id()); |
| 1459 for (const auto& writer : index_writers) { | 1442 for (const auto& writer : index_writers) { |
| 1460 writer->WriteIndexKeys(record_identifier, backing_store_.get(), | 1443 writer->WriteIndexKeys(record_identifier, backing_store_.get(), |
| 1461 transaction->BackingStoreTransaction(), id(), | 1444 transaction->BackingStoreTransaction(), id(), |
| 1462 params->object_store_id); | 1445 params->object_store_id); |
| 1463 } | 1446 } |
| 1464 } | 1447 } |
| 1465 | 1448 |
| 1466 if (object_store.auto_increment && | 1449 if (object_store.auto_increment && |
| 1467 params->put_mode != blink::WebIDBPutModeCursorUpdate && | 1450 params->put_mode != blink::WebIDBPutModeCursorUpdate && |
| 1468 key->type() == WebIDBKeyTypeNumber) { | 1451 key->type() == WebIDBKeyTypeNumber) { |
| 1469 IDB_TRACE1("IndexedDBDatabase::PutOperation.AutoIncrement", "txn.id", | 1452 IDB_TRACE1("IndexedDBDatabase::PutOperation.AutoIncrement", "txn.id", |
| 1470 transaction->id()); | 1453 transaction->id()); |
| 1471 leveldb::Status s = UpdateKeyGenerator(backing_store_.get(), | 1454 s = UpdateKeyGenerator(backing_store_.get(), transaction, id(), |
| 1472 transaction, | 1455 params->object_store_id, *key, !key_was_generated); |
| 1473 id(), | |
| 1474 params->object_store_id, | |
| 1475 *key, | |
| 1476 !key_was_generated); | |
| 1477 if (!s.ok()) { | 1456 if (!s.ok()) { |
| 1478 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1457 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1479 "Internal error updating key generator."); | 1458 "Internal error updating key generator."); |
| 1480 params->callbacks->OnError(error); | 1459 params->callbacks->OnError(error); |
| 1481 if (s.IsCorruption()) | 1460 return s; |
| 1482 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1483 return; | |
| 1484 } | 1461 } |
| 1485 } | 1462 } |
| 1486 { | 1463 { |
| 1487 IDB_TRACE1("IndexedDBDatabase::PutOperation.Callbacks", "txn.id", | 1464 IDB_TRACE1("IndexedDBDatabase::PutOperation.Callbacks", "txn.id", |
| 1488 transaction->id()); | 1465 transaction->id()); |
| 1489 params->callbacks->OnSuccess(*key); | 1466 params->callbacks->OnSuccess(*key); |
| 1490 } | 1467 } |
| 1491 FilterObservation(transaction, params->object_store_id, | 1468 FilterObservation(transaction, params->object_store_id, |
| 1492 params->put_mode == blink::WebIDBPutModeAddOnly | 1469 params->put_mode == blink::WebIDBPutModeAddOnly |
| 1493 ? blink::WebIDBAdd | 1470 ? blink::WebIDBAdd |
| 1494 : blink::WebIDBPut, | 1471 : blink::WebIDBPut, |
| 1495 IndexedDBKeyRange(*key)); | 1472 IndexedDBKeyRange(*key)); |
| 1473 return s; |
| 1496 } | 1474 } |
| 1497 | 1475 |
| 1498 void IndexedDBDatabase::SetIndexKeys( | 1476 void IndexedDBDatabase::SetIndexKeys( |
| 1499 int64_t transaction_id, | 1477 int64_t transaction_id, |
| 1500 int64_t object_store_id, | 1478 int64_t object_store_id, |
| 1501 std::unique_ptr<IndexedDBKey> primary_key, | 1479 std::unique_ptr<IndexedDBKey> primary_key, |
| 1502 const std::vector<IndexedDBIndexKeys>& index_keys) { | 1480 const std::vector<IndexedDBIndexKeys>& index_keys) { |
| 1503 IDB_TRACE1("IndexedDBDatabase::SetIndexKeys", "txn.id", transaction_id); | 1481 IDB_TRACE1("IndexedDBDatabase::SetIndexKeys", "txn.id", transaction_id); |
| 1482 |
| 1504 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 1483 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
| 1505 if (!transaction) | 1484 if (!transaction) |
| 1506 return; | 1485 return; |
| 1507 DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange); | 1486 DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange); |
| 1508 | 1487 |
| 1509 // TODO(alecflett): This method could be asynchronous, but we need to | 1488 // TODO(alecflett): This method could be asynchronous, but we need to |
| 1510 // evaluate if it's worth the extra complexity. | 1489 // evaluate if it's worth the extra complexity. |
| 1511 IndexedDBBackingStore::RecordIdentifier record_identifier; | 1490 IndexedDBBackingStore::RecordIdentifier record_identifier; |
| 1512 bool found = false; | 1491 bool found = false; |
| 1513 leveldb::Status s = backing_store_->KeyExistsInObjectStore( | 1492 leveldb::Status s = backing_store_->KeyExistsInObjectStore( |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1576 return; | 1555 return; |
| 1577 DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange); | 1556 DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange); |
| 1578 | 1557 |
| 1579 transaction->ScheduleTask( | 1558 transaction->ScheduleTask( |
| 1580 blink::WebIDBTaskTypePreemptive, | 1559 blink::WebIDBTaskTypePreemptive, |
| 1581 base::Bind(&IndexedDBDatabase::SetIndexesReadyOperation, | 1560 base::Bind(&IndexedDBDatabase::SetIndexesReadyOperation, |
| 1582 this, | 1561 this, |
| 1583 index_ids.size())); | 1562 index_ids.size())); |
| 1584 } | 1563 } |
| 1585 | 1564 |
| 1586 void IndexedDBDatabase::SetIndexesReadyOperation( | 1565 leveldb::Status IndexedDBDatabase::SetIndexesReadyOperation( |
| 1587 size_t index_count, | 1566 size_t index_count, |
| 1588 IndexedDBTransaction* transaction) { | 1567 IndexedDBTransaction* transaction) { |
| 1589 for (size_t i = 0; i < index_count; ++i) | 1568 for (size_t i = 0; i < index_count; ++i) |
| 1590 transaction->DidCompletePreemptiveEvent(); | 1569 transaction->DidCompletePreemptiveEvent(); |
| 1570 return leveldb::Status::OK(); |
| 1591 } | 1571 } |
| 1592 | 1572 |
| 1593 struct IndexedDBDatabase::OpenCursorOperationParams { | 1573 struct IndexedDBDatabase::OpenCursorOperationParams { |
| 1594 OpenCursorOperationParams() {} | 1574 OpenCursorOperationParams() {} |
| 1595 int64_t object_store_id; | 1575 int64_t object_store_id; |
| 1596 int64_t index_id; | 1576 int64_t index_id; |
| 1597 std::unique_ptr<IndexedDBKeyRange> key_range; | 1577 std::unique_ptr<IndexedDBKeyRange> key_range; |
| 1598 blink::WebIDBCursorDirection direction; | 1578 blink::WebIDBCursorDirection direction; |
| 1599 indexed_db::CursorType cursor_type; | 1579 indexed_db::CursorType cursor_type; |
| 1600 blink::WebIDBTaskType task_type; | 1580 blink::WebIDBTaskType task_type; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1628 params->key_range = std::move(key_range); | 1608 params->key_range = std::move(key_range); |
| 1629 params->direction = direction; | 1609 params->direction = direction; |
| 1630 params->cursor_type = | 1610 params->cursor_type = |
| 1631 key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE; | 1611 key_only ? indexed_db::CURSOR_KEY_ONLY : indexed_db::CURSOR_KEY_AND_VALUE; |
| 1632 params->task_type = task_type; | 1612 params->task_type = task_type; |
| 1633 params->callbacks = callbacks; | 1613 params->callbacks = callbacks; |
| 1634 transaction->ScheduleTask(base::Bind( | 1614 transaction->ScheduleTask(base::Bind( |
| 1635 &IndexedDBDatabase::OpenCursorOperation, this, base::Passed(¶ms))); | 1615 &IndexedDBDatabase::OpenCursorOperation, this, base::Passed(¶ms))); |
| 1636 } | 1616 } |
| 1637 | 1617 |
| 1638 void IndexedDBDatabase::OpenCursorOperation( | 1618 leveldb::Status IndexedDBDatabase::OpenCursorOperation( |
| 1639 std::unique_ptr<OpenCursorOperationParams> params, | 1619 std::unique_ptr<OpenCursorOperationParams> params, |
| 1640 IndexedDBTransaction* transaction) { | 1620 IndexedDBTransaction* transaction) { |
| 1641 IDB_TRACE1( | 1621 IDB_TRACE1( |
| 1642 "IndexedDBDatabase::OpenCursorOperation", "txn.id", transaction->id()); | 1622 "IndexedDBDatabase::OpenCursorOperation", "txn.id", transaction->id()); |
| 1643 | 1623 |
| 1644 // The frontend has begun indexing, so this pauses the transaction | 1624 // The frontend has begun indexing, so this pauses the transaction |
| 1645 // until the indexing is complete. This can't happen any earlier | 1625 // until the indexing is complete. This can't happen any earlier |
| 1646 // because we don't want to switch to early mode in case multiple | 1626 // because we don't want to switch to early mode in case multiple |
| 1647 // indexes are being created in a row, with Put()'s in between. | 1627 // indexes are being created in a row, with Put()'s in between. |
| 1648 if (params->task_type == blink::WebIDBTaskTypePreemptive) | 1628 if (params->task_type == blink::WebIDBTaskTypePreemptive) |
| 1649 transaction->AddPreemptiveEvent(); | 1629 transaction->AddPreemptiveEvent(); |
| 1650 | 1630 |
| 1651 leveldb::Status s; | 1631 leveldb::Status s = leveldb::Status::OK(); |
| 1652 std::unique_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; | 1632 std::unique_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; |
| 1653 if (params->index_id == IndexedDBIndexMetadata::kInvalidId) { | 1633 if (params->index_id == IndexedDBIndexMetadata::kInvalidId) { |
| 1654 if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) { | 1634 if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) { |
| 1655 DCHECK_EQ(params->task_type, blink::WebIDBTaskTypeNormal); | 1635 DCHECK_EQ(params->task_type, blink::WebIDBTaskTypeNormal); |
| 1656 backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor( | 1636 backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor( |
| 1657 transaction->BackingStoreTransaction(), | 1637 transaction->BackingStoreTransaction(), |
| 1658 id(), | 1638 id(), |
| 1659 params->object_store_id, | 1639 params->object_store_id, |
| 1660 *params->key_range, | 1640 *params->key_range, |
| 1661 params->direction, | 1641 params->direction, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1689 *params->key_range, | 1669 *params->key_range, |
| 1690 params->direction, | 1670 params->direction, |
| 1691 &s); | 1671 &s); |
| 1692 } | 1672 } |
| 1693 } | 1673 } |
| 1694 | 1674 |
| 1695 if (!s.ok()) { | 1675 if (!s.ok()) { |
| 1696 DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString(); | 1676 DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString(); |
| 1697 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1677 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1698 "Internal error opening cursor operation"); | 1678 "Internal error opening cursor operation"); |
| 1699 if (s.IsCorruption()) { | 1679 return s; |
| 1700 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1701 } | |
| 1702 } | 1680 } |
| 1703 | 1681 |
| 1704 if (!backing_store_cursor) { | 1682 if (!backing_store_cursor) { |
| 1705 // Why is Success being called? | 1683 // Occurs when we've reached the end of cursor's data. |
| 1706 params->callbacks->OnSuccess(nullptr); | 1684 params->callbacks->OnSuccess(nullptr); |
| 1707 return; | 1685 return s; |
| 1708 } | 1686 } |
| 1709 | 1687 |
| 1710 scoped_refptr<IndexedDBCursor> cursor = | 1688 scoped_refptr<IndexedDBCursor> cursor = |
| 1711 new IndexedDBCursor(std::move(backing_store_cursor), params->cursor_type, | 1689 new IndexedDBCursor(std::move(backing_store_cursor), params->cursor_type, |
| 1712 params->task_type, transaction); | 1690 params->task_type, transaction); |
| 1713 params->callbacks->OnSuccess( | 1691 params->callbacks->OnSuccess( |
| 1714 cursor, cursor->key(), cursor->primary_key(), cursor->Value()); | 1692 cursor, cursor->key(), cursor->primary_key(), cursor->Value()); |
| 1693 return s; |
| 1715 } | 1694 } |
| 1716 | 1695 |
| 1717 void IndexedDBDatabase::Count(int64_t transaction_id, | 1696 void IndexedDBDatabase::Count(int64_t transaction_id, |
| 1718 int64_t object_store_id, | 1697 int64_t object_store_id, |
| 1719 int64_t index_id, | 1698 int64_t index_id, |
| 1720 std::unique_ptr<IndexedDBKeyRange> key_range, | 1699 std::unique_ptr<IndexedDBKeyRange> key_range, |
| 1721 scoped_refptr<IndexedDBCallbacks> callbacks) { | 1700 scoped_refptr<IndexedDBCallbacks> callbacks) { |
| 1722 IDB_TRACE1("IndexedDBDatabase::Count", "txn.id", transaction_id); | 1701 IDB_TRACE1("IndexedDBDatabase::Count", "txn.id", transaction_id); |
| 1723 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 1702 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
| 1724 if (!transaction) | 1703 if (!transaction) |
| 1725 return; | 1704 return; |
| 1726 | 1705 |
| 1727 if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id)) | 1706 if (!ValidateObjectStoreIdAndOptionalIndexId(object_store_id, index_id)) |
| 1728 return; | 1707 return; |
| 1729 | 1708 |
| 1730 transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::CountOperation, | 1709 transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::CountOperation, |
| 1731 this, | 1710 this, |
| 1732 object_store_id, | 1711 object_store_id, |
| 1733 index_id, | 1712 index_id, |
| 1734 base::Passed(&key_range), | 1713 base::Passed(&key_range), |
| 1735 callbacks)); | 1714 callbacks)); |
| 1736 } | 1715 } |
| 1737 | 1716 |
| 1738 void IndexedDBDatabase::CountOperation( | 1717 leveldb::Status IndexedDBDatabase::CountOperation( |
| 1739 int64_t object_store_id, | 1718 int64_t object_store_id, |
| 1740 int64_t index_id, | 1719 int64_t index_id, |
| 1741 std::unique_ptr<IndexedDBKeyRange> key_range, | 1720 std::unique_ptr<IndexedDBKeyRange> key_range, |
| 1742 scoped_refptr<IndexedDBCallbacks> callbacks, | 1721 scoped_refptr<IndexedDBCallbacks> callbacks, |
| 1743 IndexedDBTransaction* transaction) { | 1722 IndexedDBTransaction* transaction) { |
| 1744 IDB_TRACE1("IndexedDBDatabase::CountOperation", "txn.id", transaction->id()); | 1723 IDB_TRACE1("IndexedDBDatabase::CountOperation", "txn.id", transaction->id()); |
| 1745 uint32_t count = 0; | 1724 uint32_t count = 0; |
| 1746 std::unique_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; | 1725 std::unique_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; |
| 1747 | 1726 |
| 1748 leveldb::Status s; | 1727 leveldb::Status s = leveldb::Status::OK(); |
| 1749 if (index_id == IndexedDBIndexMetadata::kInvalidId) { | 1728 if (index_id == IndexedDBIndexMetadata::kInvalidId) { |
| 1750 backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor( | 1729 backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor( |
| 1751 transaction->BackingStoreTransaction(), | 1730 transaction->BackingStoreTransaction(), |
| 1752 id(), | 1731 id(), |
| 1753 object_store_id, | 1732 object_store_id, |
| 1754 *key_range, | 1733 *key_range, |
| 1755 blink::WebIDBCursorDirectionNext, | 1734 blink::WebIDBCursorDirectionNext, |
| 1756 &s); | 1735 &s); |
| 1757 } else { | 1736 } else { |
| 1758 backing_store_cursor = backing_store_->OpenIndexKeyCursor( | 1737 backing_store_cursor = backing_store_->OpenIndexKeyCursor( |
| 1759 transaction->BackingStoreTransaction(), | 1738 transaction->BackingStoreTransaction(), |
| 1760 id(), | 1739 id(), |
| 1761 object_store_id, | 1740 object_store_id, |
| 1762 index_id, | 1741 index_id, |
| 1763 *key_range, | 1742 *key_range, |
| 1764 blink::WebIDBCursorDirectionNext, | 1743 blink::WebIDBCursorDirectionNext, |
| 1765 &s); | 1744 &s); |
| 1766 } | 1745 } |
| 1767 if (!s.ok()) { | 1746 if (!s.ok()) { |
| 1768 DLOG(ERROR) << "Unable perform count operation: " << s.ToString(); | 1747 DLOG(ERROR) << "Unable perform count operation: " << s.ToString(); |
| 1769 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1748 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1770 "Internal error performing count operation"); | 1749 "Internal error performing count operation"); |
| 1771 if (s.IsCorruption()) { | 1750 return s; |
| 1772 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1773 } | |
| 1774 } | 1751 } |
| 1775 if (!backing_store_cursor) { | 1752 if (!backing_store_cursor) { |
| 1776 callbacks->OnSuccess(count); | 1753 callbacks->OnSuccess(count); |
| 1777 return; | 1754 return s; |
| 1778 } | 1755 } |
| 1779 | 1756 |
| 1780 do { | 1757 do { |
| 1758 if (!s.ok()) |
| 1759 return s; |
| 1781 ++count; | 1760 ++count; |
| 1782 } while (backing_store_cursor->Continue(&s)); | 1761 } while (backing_store_cursor->Continue(&s)); |
| 1783 | 1762 |
| 1784 // TODO(cmumford): Check for database corruption. | |
| 1785 | |
| 1786 callbacks->OnSuccess(count); | 1763 callbacks->OnSuccess(count); |
| 1764 return s; |
| 1787 } | 1765 } |
| 1788 | 1766 |
| 1789 void IndexedDBDatabase::DeleteRange( | 1767 void IndexedDBDatabase::DeleteRange( |
| 1790 int64_t transaction_id, | 1768 int64_t transaction_id, |
| 1791 int64_t object_store_id, | 1769 int64_t object_store_id, |
| 1792 std::unique_ptr<IndexedDBKeyRange> key_range, | 1770 std::unique_ptr<IndexedDBKeyRange> key_range, |
| 1793 scoped_refptr<IndexedDBCallbacks> callbacks) { | 1771 scoped_refptr<IndexedDBCallbacks> callbacks) { |
| 1794 IDB_TRACE1("IndexedDBDatabase::DeleteRange", "txn.id", transaction_id); | 1772 IDB_TRACE1("IndexedDBDatabase::DeleteRange", "txn.id", transaction_id); |
| 1795 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 1773 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
| 1796 if (!transaction) | 1774 if (!transaction) |
| 1797 return; | 1775 return; |
| 1798 DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly); | 1776 DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly); |
| 1799 | 1777 |
| 1800 if (!ValidateObjectStoreId(object_store_id)) | 1778 if (!ValidateObjectStoreId(object_store_id)) |
| 1801 return; | 1779 return; |
| 1802 | 1780 |
| 1803 transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::DeleteRangeOperation, | 1781 transaction->ScheduleTask(base::Bind(&IndexedDBDatabase::DeleteRangeOperation, |
| 1804 this, | 1782 this, |
| 1805 object_store_id, | 1783 object_store_id, |
| 1806 base::Passed(&key_range), | 1784 base::Passed(&key_range), |
| 1807 callbacks)); | 1785 callbacks)); |
| 1808 } | 1786 } |
| 1809 | 1787 |
| 1810 void IndexedDBDatabase::DeleteRangeOperation( | 1788 leveldb::Status IndexedDBDatabase::DeleteRangeOperation( |
| 1811 int64_t object_store_id, | 1789 int64_t object_store_id, |
| 1812 std::unique_ptr<IndexedDBKeyRange> key_range, | 1790 std::unique_ptr<IndexedDBKeyRange> key_range, |
| 1813 scoped_refptr<IndexedDBCallbacks> callbacks, | 1791 scoped_refptr<IndexedDBCallbacks> callbacks, |
| 1814 IndexedDBTransaction* transaction) { | 1792 IndexedDBTransaction* transaction) { |
| 1815 IDB_TRACE1("IndexedDBDatabase::DeleteRangeOperation", "txn.id", | 1793 IDB_TRACE1("IndexedDBDatabase::DeleteRangeOperation", "txn.id", |
| 1816 transaction->id()); | 1794 transaction->id()); |
| 1817 size_t delete_count = 0; | 1795 size_t delete_count = 0; |
| 1818 leveldb::Status s = | 1796 leveldb::Status s = |
| 1819 backing_store_->DeleteRange(transaction->BackingStoreTransaction(), id(), | 1797 backing_store_->DeleteRange(transaction->BackingStoreTransaction(), id(), |
| 1820 object_store_id, *key_range, &delete_count); | 1798 object_store_id, *key_range, &delete_count); |
| 1821 if (!s.ok()) { | 1799 if (!s.ok()) { |
| 1822 base::string16 error_string = | 1800 base::string16 error_string = |
| 1823 ASCIIToUTF16("Internal error deleting data in range"); | 1801 ASCIIToUTF16("Internal error deleting data in range"); |
| 1824 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1802 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1825 error_string); | 1803 error_string); |
| 1826 transaction->Abort(error); | 1804 transaction->Abort(error); |
| 1827 if (s.IsCorruption()) { | 1805 return s; |
| 1828 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1829 } | |
| 1830 return; | |
| 1831 } | 1806 } |
| 1832 callbacks->OnSuccess(); | 1807 callbacks->OnSuccess(); |
| 1833 FilterObservation(transaction, object_store_id, blink::WebIDBDelete, | 1808 FilterObservation(transaction, object_store_id, blink::WebIDBDelete, |
| 1834 *key_range); | 1809 *key_range); |
| 1810 return s; |
| 1835 } | 1811 } |
| 1836 | 1812 |
| 1837 void IndexedDBDatabase::Clear(int64_t transaction_id, | 1813 void IndexedDBDatabase::Clear(int64_t transaction_id, |
| 1838 int64_t object_store_id, | 1814 int64_t object_store_id, |
| 1839 scoped_refptr<IndexedDBCallbacks> callbacks) { | 1815 scoped_refptr<IndexedDBCallbacks> callbacks) { |
| 1840 IDB_TRACE1("IndexedDBDatabase::Clear", "txn.id", transaction_id); | 1816 IDB_TRACE1("IndexedDBDatabase::Clear", "txn.id", transaction_id); |
| 1841 IndexedDBTransaction* transaction = GetTransaction(transaction_id); | 1817 IndexedDBTransaction* transaction = GetTransaction(transaction_id); |
| 1842 if (!transaction) | 1818 if (!transaction) |
| 1843 return; | 1819 return; |
| 1844 DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly); | 1820 DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly); |
| 1845 | 1821 |
| 1846 if (!ValidateObjectStoreId(object_store_id)) | 1822 if (!ValidateObjectStoreId(object_store_id)) |
| 1847 return; | 1823 return; |
| 1848 | 1824 |
| 1849 transaction->ScheduleTask(base::Bind( | 1825 transaction->ScheduleTask(base::Bind( |
| 1850 &IndexedDBDatabase::ClearOperation, this, object_store_id, callbacks)); | 1826 &IndexedDBDatabase::ClearOperation, this, object_store_id, callbacks)); |
| 1851 } | 1827 } |
| 1852 | 1828 |
| 1853 void IndexedDBDatabase::ClearOperation( | 1829 leveldb::Status IndexedDBDatabase::ClearOperation( |
| 1854 int64_t object_store_id, | 1830 int64_t object_store_id, |
| 1855 scoped_refptr<IndexedDBCallbacks> callbacks, | 1831 scoped_refptr<IndexedDBCallbacks> callbacks, |
| 1856 IndexedDBTransaction* transaction) { | 1832 IndexedDBTransaction* transaction) { |
| 1857 IDB_TRACE1("IndexedDBDatabase::ClearOperation", "txn.id", transaction->id()); | 1833 IDB_TRACE1("IndexedDBDatabase::ClearOperation", "txn.id", transaction->id()); |
| 1858 leveldb::Status s = backing_store_->ClearObjectStore( | 1834 leveldb::Status s = backing_store_->ClearObjectStore( |
| 1859 transaction->BackingStoreTransaction(), id(), object_store_id); | 1835 transaction->BackingStoreTransaction(), id(), object_store_id); |
| 1860 if (!s.ok()) { | 1836 if (!s.ok()) { |
| 1861 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1837 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1862 "Internal error clearing object store"); | 1838 "Internal error clearing object store"); |
| 1863 callbacks->OnError(error); | 1839 callbacks->OnError(error); |
| 1864 if (s.IsCorruption()) { | 1840 return s; |
| 1865 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1866 } | |
| 1867 return; | |
| 1868 } | 1841 } |
| 1869 callbacks->OnSuccess(); | 1842 callbacks->OnSuccess(); |
| 1870 | 1843 |
| 1871 FilterObservation(transaction, object_store_id, blink::WebIDBClear, | 1844 FilterObservation(transaction, object_store_id, blink::WebIDBClear, |
| 1872 IndexedDBKeyRange()); | 1845 IndexedDBKeyRange()); |
| 1846 return s; |
| 1873 } | 1847 } |
| 1874 | 1848 |
| 1875 void IndexedDBDatabase::DeleteObjectStoreOperation( | 1849 leveldb::Status IndexedDBDatabase::DeleteObjectStoreOperation( |
| 1876 int64_t object_store_id, | 1850 int64_t object_store_id, |
| 1877 IndexedDBTransaction* transaction) { | 1851 IndexedDBTransaction* transaction) { |
| 1878 IDB_TRACE1("IndexedDBDatabase::DeleteObjectStoreOperation", | 1852 IDB_TRACE1("IndexedDBDatabase::DeleteObjectStoreOperation", |
| 1879 "txn.id", | 1853 "txn.id", |
| 1880 transaction->id()); | 1854 transaction->id()); |
| 1881 | 1855 |
| 1882 const IndexedDBObjectStoreMetadata object_store_metadata = | 1856 const IndexedDBObjectStoreMetadata object_store_metadata = |
| 1883 metadata_.object_stores[object_store_id]; | 1857 metadata_.object_stores[object_store_id]; |
| 1884 leveldb::Status s = | 1858 leveldb::Status s = |
| 1885 backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(), | 1859 backing_store_->DeleteObjectStore(transaction->BackingStoreTransaction(), |
| 1886 transaction->database()->id(), | 1860 transaction->database()->id(), |
| 1887 object_store_id); | 1861 object_store_id); |
| 1888 if (!s.ok()) { | 1862 if (!s.ok()) { |
| 1889 base::string16 error_string = | 1863 base::string16 error_string = |
| 1890 ASCIIToUTF16("Internal error deleting object store '") + | 1864 ASCIIToUTF16("Internal error deleting object store '") + |
| 1891 object_store_metadata.name + ASCIIToUTF16("'."); | 1865 object_store_metadata.name + ASCIIToUTF16("'."); |
| 1892 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1866 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
| 1893 error_string); | 1867 error_string); |
| 1894 transaction->Abort(error); | 1868 transaction->Abort(error); |
| 1895 if (s.IsCorruption()) | 1869 return s; |
| 1896 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1897 return; | |
| 1898 } | 1870 } |
| 1899 | 1871 |
| 1900 RemoveObjectStore(object_store_id); | 1872 RemoveObjectStore(object_store_id); |
| 1901 transaction->ScheduleAbortTask( | 1873 transaction->ScheduleAbortTask( |
| 1902 base::Bind(&IndexedDBDatabase::DeleteObjectStoreAbortOperation, | 1874 base::Bind(&IndexedDBDatabase::DeleteObjectStoreAbortOperation, |
| 1903 this, | 1875 this, |
| 1904 object_store_metadata)); | 1876 object_store_metadata)); |
| 1877 return s; |
| 1905 } | 1878 } |
| 1906 | 1879 |
| 1907 void IndexedDBDatabase::VersionChangeOperation( | 1880 leveldb::Status IndexedDBDatabase::VersionChangeOperation( |
| 1908 int64_t version, | 1881 int64_t version, |
| 1909 scoped_refptr<IndexedDBCallbacks> callbacks, | 1882 scoped_refptr<IndexedDBCallbacks> callbacks, |
| 1910 IndexedDBTransaction* transaction) { | 1883 IndexedDBTransaction* transaction) { |
| 1911 IDB_TRACE1( | 1884 IDB_TRACE1( |
| 1912 "IndexedDBDatabase::VersionChangeOperation", "txn.id", transaction->id()); | 1885 "IndexedDBDatabase::VersionChangeOperation", "txn.id", transaction->id()); |
| 1913 int64_t old_version = metadata_.version; | 1886 int64_t old_version = metadata_.version; |
| 1914 DCHECK_GT(version, old_version); | 1887 DCHECK_GT(version, old_version); |
| 1915 | 1888 |
| 1916 if (!backing_store_->UpdateIDBDatabaseIntVersion( | 1889 backing_store_->UpdateIDBDatabaseIntVersion( |
| 1917 transaction->BackingStoreTransaction(), id(), version)) { | 1890 transaction->BackingStoreTransaction(), id(), version); |
| 1918 IndexedDBDatabaseError error( | |
| 1919 blink::WebIDBDatabaseExceptionUnknownError, | |
| 1920 ASCIIToUTF16( | |
| 1921 "Internal error writing data to stable storage when " | |
| 1922 "updating version.")); | |
| 1923 callbacks->OnError(error); | |
| 1924 transaction->Abort(error); | |
| 1925 return; | |
| 1926 } | |
| 1927 | 1891 |
| 1928 transaction->ScheduleAbortTask( | 1892 transaction->ScheduleAbortTask( |
| 1929 base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation, this, | 1893 base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation, this, |
| 1930 metadata_.version)); | 1894 metadata_.version)); |
| 1931 metadata_.version = version; | 1895 metadata_.version = version; |
| 1932 | 1896 |
| 1933 active_request_->UpgradeTransactionStarted(old_version); | 1897 active_request_->UpgradeTransactionStarted(old_version); |
| 1898 return leveldb::Status::OK(); |
| 1934 } | 1899 } |
| 1935 | 1900 |
| 1936 void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction, | 1901 void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction, |
| 1937 bool committed) { | 1902 bool committed) { |
| 1938 IDB_TRACE1("IndexedDBTransaction::TransactionFinished", "txn.id", id()); | 1903 IDB_TRACE1("IndexedDBTransaction::TransactionFinished", "txn.id", id()); |
| 1939 DCHECK(transactions_.find(transaction->id()) != transactions_.end()); | 1904 DCHECK(transactions_.find(transaction->id()) != transactions_.end()); |
| 1940 DCHECK_EQ(transactions_[transaction->id()], transaction); | 1905 DCHECK_EQ(transactions_[transaction->id()], transaction); |
| 1941 transactions_.erase(transaction->id()); | 1906 transactions_.erase(transaction->id()); |
| 1942 | 1907 |
| 1943 // This may be an unrelated transaction finishing while waiting for | 1908 // This may be an unrelated transaction finishing while waiting for |
| 1944 // connections to close, or the actual upgrade transaction from an active | 1909 // connections to close, or the actual upgrade transaction from an active |
| 1945 // request. Notify the active request if it's the latter. | 1910 // request. Notify the active request if it's the latter. |
| 1946 if (active_request_ && | 1911 if (active_request_ && |
| 1947 transaction->mode() == blink::WebIDBTransactionModeVersionChange) { | 1912 transaction->mode() == blink::WebIDBTransactionModeVersionChange) { |
| 1948 active_request_->UpgradeTransactionFinished(committed); | 1913 active_request_->UpgradeTransactionFinished(committed); |
| 1949 } | 1914 } |
| 1950 } | 1915 } |
| 1951 | 1916 |
| 1952 void IndexedDBDatabase::TransactionCommitFailed(const leveldb::Status& status) { | |
| 1953 if (status.IsCorruption()) { | |
| 1954 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | |
| 1955 "Error committing transaction"); | |
| 1956 factory_->HandleBackingStoreCorruption(backing_store_->origin(), error); | |
| 1957 } else { | |
| 1958 factory_->HandleBackingStoreFailure(backing_store_->origin()); | |
| 1959 } | |
| 1960 } | |
| 1961 | |
| 1962 void IndexedDBDatabase::AppendRequest( | 1917 void IndexedDBDatabase::AppendRequest( |
| 1963 std::unique_ptr<ConnectionRequest> request) { | 1918 std::unique_ptr<ConnectionRequest> request) { |
| 1964 pending_requests_.push(std::move(request)); | 1919 pending_requests_.push(std::move(request)); |
| 1965 | 1920 |
| 1966 if (!active_request_) | 1921 if (!active_request_) |
| 1967 ProcessRequestQueue(); | 1922 ProcessRequestQueue(); |
| 1968 } | 1923 } |
| 1969 | 1924 |
| 1970 void IndexedDBDatabase::RequestComplete(ConnectionRequest* request) { | 1925 void IndexedDBDatabase::RequestComplete(ConnectionRequest* request) { |
| 1971 DCHECK_EQ(request, active_request_.get()); | 1926 DCHECK_EQ(request, active_request_.get()); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2086 // If there are no more connections (current, active, or pending), tell the | 2041 // If there are no more connections (current, active, or pending), tell the |
| 2087 // factory to clean us up. | 2042 // factory to clean us up. |
| 2088 if (connections_.empty() && !active_request_ && pending_requests_.empty()) { | 2043 if (connections_.empty() && !active_request_ && pending_requests_.empty()) { |
| 2089 DCHECK(transactions_.empty()); | 2044 DCHECK(transactions_.empty()); |
| 2090 backing_store_ = nullptr; | 2045 backing_store_ = nullptr; |
| 2091 factory_->ReleaseDatabase(identifier_, forced); | 2046 factory_->ReleaseDatabase(identifier_, forced); |
| 2092 } | 2047 } |
| 2093 } | 2048 } |
| 2094 | 2049 |
| 2095 void IndexedDBDatabase::CreateObjectStoreAbortOperation( | 2050 void IndexedDBDatabase::CreateObjectStoreAbortOperation( |
| 2096 int64_t object_store_id, | 2051 int64_t object_store_id) { |
| 2097 IndexedDBTransaction* transaction) { | |
| 2098 DCHECK(!transaction); | |
| 2099 IDB_TRACE("IndexedDBDatabase::CreateObjectStoreAbortOperation"); | 2052 IDB_TRACE("IndexedDBDatabase::CreateObjectStoreAbortOperation"); |
| 2100 RemoveObjectStore(object_store_id); | 2053 RemoveObjectStore(object_store_id); |
| 2101 } | 2054 } |
| 2102 | 2055 |
| 2103 void IndexedDBDatabase::DeleteObjectStoreAbortOperation( | 2056 void IndexedDBDatabase::DeleteObjectStoreAbortOperation( |
| 2104 const IndexedDBObjectStoreMetadata& object_store_metadata, | 2057 const IndexedDBObjectStoreMetadata& object_store_metadata) { |
| 2105 IndexedDBTransaction* transaction) { | |
| 2106 DCHECK(!transaction); | |
| 2107 IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreAbortOperation"); | 2058 IDB_TRACE("IndexedDBDatabase::DeleteObjectStoreAbortOperation"); |
| 2108 AddObjectStore(object_store_metadata, | 2059 AddObjectStore(object_store_metadata, |
| 2109 IndexedDBObjectStoreMetadata::kInvalidId); | 2060 IndexedDBObjectStoreMetadata::kInvalidId); |
| 2110 } | 2061 } |
| 2111 | 2062 |
| 2112 void IndexedDBDatabase::RenameObjectStoreAbortOperation( | 2063 void IndexedDBDatabase::RenameObjectStoreAbortOperation( |
| 2113 int64_t object_store_id, | 2064 int64_t object_store_id, |
| 2114 const base::string16& old_name, | 2065 const base::string16& old_name) { |
| 2115 IndexedDBTransaction* transaction) { | |
| 2116 DCHECK(!transaction); | |
| 2117 IDB_TRACE("IndexedDBDatabase::RenameObjectStoreAbortOperation"); | 2066 IDB_TRACE("IndexedDBDatabase::RenameObjectStoreAbortOperation"); |
| 2118 SetObjectStoreName(object_store_id, old_name); | 2067 SetObjectStoreName(object_store_id, old_name); |
| 2119 } | 2068 } |
| 2120 | 2069 |
| 2121 void IndexedDBDatabase::VersionChangeAbortOperation( | 2070 void IndexedDBDatabase::VersionChangeAbortOperation(int64_t previous_version) { |
| 2122 int64_t previous_version, | |
| 2123 IndexedDBTransaction* transaction) { | |
| 2124 DCHECK(!transaction); | |
| 2125 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); | 2071 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); |
| 2126 metadata_.version = previous_version; | 2072 metadata_.version = previous_version; |
| 2127 } | 2073 } |
| 2128 | 2074 |
| 2129 } // namespace content | 2075 } // namespace content |
| OLD | NEW |