Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/indexed_db/indexed_db_backing_store.h" | 5 #include "content/browser/indexed_db/indexed_db_backing_store.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/json/json_reader.h" | 9 #include "base/json/json_reader.h" |
| 10 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "content/browser/child_process_security_policy_impl.h" | |
| 16 #include "content/browser/indexed_db/indexed_db_blob_info.h" | |
| 15 #include "content/browser/indexed_db/indexed_db_database_error.h" | 17 #include "content/browser/indexed_db/indexed_db_database_error.h" |
| 16 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" | 18 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" |
| 17 #include "content/browser/indexed_db/indexed_db_metadata.h" | 19 #include "content/browser/indexed_db/indexed_db_metadata.h" |
| 18 #include "content/browser/indexed_db/indexed_db_tracing.h" | 20 #include "content/browser/indexed_db/indexed_db_tracing.h" |
| 19 #include "content/browser/indexed_db/indexed_db_value.h" | 21 #include "content/browser/indexed_db/indexed_db_value.h" |
| 20 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h" | 22 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h" |
| 21 #include "content/browser/indexed_db/leveldb/leveldb_database.h" | 23 #include "content/browser/indexed_db/leveldb/leveldb_database.h" |
| 22 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h" | 24 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h" |
| 23 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" | 25 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" |
| 24 #include "content/common/indexed_db/indexed_db_key.h" | 26 #include "content/common/indexed_db/indexed_db_key.h" |
| 25 #include "content/common/indexed_db/indexed_db_key_path.h" | 27 #include "content/common/indexed_db/indexed_db_key_path.h" |
| 26 #include "content/common/indexed_db/indexed_db_key_range.h" | 28 #include "content/common/indexed_db/indexed_db_key_range.h" |
| 27 #include "third_party/WebKit/public/platform/WebIDBTypes.h" | 29 #include "third_party/WebKit/public/platform/WebIDBTypes.h" |
| 28 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h" | 30 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h" |
| 29 #include "third_party/leveldatabase/env_chromium.h" | 31 #include "third_party/leveldatabase/env_chromium.h" |
| 32 #include "webkit/browser/blob/blob_data_handle.h" | |
| 30 #include "webkit/common/database/database_identifier.h" | 33 #include "webkit/common/database/database_identifier.h" |
| 31 | 34 |
| 32 using base::StringPiece; | 35 using base::StringPiece; |
| 33 | 36 |
| 34 namespace content { | 37 namespace content { |
| 35 | 38 |
| 36 namespace { | 39 namespace { |
| 37 | 40 |
| 38 static std::string ComputeOriginIdentifier(const GURL& origin_url) { | 41 static std::string ComputeOriginIdentifier(const GURL& origin_url) { |
| 39 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1"; | 42 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1"; |
| 40 } | 43 } |
| 41 | 44 |
| 42 static base::FilePath ComputeFileName(const GURL& origin_url) { | 45 static base::FilePath ComputeFileName(const GURL& origin_url) { |
| 43 return base::FilePath() | 46 return base::FilePath() |
| 44 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url)) | 47 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url)) |
| 45 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb")); | 48 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb")); |
| 46 } | 49 } |
| 47 | 50 |
| 51 static base::FilePath ComputeBlobPath(const GURL& origin_url) { | |
| 52 return base::FilePath() | |
| 53 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url)) | |
| 54 .AddExtension(FILE_PATH_LITERAL(".indexeddb.blob")); | |
|
cmumford
2014/04/10 16:59:43
Nit: Consider removing leading '.' as FilePath::kE
jsbell
2014/04/11 16:19:57
Can you give an example of where this would be pro
ericu
2014/04/14 23:23:38
It need not be an extension separator as long as i
| |
| 55 } | |
| 56 | |
| 48 static base::FilePath ComputeCorruptionFileName(const GURL& origin_url) { | 57 static base::FilePath ComputeCorruptionFileName(const GURL& origin_url) { |
| 49 return ComputeFileName(origin_url) | 58 return ComputeFileName(origin_url) |
| 50 .Append(FILE_PATH_LITERAL("corruption_info.json")); | 59 .Append(FILE_PATH_LITERAL("corruption_info.json")); |
| 51 } | 60 } |
| 52 | 61 |
| 53 } // namespace | 62 } // namespace |
| 54 | 63 |
| 55 static const int64 kKeyGeneratorInitialNumber = | 64 static const int64 kKeyGeneratorInitialNumber = |
| 56 1; // From the IndexedDB specification. | 65 1; // From the IndexedDB specification. |
| 57 | 66 |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 } | 426 } |
| 418 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name) | 427 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name) |
| 419 OVERRIDE { | 428 OVERRIDE { |
| 420 return LevelDBDatabase::Destroy(file_name); | 429 return LevelDBDatabase::Destroy(file_name); |
| 421 } | 430 } |
| 422 }; | 431 }; |
| 423 | 432 |
| 424 IndexedDBBackingStore::IndexedDBBackingStore( | 433 IndexedDBBackingStore::IndexedDBBackingStore( |
| 425 IndexedDBFactory* indexed_db_factory, | 434 IndexedDBFactory* indexed_db_factory, |
| 426 const GURL& origin_url, | 435 const GURL& origin_url, |
| 436 const base::FilePath& blob_path, | |
| 427 scoped_ptr<LevelDBDatabase> db, | 437 scoped_ptr<LevelDBDatabase> db, |
| 428 scoped_ptr<LevelDBComparator> comparator, | 438 scoped_ptr<LevelDBComparator> comparator, |
| 429 base::TaskRunner* task_runner) | 439 base::TaskRunner* task_runner) |
| 430 : indexed_db_factory_(indexed_db_factory), | 440 : indexed_db_factory_(indexed_db_factory), |
| 431 origin_url_(origin_url), | 441 origin_url_(origin_url), |
| 442 blob_path_(blob_path), | |
| 432 origin_identifier_(ComputeOriginIdentifier(origin_url)), | 443 origin_identifier_(ComputeOriginIdentifier(origin_url)), |
| 433 task_runner_(task_runner), | 444 task_runner_(task_runner), |
| 434 db_(db.Pass()), | 445 db_(db.Pass()), |
| 435 comparator_(comparator.Pass()), | 446 comparator_(comparator.Pass()), |
| 436 active_blob_registry_(this) {} | 447 active_blob_registry_(this) {} |
| 437 | 448 |
| 438 IndexedDBBackingStore::~IndexedDBBackingStore() { | 449 IndexedDBBackingStore::~IndexedDBBackingStore() { |
| 450 if (!blob_path_.empty() && !child_process_ids_granted_.empty()) { | |
| 451 ChildProcessSecurityPolicyImpl* policy = | |
| 452 ChildProcessSecurityPolicyImpl::GetInstance(); | |
| 453 for (std::set<int>::iterator iter = child_process_ids_granted_.begin(); | |
|
cmumford
2014/04/10 16:59:43
Nit: const_iterator?
ericu
2014/04/14 23:23:38
Done.
| |
| 454 iter != child_process_ids_granted_.end(); | |
| 455 ++iter) { | |
| 456 policy->RevokeAllPermissionsForFile(*iter, blob_path_); | |
| 457 } | |
| 458 } | |
| 439 // db_'s destructor uses comparator_. The order of destruction is important. | 459 // db_'s destructor uses comparator_. The order of destruction is important. |
| 440 db_.reset(); | 460 db_.reset(); |
| 441 comparator_.reset(); | 461 comparator_.reset(); |
| 442 } | 462 } |
| 443 | 463 |
| 444 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier( | 464 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier( |
| 445 const std::string& primary_key, | 465 const std::string& primary_key, |
| 446 int64 version) | 466 int64 version) |
| 447 : primary_key_(primary_key), version_(version) { | 467 : primary_key_(primary_key), version_(version) { |
| 448 DCHECK(!primary_key.empty()); | 468 DCHECK(!primary_key.empty()); |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 647 if (!base::CreateDirectory(path_base)) { | 667 if (!base::CreateDirectory(path_base)) { |
| 648 LOG(ERROR) << "Unable to create IndexedDB database path " | 668 LOG(ERROR) << "Unable to create IndexedDB database path " |
| 649 << path_base.AsUTF8Unsafe(); | 669 << path_base.AsUTF8Unsafe(); |
| 650 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY, | 670 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY, |
| 651 origin_url); | 671 origin_url); |
| 652 return scoped_refptr<IndexedDBBackingStore>(); | 672 return scoped_refptr<IndexedDBBackingStore>(); |
| 653 } | 673 } |
| 654 | 674 |
| 655 const base::FilePath file_path = | 675 const base::FilePath file_path = |
| 656 path_base.Append(ComputeFileName(origin_url)); | 676 path_base.Append(ComputeFileName(origin_url)); |
| 677 const base::FilePath blob_path = | |
| 678 path_base.Append(ComputeBlobPath(origin_url)); | |
| 657 | 679 |
| 658 if (IsPathTooLong(file_path)) { | 680 if (IsPathTooLong(file_path)) { |
| 659 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG, | 681 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG, |
| 660 origin_url); | 682 origin_url); |
| 661 return scoped_refptr<IndexedDBBackingStore>(); | 683 return scoped_refptr<IndexedDBBackingStore>(); |
| 662 } | 684 } |
| 663 | 685 |
| 664 scoped_ptr<LevelDBDatabase> db; | 686 scoped_ptr<LevelDBDatabase> db; |
| 665 leveldb::Status status = leveldb_factory->OpenLevelDB( | 687 leveldb::Status status = leveldb_factory->OpenLevelDB( |
| 666 file_path, comparator.get(), &db, is_disk_full); | 688 file_path, comparator.get(), &db, is_disk_full); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 742 | 764 |
| 743 if (!db) { | 765 if (!db) { |
| 744 NOTREACHED(); | 766 NOTREACHED(); |
| 745 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR, | 767 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR, |
| 746 origin_url); | 768 origin_url); |
| 747 return scoped_refptr<IndexedDBBackingStore>(); | 769 return scoped_refptr<IndexedDBBackingStore>(); |
| 748 } | 770 } |
| 749 | 771 |
| 750 return Create(indexed_db_factory, | 772 return Create(indexed_db_factory, |
| 751 origin_url, | 773 origin_url, |
| 774 blob_path, | |
| 752 db.Pass(), | 775 db.Pass(), |
| 753 comparator.Pass(), | 776 comparator.Pass(), |
| 754 task_runner); | 777 task_runner); |
| 755 } | 778 } |
| 756 | 779 |
| 757 // static | 780 // static |
| 758 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( | 781 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( |
| 759 const GURL& origin_url, | 782 const GURL& origin_url, |
| 760 base::TaskRunner* task_runner) { | 783 base::TaskRunner* task_runner) { |
| 761 DefaultLevelDBFactory leveldb_factory; | 784 DefaultLevelDBFactory leveldb_factory; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 776 if (!db) { | 799 if (!db) { |
| 777 LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed."; | 800 LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed."; |
| 778 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED, | 801 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED, |
| 779 origin_url); | 802 origin_url); |
| 780 return scoped_refptr<IndexedDBBackingStore>(); | 803 return scoped_refptr<IndexedDBBackingStore>(); |
| 781 } | 804 } |
| 782 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url); | 805 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url); |
| 783 | 806 |
| 784 return Create(NULL /* indexed_db_factory */, | 807 return Create(NULL /* indexed_db_factory */, |
| 785 origin_url, | 808 origin_url, |
| 809 base::FilePath(), | |
| 786 db.Pass(), | 810 db.Pass(), |
| 787 comparator.Pass(), | 811 comparator.Pass(), |
| 788 task_runner); | 812 task_runner); |
| 789 } | 813 } |
| 790 | 814 |
| 791 // static | 815 // static |
| 792 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( | 816 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( |
| 793 IndexedDBFactory* indexed_db_factory, | 817 IndexedDBFactory* indexed_db_factory, |
| 794 const GURL& origin_url, | 818 const GURL& origin_url, |
| 819 const base::FilePath& blob_path, | |
| 795 scoped_ptr<LevelDBDatabase> db, | 820 scoped_ptr<LevelDBDatabase> db, |
| 796 scoped_ptr<LevelDBComparator> comparator, | 821 scoped_ptr<LevelDBComparator> comparator, |
| 797 base::TaskRunner* task_runner) { | 822 base::TaskRunner* task_runner) { |
| 798 // TODO(jsbell): Handle comparator name changes. | 823 // TODO(jsbell): Handle comparator name changes. |
| 799 | 824 |
| 800 scoped_refptr<IndexedDBBackingStore> backing_store( | 825 scoped_refptr<IndexedDBBackingStore> backing_store( |
| 801 new IndexedDBBackingStore(indexed_db_factory, | 826 new IndexedDBBackingStore(indexed_db_factory, |
| 802 origin_url, | 827 origin_url, |
| 828 blob_path, | |
| 803 db.Pass(), | 829 db.Pass(), |
| 804 comparator.Pass(), | 830 comparator.Pass(), |
| 805 task_runner)); | 831 task_runner)); |
| 806 if (!SetUpMetadata(backing_store->db_.get(), | 832 if (!SetUpMetadata(backing_store->db_.get(), |
| 807 backing_store->origin_identifier_)) | 833 backing_store->origin_identifier_)) |
| 808 return scoped_refptr<IndexedDBBackingStore>(); | 834 return scoped_refptr<IndexedDBBackingStore>(); |
| 809 | 835 |
| 810 return backing_store; | 836 return backing_store; |
| 811 } | 837 } |
| 812 | 838 |
| 839 void IndexedDBBackingStore::GrantChildProcessPermissions(int child_process_id) { | |
| 840 if (!child_process_ids_granted_.count(child_process_id)) { | |
| 841 child_process_ids_granted_.insert(child_process_id); | |
| 842 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile( | |
| 843 child_process_id, blob_path_); | |
| 844 } | |
| 845 } | |
| 846 | |
| 813 std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames() { | 847 std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames() { |
| 814 std::vector<base::string16> found_names; | 848 std::vector<base::string16> found_names; |
| 815 const std::string start_key = | 849 const std::string start_key = |
| 816 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_); | 850 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_); |
| 817 const std::string stop_key = | 851 const std::string stop_key = |
| 818 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_); | 852 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_); |
| 819 | 853 |
| 820 DCHECK(found_names.empty()); | 854 DCHECK(found_names.empty()); |
| 821 | 855 |
| 822 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); | 856 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1086 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1120 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1087 break; | 1121 break; |
| 1088 } | 1122 } |
| 1089 bool auto_increment; | 1123 bool auto_increment; |
| 1090 { | 1124 { |
| 1091 StringPiece slice(it->Value()); | 1125 StringPiece slice(it->Value()); |
| 1092 if (!DecodeBool(&slice, &auto_increment) || !slice.empty()) | 1126 if (!DecodeBool(&slice, &auto_increment) || !slice.empty()) |
| 1093 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1127 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1094 } | 1128 } |
| 1095 | 1129 |
| 1096 it->Next(); // Is evicatble. | 1130 it->Next(); // Is evictable. |
| 1097 if (!CheckObjectStoreAndMetaDataType(it.get(), | 1131 if (!CheckObjectStoreAndMetaDataType(it.get(), |
| 1098 stop_key, | 1132 stop_key, |
| 1099 object_store_id, | 1133 object_store_id, |
| 1100 ObjectStoreMetaDataKey::EVICTABLE)) { | 1134 ObjectStoreMetaDataKey::EVICTABLE)) { |
| 1101 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); | 1135 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES); |
| 1102 break; | 1136 break; |
| 1103 } | 1137 } |
| 1104 | 1138 |
| 1105 it->Next(); // Last version. | 1139 it->Next(); // Last version. |
| 1106 if (!CheckObjectStoreAndMetaDataType( | 1140 if (!CheckObjectStoreAndMetaDataType( |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1375 | 1409 |
| 1376 *new_version_number = version; | 1410 *new_version_number = version; |
| 1377 return s; | 1411 return s; |
| 1378 } | 1412 } |
| 1379 | 1413 |
| 1380 leveldb::Status IndexedDBBackingStore::PutRecord( | 1414 leveldb::Status IndexedDBBackingStore::PutRecord( |
| 1381 IndexedDBBackingStore::Transaction* transaction, | 1415 IndexedDBBackingStore::Transaction* transaction, |
| 1382 int64 database_id, | 1416 int64 database_id, |
| 1383 int64 object_store_id, | 1417 int64 object_store_id, |
| 1384 const IndexedDBKey& key, | 1418 const IndexedDBKey& key, |
| 1385 const IndexedDBValue& value, | 1419 IndexedDBValue& value, |
| 1420 ScopedVector<webkit_blob::BlobDataHandle>* handles, | |
| 1386 RecordIdentifier* record_identifier) { | 1421 RecordIdentifier* record_identifier) { |
| 1387 IDB_TRACE("IndexedDBBackingStore::PutRecord"); | 1422 IDB_TRACE("IndexedDBBackingStore::PutRecord"); |
| 1388 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1423 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
| 1389 return InvalidDBKeyStatus(); | 1424 return InvalidDBKeyStatus(); |
| 1390 DCHECK(key.IsValid()); | 1425 DCHECK(key.IsValid()); |
| 1391 | 1426 |
| 1392 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 1427 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
| 1393 int64 version = -1; | 1428 int64 version = -1; |
| 1394 leveldb::Status s = GetNewVersionNumber( | 1429 leveldb::Status s = GetNewVersionNumber( |
| 1395 leveldb_transaction, database_id, object_store_id, &version); | 1430 leveldb_transaction, database_id, object_store_id, &version); |
| 1396 if (!s.ok()) | 1431 if (!s.ok()) |
| 1397 return s; | 1432 return s; |
| 1398 DCHECK_GE(version, 0); | 1433 DCHECK_GE(version, 0); |
| 1399 const std::string object_store_data_key = | 1434 const std::string object_store_data_key = |
| 1400 ObjectStoreDataKey::Encode(database_id, object_store_id, key); | 1435 ObjectStoreDataKey::Encode(database_id, object_store_id, key); |
| 1401 | 1436 |
| 1402 std::string v; | 1437 std::string v; |
| 1403 EncodeVarInt(version, &v); | 1438 EncodeVarInt(version, &v); |
| 1404 v.append(value.bits); | 1439 v.append(value.bits); |
| 1405 | 1440 |
| 1406 leveldb_transaction->Put(object_store_data_key, &v); | 1441 leveldb_transaction->Put(object_store_data_key, &v); |
| 1442 transaction->PutBlobInfo(database_id, | |
| 1443 object_store_id, | |
| 1444 object_store_data_key, | |
| 1445 &value.blob_info, | |
| 1446 handles); | |
| 1447 DCHECK(!handles->size()); | |
| 1407 | 1448 |
| 1408 const std::string exists_entry_key = | 1449 const std::string exists_entry_key = |
| 1409 ExistsEntryKey::Encode(database_id, object_store_id, key); | 1450 ExistsEntryKey::Encode(database_id, object_store_id, key); |
| 1410 std::string version_encoded; | 1451 std::string version_encoded; |
| 1411 EncodeInt(version, &version_encoded); | 1452 EncodeInt(version, &version_encoded); |
| 1412 leveldb_transaction->Put(exists_entry_key, &version_encoded); | 1453 leveldb_transaction->Put(exists_entry_key, &version_encoded); |
| 1413 | 1454 |
| 1414 std::string key_encoded; | 1455 std::string key_encoded; |
| 1415 EncodeIDBKey(key, &key_encoded); | 1456 EncodeIDBKey(key, &key_encoded); |
| 1416 record_identifier->Reset(key_encoded, version); | 1457 record_identifier->Reset(key_encoded, version); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1439 int64 object_store_id, | 1480 int64 object_store_id, |
| 1440 const RecordIdentifier& record_identifier) { | 1481 const RecordIdentifier& record_identifier) { |
| 1441 IDB_TRACE("IndexedDBBackingStore::DeleteRecord"); | 1482 IDB_TRACE("IndexedDBBackingStore::DeleteRecord"); |
| 1442 if (!KeyPrefix::ValidIds(database_id, object_store_id)) | 1483 if (!KeyPrefix::ValidIds(database_id, object_store_id)) |
| 1443 return InvalidDBKeyStatus(); | 1484 return InvalidDBKeyStatus(); |
| 1444 LevelDBTransaction* leveldb_transaction = transaction->transaction(); | 1485 LevelDBTransaction* leveldb_transaction = transaction->transaction(); |
| 1445 | 1486 |
| 1446 const std::string object_store_data_key = ObjectStoreDataKey::Encode( | 1487 const std::string object_store_data_key = ObjectStoreDataKey::Encode( |
| 1447 database_id, object_store_id, record_identifier.primary_key()); | 1488 database_id, object_store_id, record_identifier.primary_key()); |
| 1448 leveldb_transaction->Remove(object_store_data_key); | 1489 leveldb_transaction->Remove(object_store_data_key); |
| 1490 transaction->PutBlobInfo( | |
| 1491 database_id, object_store_id, object_store_data_key, NULL, NULL); | |
| 1449 | 1492 |
| 1450 const std::string exists_entry_key = ExistsEntryKey::Encode( | 1493 const std::string exists_entry_key = ExistsEntryKey::Encode( |
| 1451 database_id, object_store_id, record_identifier.primary_key()); | 1494 database_id, object_store_id, record_identifier.primary_key()); |
| 1452 leveldb_transaction->Remove(exists_entry_key); | 1495 leveldb_transaction->Remove(exists_entry_key); |
| 1453 return leveldb::Status::OK(); | 1496 return leveldb::Status::OK(); |
| 1454 } | 1497 } |
| 1455 | 1498 |
| 1456 leveldb::Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber( | 1499 leveldb::Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber( |
| 1457 IndexedDBBackingStore::Transaction* transaction, | 1500 IndexedDBBackingStore::Transaction* transaction, |
| 1458 int64 database_id, | 1501 int64 database_id, |
| (...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2760 scoped_ptr<IndexCursorImpl> cursor( | 2803 scoped_ptr<IndexCursorImpl> cursor( |
| 2761 new IndexCursorImpl(leveldb_transaction, cursor_options)); | 2804 new IndexCursorImpl(leveldb_transaction, cursor_options)); |
| 2762 if (!cursor->FirstSeek()) | 2805 if (!cursor->FirstSeek()) |
| 2763 return scoped_ptr<IndexedDBBackingStore::Cursor>(); | 2806 return scoped_ptr<IndexedDBBackingStore::Cursor>(); |
| 2764 | 2807 |
| 2765 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); | 2808 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); |
| 2766 } | 2809 } |
| 2767 | 2810 |
| 2768 IndexedDBBackingStore::Transaction::Transaction( | 2811 IndexedDBBackingStore::Transaction::Transaction( |
| 2769 IndexedDBBackingStore* backing_store) | 2812 IndexedDBBackingStore* backing_store) |
| 2770 : backing_store_(backing_store) {} | 2813 : backing_store_(backing_store), database_id_(-1) {} |
| 2771 | 2814 |
| 2772 IndexedDBBackingStore::Transaction::~Transaction() {} | 2815 IndexedDBBackingStore::Transaction::~Transaction() { |
| 2816 BlobChangeMap::iterator iter = blob_change_map_.begin(); | |
|
cmumford
2014/04/10 16:59:43
Can you use STLDeleteContainerPairSecondPointers()
ericu
2014/04/14 23:23:38
Done. Just barely makes it shorter, what with tha
| |
| 2817 for (; iter != blob_change_map_.end(); ++iter) { | |
| 2818 delete iter->second; | |
| 2819 } | |
| 2820 } | |
| 2773 | 2821 |
| 2774 void IndexedDBBackingStore::Transaction::Begin() { | 2822 void IndexedDBBackingStore::Transaction::Begin() { |
| 2775 IDB_TRACE("IndexedDBBackingStore::Transaction::Begin"); | 2823 IDB_TRACE("IndexedDBBackingStore::Transaction::Begin"); |
| 2776 DCHECK(!transaction_.get()); | 2824 DCHECK(!transaction_.get()); |
| 2777 transaction_ = new LevelDBTransaction(backing_store_->db_.get()); | 2825 transaction_ = new LevelDBTransaction(backing_store_->db_.get()); |
| 2778 } | 2826 } |
| 2779 | 2827 |
| 2780 leveldb::Status IndexedDBBackingStore::Transaction::Commit() { | 2828 leveldb::Status IndexedDBBackingStore::Transaction::Commit() { |
| 2781 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); | 2829 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); |
| 2782 DCHECK(transaction_.get()); | 2830 DCHECK(transaction_.get()); |
| 2783 leveldb::Status s = transaction_->Commit(); | 2831 leveldb::Status s = transaction_->Commit(); |
| 2784 transaction_ = NULL; | 2832 transaction_ = NULL; |
| 2785 if (!s.ok()) | 2833 if (!s.ok()) |
| 2786 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD); | 2834 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD); |
| 2787 return s; | 2835 return s; |
| 2788 } | 2836 } |
| 2789 | 2837 |
| 2790 void IndexedDBBackingStore::Transaction::Rollback() { | 2838 void IndexedDBBackingStore::Transaction::Rollback() { |
| 2791 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); | 2839 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); |
| 2792 DCHECK(transaction_.get()); | 2840 DCHECK(transaction_.get()); |
| 2793 transaction_->Rollback(); | 2841 transaction_->Rollback(); |
| 2794 transaction_ = NULL; | 2842 transaction_ = NULL; |
| 2795 } | 2843 } |
| 2796 | 2844 |
| 2845 | |
| 2846 void IndexedDBBackingStore::Transaction::BlobChangeRecord::SetBlobInfo( | |
| 2847 std::vector<IndexedDBBlobInfo>* blob_info) { | |
| 2848 blob_info_.clear(); | |
| 2849 if (blob_info) | |
| 2850 blob_info_.swap(*blob_info); | |
|
cmumford
2014/04/10 16:59:43
Why swap the blob info vs. operator=()
ericu
2014/04/14 23:23:38
I believe that swapping the innards of a std::vect
| |
| 2851 } | |
| 2852 | |
| 2853 void IndexedDBBackingStore::Transaction::BlobChangeRecord::SetHandles( | |
| 2854 ScopedVector<webkit_blob::BlobDataHandle>* handles) { | |
| 2855 handles_.clear(); | |
| 2856 if (handles) | |
| 2857 handles_.swap(*handles); | |
| 2858 } | |
| 2859 | |
| 2860 // This is storing an info, even if empty, even if the previous key had no blob | |
| 2861 // info that we know of. It duplicates a bunch of information stored in the | |
| 2862 // leveldb transaction, but only w.r.t. the user keys altered--we don't keep the | |
| 2863 // changes to exists or index keys here. | |
| 2864 void IndexedDBBackingStore::Transaction::PutBlobInfo( | |
| 2865 int64 database_id, | |
| 2866 int64 object_store_id, | |
| 2867 const std::string& key, | |
| 2868 std::vector<IndexedDBBlobInfo>* blob_info, | |
| 2869 ScopedVector<webkit_blob::BlobDataHandle>* handles) { | |
| 2870 DCHECK_GT(key.size(), 0UL); | |
| 2871 if (database_id_ < 0) | |
| 2872 database_id_ = database_id; | |
| 2873 DCHECK_EQ(database_id_, database_id); | |
| 2874 | |
| 2875 BlobChangeMap::iterator it = blob_change_map_.find(key); | |
| 2876 BlobChangeRecord* record = NULL; | |
| 2877 if (it == blob_change_map_.end()) { | |
| 2878 record = new BlobChangeRecord(); | |
| 2879 blob_change_map_[key] = record; | |
| 2880 record->set_key(key); | |
| 2881 record->set_object_store_id(object_store_id); | |
| 2882 } else { | |
| 2883 record = it->second; | |
| 2884 } | |
| 2885 DCHECK_EQ(record->object_store_id(), object_store_id); | |
| 2886 record->SetBlobInfo(blob_info); | |
| 2887 record->SetHandles(handles); | |
| 2888 DCHECK(!handles || !handles->size()); | |
| 2889 } | |
| 2890 | |
| 2797 } // namespace content | 2891 } // namespace content |
| OLD | NEW |