Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(406)

Side by Side Diff: content/browser/indexed_db/indexed_db_database.cc

Issue 237143006: Make iterating over a corrupted IndexedDB fail. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/indexed_db_database.h" 5 #include "content/browser/indexed_db/indexed_db_database.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 #include <set> 8 #include <set>
9 9
10 #include "base/auto_reset.h" 10 #include "base/auto_reset.h"
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; } 85 scoped_refptr<IndexedDBCallbacks> callbacks() const { return callbacks_; }
86 86
87 private: 87 private:
88 scoped_refptr<IndexedDBCallbacks> callbacks_; 88 scoped_refptr<IndexedDBCallbacks> callbacks_;
89 }; 89 };
90 90
91 scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create( 91 scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create(
92 const base::string16& name, 92 const base::string16& name,
93 IndexedDBBackingStore* backing_store, 93 IndexedDBBackingStore* backing_store,
94 IndexedDBFactory* factory, 94 IndexedDBFactory* factory,
95 const Identifier& unique_identifier) { 95 const Identifier& unique_identifier,
96 leveldb::Status& s) {
96 scoped_refptr<IndexedDBDatabase> database = 97 scoped_refptr<IndexedDBDatabase> database =
97 new IndexedDBDatabase(name, backing_store, factory, unique_identifier); 98 new IndexedDBDatabase(name, backing_store, factory, unique_identifier);
98 if (!database->OpenInternal().ok()) 99 s = database->OpenInternal();
99 return 0; 100 return s.ok() ? database : 0;
jsbell 2014/04/14 20:44:20 Does this compile everywhere? The trinary operator
cmumford 2014/04/14 23:39:23 I didn't compile it everywhere. I'll be safe and g
100 return database;
101 } 101 }
102 102
103 namespace { 103 namespace {
104 const base::string16::value_type kNoStringVersion[] = {0}; 104 const base::string16::value_type kNoStringVersion[] = {0};
105 } 105 }
106 106
107 IndexedDBDatabase::IndexedDBDatabase(const base::string16& name, 107 IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
108 IndexedDBBackingStore* backing_store, 108 IndexedDBBackingStore* backing_store,
109 IndexedDBFactory* factory, 109 IndexedDBFactory* factory,
110 const Identifier& unique_identifier) 110 const Identifier& unique_identifier)
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 IndexedDBTransaction* transaction) { 520 IndexedDBTransaction* transaction) {
521 IDB_TRACE("IndexedDBDatabase::GetOperation"); 521 IDB_TRACE("IndexedDBDatabase::GetOperation");
522 522
523 DCHECK(metadata_.object_stores.find(object_store_id) != 523 DCHECK(metadata_.object_stores.find(object_store_id) !=
524 metadata_.object_stores.end()); 524 metadata_.object_stores.end());
525 const IndexedDBObjectStoreMetadata& object_store_metadata = 525 const IndexedDBObjectStoreMetadata& object_store_metadata =
526 metadata_.object_stores[object_store_id]; 526 metadata_.object_stores[object_store_id];
527 527
528 const IndexedDBKey* key; 528 const IndexedDBKey* key;
529 529
530 leveldb::Status s;
530 scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; 531 scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
531 if (key_range->IsOnlyKey()) { 532 if (key_range->IsOnlyKey()) {
532 key = &key_range->lower(); 533 key = &key_range->lower();
533 } else { 534 } else {
534 if (index_id == IndexedDBIndexMetadata::kInvalidId) { 535 if (index_id == IndexedDBIndexMetadata::kInvalidId) {
535 DCHECK_NE(cursor_type, indexed_db::CURSOR_KEY_ONLY); 536 DCHECK_NE(cursor_type, indexed_db::CURSOR_KEY_ONLY);
536 // ObjectStore Retrieval Operation 537 // ObjectStore Retrieval Operation
537 backing_store_cursor = backing_store_->OpenObjectStoreCursor( 538 backing_store_cursor = backing_store_->OpenObjectStoreCursor(
538 transaction->BackingStoreTransaction(), 539 transaction->BackingStoreTransaction(),
539 id(), 540 id(),
540 object_store_id, 541 object_store_id,
541 *key_range, 542 *key_range,
542 indexed_db::CURSOR_NEXT); 543 indexed_db::CURSOR_NEXT,
544 s);
543 } else if (cursor_type == indexed_db::CURSOR_KEY_ONLY) { 545 } else if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
544 // Index Value Retrieval Operation 546 // Index Value Retrieval Operation
545 backing_store_cursor = backing_store_->OpenIndexKeyCursor( 547 backing_store_cursor = backing_store_->OpenIndexKeyCursor(
546 transaction->BackingStoreTransaction(), 548 transaction->BackingStoreTransaction(),
547 id(), 549 id(),
548 object_store_id, 550 object_store_id,
549 index_id, 551 index_id,
550 *key_range, 552 *key_range,
551 indexed_db::CURSOR_NEXT); 553 indexed_db::CURSOR_NEXT,
554 s);
552 } else { 555 } else {
553 // Index Referenced Value Retrieval Operation 556 // Index Referenced Value Retrieval Operation
554 backing_store_cursor = backing_store_->OpenIndexCursor( 557 backing_store_cursor = backing_store_->OpenIndexCursor(
555 transaction->BackingStoreTransaction(), 558 transaction->BackingStoreTransaction(),
556 id(), 559 id(),
557 object_store_id, 560 object_store_id,
558 index_id, 561 index_id,
559 *key_range, 562 *key_range,
560 indexed_db::CURSOR_NEXT); 563 indexed_db::CURSOR_NEXT,
564 s);
565 }
566
567 if (!s.ok()) {
568 DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString();
569 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
570 "Internal error deleting data in range");
571 if (s.IsCorruption()) {
572 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
573 error);
574 }
561 } 575 }
562 576
563 if (!backing_store_cursor) { 577 if (!backing_store_cursor) {
564 callbacks->OnSuccess(); 578 callbacks->OnSuccess();
565 return; 579 return;
566 } 580 }
567 581
568 key = &backing_store_cursor->key(); 582 key = &backing_store_cursor->key();
569 } 583 }
570 584
571 scoped_ptr<IndexedDBKey> primary_key; 585 scoped_ptr<IndexedDBKey> primary_key;
572 leveldb::Status s;
573 if (index_id == IndexedDBIndexMetadata::kInvalidId) { 586 if (index_id == IndexedDBIndexMetadata::kInvalidId) {
574 // Object Store Retrieval Operation 587 // Object Store Retrieval Operation
575 IndexedDBValue value; 588 IndexedDBValue value;
576 s = backing_store_->GetRecord(transaction->BackingStoreTransaction(), 589 s = backing_store_->GetRecord(transaction->BackingStoreTransaction(),
577 id(), 590 id(),
578 object_store_id, 591 object_store_id,
579 *key, 592 *key,
580 &value); 593 &value);
581 if (!s.ok()) { 594 if (!s.ok()) {
582 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, 595 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 IndexedDBTransaction* transaction) { 1036 IndexedDBTransaction* transaction) {
1024 IDB_TRACE("IndexedDBDatabase::OpenCursorOperation"); 1037 IDB_TRACE("IndexedDBDatabase::OpenCursorOperation");
1025 1038
1026 // The frontend has begun indexing, so this pauses the transaction 1039 // The frontend has begun indexing, so this pauses the transaction
1027 // until the indexing is complete. This can't happen any earlier 1040 // until the indexing is complete. This can't happen any earlier
1028 // because we don't want to switch to early mode in case multiple 1041 // because we don't want to switch to early mode in case multiple
1029 // indexes are being created in a row, with Put()'s in between. 1042 // indexes are being created in a row, with Put()'s in between.
1030 if (params->task_type == IndexedDBDatabase::PREEMPTIVE_TASK) 1043 if (params->task_type == IndexedDBDatabase::PREEMPTIVE_TASK)
1031 transaction->AddPreemptiveEvent(); 1044 transaction->AddPreemptiveEvent();
1032 1045
1046 leveldb::Status s;
1033 scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; 1047 scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
1034 if (params->index_id == IndexedDBIndexMetadata::kInvalidId) { 1048 if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
1035 if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) { 1049 if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1036 DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK); 1050 DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
1037 backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor( 1051 backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1038 transaction->BackingStoreTransaction(), 1052 transaction->BackingStoreTransaction(),
1039 id(), 1053 id(),
1040 params->object_store_id, 1054 params->object_store_id,
1041 *params->key_range, 1055 *params->key_range,
1042 params->direction); 1056 params->direction,
1057 s);
1043 } else { 1058 } else {
1044 backing_store_cursor = backing_store_->OpenObjectStoreCursor( 1059 backing_store_cursor = backing_store_->OpenObjectStoreCursor(
1045 transaction->BackingStoreTransaction(), 1060 transaction->BackingStoreTransaction(),
1046 id(), 1061 id(),
1047 params->object_store_id, 1062 params->object_store_id,
1048 *params->key_range, 1063 *params->key_range,
1049 params->direction); 1064 params->direction,
1065 s);
1050 } 1066 }
1051 } else { 1067 } else {
1052 DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK); 1068 DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
1053 if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) { 1069 if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
1054 backing_store_cursor = backing_store_->OpenIndexKeyCursor( 1070 backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1055 transaction->BackingStoreTransaction(), 1071 transaction->BackingStoreTransaction(),
1056 id(), 1072 id(),
1057 params->object_store_id, 1073 params->object_store_id,
1058 params->index_id, 1074 params->index_id,
1059 *params->key_range, 1075 *params->key_range,
1060 params->direction); 1076 params->direction,
1077 s);
1061 } else { 1078 } else {
1062 backing_store_cursor = backing_store_->OpenIndexCursor( 1079 backing_store_cursor = backing_store_->OpenIndexCursor(
1063 transaction->BackingStoreTransaction(), 1080 transaction->BackingStoreTransaction(),
1064 id(), 1081 id(),
1065 params->object_store_id, 1082 params->object_store_id,
1066 params->index_id, 1083 params->index_id,
1067 *params->key_range, 1084 *params->key_range,
1068 params->direction); 1085 params->direction,
1086 s);
1087 }
1088 }
1089
1090 if (!s.ok()) {
1091 DLOG(ERROR) << "Unable to open cursor operation: " << s.ToString();
1092 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
1093 "Internal error opening cursor operation");
1094 if (s.IsCorruption()) {
1095 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
1096 error);
1069 } 1097 }
1070 } 1098 }
1071 1099
1072 if (!backing_store_cursor) { 1100 if (!backing_store_cursor) {
1101 // Why is Success being called?
jsbell 2014/04/14 20:44:20 In script, if a cursor is opened and there's nothi
cmumford 2014/04/14 23:39:23 Are you saying that if the db is corrupt you want
jsbell 2014/04/15 16:39:57 I'm just answering the question "Why is Success be
1073 params->callbacks->OnSuccess(static_cast<IndexedDBValue*>(NULL)); 1102 params->callbacks->OnSuccess(static_cast<IndexedDBValue*>(NULL));
1074 return; 1103 return;
1075 } 1104 }
1076 1105
1077 scoped_refptr<IndexedDBCursor> cursor = 1106 scoped_refptr<IndexedDBCursor> cursor =
1078 new IndexedDBCursor(backing_store_cursor.Pass(), 1107 new IndexedDBCursor(backing_store_cursor.Pass(),
1079 params->cursor_type, 1108 params->cursor_type,
1080 params->task_type, 1109 params->task_type,
1081 transaction); 1110 transaction);
1082 params->callbacks->OnSuccess( 1111 params->callbacks->OnSuccess(
(...skipping 24 matching lines...) Expand all
1107 void IndexedDBDatabase::CountOperation( 1136 void IndexedDBDatabase::CountOperation(
1108 int64 object_store_id, 1137 int64 object_store_id,
1109 int64 index_id, 1138 int64 index_id,
1110 scoped_ptr<IndexedDBKeyRange> key_range, 1139 scoped_ptr<IndexedDBKeyRange> key_range,
1111 scoped_refptr<IndexedDBCallbacks> callbacks, 1140 scoped_refptr<IndexedDBCallbacks> callbacks,
1112 IndexedDBTransaction* transaction) { 1141 IndexedDBTransaction* transaction) {
1113 IDB_TRACE("IndexedDBDatabase::CountOperation"); 1142 IDB_TRACE("IndexedDBDatabase::CountOperation");
1114 uint32 count = 0; 1143 uint32 count = 0;
1115 scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor; 1144 scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
1116 1145
1146 leveldb::Status s;
1117 if (index_id == IndexedDBIndexMetadata::kInvalidId) { 1147 if (index_id == IndexedDBIndexMetadata::kInvalidId) {
1118 backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor( 1148 backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
1119 transaction->BackingStoreTransaction(), 1149 transaction->BackingStoreTransaction(),
1120 id(), 1150 id(),
1121 object_store_id, 1151 object_store_id,
1122 *key_range, 1152 *key_range,
1123 indexed_db::CURSOR_NEXT); 1153 indexed_db::CURSOR_NEXT,
1154 s);
1124 } else { 1155 } else {
1125 backing_store_cursor = backing_store_->OpenIndexKeyCursor( 1156 backing_store_cursor = backing_store_->OpenIndexKeyCursor(
1126 transaction->BackingStoreTransaction(), 1157 transaction->BackingStoreTransaction(),
1127 id(), 1158 id(),
1128 object_store_id, 1159 object_store_id,
1129 index_id, 1160 index_id,
1130 *key_range, 1161 *key_range,
1131 indexed_db::CURSOR_NEXT); 1162 indexed_db::CURSOR_NEXT,
1163 s);
1164 }
1165 if (!s.ok()) {
1166 DLOG(ERROR) << "Unable perform count operation: " << s.ToString();
1167 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
1168 "Internal error performing count operation");
1169 if (s.IsCorruption()) {
1170 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
1171 error);
1172 }
1132 } 1173 }
1133 if (!backing_store_cursor) { 1174 if (!backing_store_cursor) {
1134 callbacks->OnSuccess(count); 1175 callbacks->OnSuccess(count);
1135 return; 1176 return;
1136 } 1177 }
1137 1178
1138 do { 1179 do {
1139 ++count; 1180 ++count;
1140 } while (backing_store_cursor->Continue()); 1181 } while (backing_store_cursor->Continue(s));
1182
1183 // Should probably check for corruption here too?
jsbell 2014/04/14 20:44:20 Make this a TODO
cmumford 2014/04/14 23:39:23 Done.
1141 1184
1142 callbacks->OnSuccess(count); 1185 callbacks->OnSuccess(count);
1143 } 1186 }
1144 1187
1145 void IndexedDBDatabase::DeleteRange( 1188 void IndexedDBDatabase::DeleteRange(
1146 int64 transaction_id, 1189 int64 transaction_id,
1147 int64 object_store_id, 1190 int64 object_store_id,
1148 scoped_ptr<IndexedDBKeyRange> key_range, 1191 scoped_ptr<IndexedDBKeyRange> key_range,
1149 scoped_refptr<IndexedDBCallbacks> callbacks) { 1192 scoped_refptr<IndexedDBCallbacks> callbacks) {
1150 IDB_TRACE("IndexedDBDatabase::DeleteRange"); 1193 IDB_TRACE("IndexedDBDatabase::DeleteRange");
(...skipping 11 matching lines...) Expand all
1162 base::Passed(&key_range), 1205 base::Passed(&key_range),
1163 callbacks)); 1206 callbacks));
1164 } 1207 }
1165 1208
1166 void IndexedDBDatabase::DeleteRangeOperation( 1209 void IndexedDBDatabase::DeleteRangeOperation(
1167 int64 object_store_id, 1210 int64 object_store_id,
1168 scoped_ptr<IndexedDBKeyRange> key_range, 1211 scoped_ptr<IndexedDBKeyRange> key_range,
1169 scoped_refptr<IndexedDBCallbacks> callbacks, 1212 scoped_refptr<IndexedDBCallbacks> callbacks,
1170 IndexedDBTransaction* transaction) { 1213 IndexedDBTransaction* transaction) {
1171 IDB_TRACE("IndexedDBDatabase::DeleteRangeOperation"); 1214 IDB_TRACE("IndexedDBDatabase::DeleteRangeOperation");
1215 leveldb::Status s;
1172 scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor = 1216 scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor =
1173 backing_store_->OpenObjectStoreCursor( 1217 backing_store_->OpenObjectStoreCursor(
1174 transaction->BackingStoreTransaction(), 1218 transaction->BackingStoreTransaction(),
1175 id(), 1219 id(),
1176 object_store_id, 1220 object_store_id,
1177 *key_range, 1221 *key_range,
1178 indexed_db::CURSOR_NEXT); 1222 indexed_db::CURSOR_NEXT,
1179 if (backing_store_cursor) { 1223 s);
1224 if (backing_store_cursor && s.ok()) {
1180 do { 1225 do {
1181 if (!backing_store_->DeleteRecord( 1226 if (!backing_store_->DeleteRecord(
1182 transaction->BackingStoreTransaction(), 1227 transaction->BackingStoreTransaction(),
1183 id(), 1228 id(),
1184 object_store_id, 1229 object_store_id,
1185 backing_store_cursor->record_identifier()) 1230 backing_store_cursor->record_identifier())
1186 .ok()) { 1231 .ok()) {
1187 callbacks->OnError( 1232 callbacks->OnError(
1188 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, 1233 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
1189 "Internal error deleting data in range")); 1234 "Internal error deleting data in range"));
1190 return; 1235 return;
1191 } 1236 }
1192 } while (backing_store_cursor->Continue()); 1237 } while (backing_store_cursor->Continue(s));
1238 }
1239
1240 if (!s.ok()) {
1241 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
1242 ASCIIToUTF16("Internal error deleting range"));
1243 transaction->Abort(error);
1244 if (s.IsCorruption()) {
1245 factory_->HandleBackingStoreCorruption(backing_store_->origin_url(),
1246 error);
1247 }
1248 return;
1193 } 1249 }
1194 1250
1195 callbacks->OnSuccess(); 1251 callbacks->OnSuccess();
1196 } 1252 }
1197 1253
1198 void IndexedDBDatabase::Clear(int64 transaction_id, 1254 void IndexedDBDatabase::Clear(int64 transaction_id,
1199 int64 object_store_id, 1255 int64 object_store_id,
1200 scoped_refptr<IndexedDBCallbacks> callbacks) { 1256 scoped_refptr<IndexedDBCallbacks> callbacks) {
1201 IDB_TRACE("IndexedDBDatabase::Clear"); 1257 IDB_TRACE("IndexedDBDatabase::Clear");
1202 IndexedDBTransaction* transaction = GetTransaction(transaction_id); 1258 IndexedDBTransaction* transaction = GetTransaction(transaction_id);
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after
1692 const base::string16& previous_version, 1748 const base::string16& previous_version,
1693 int64 previous_int_version, 1749 int64 previous_int_version,
1694 IndexedDBTransaction* transaction) { 1750 IndexedDBTransaction* transaction) {
1695 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); 1751 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation");
1696 DCHECK(!transaction); 1752 DCHECK(!transaction);
1697 metadata_.version = previous_version; 1753 metadata_.version = previous_version;
1698 metadata_.int_version = previous_int_version; 1754 metadata_.int_version = previous_int_version;
1699 } 1755 }
1700 1756
1701 } // namespace content 1757 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698