OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "webkit/browser/dom_storage/session_storage_database.h" | 5 #include "content/browser/dom_storage/session_storage_database.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
13 #include "third_party/leveldatabase/src/include/leveldb/db.h" | 13 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
14 #include "third_party/leveldatabase/src/include/leveldb/iterator.h" | 14 #include "third_party/leveldatabase/src/include/leveldb/iterator.h" |
15 #include "third_party/leveldatabase/src/include/leveldb/options.h" | 15 #include "third_party/leveldatabase/src/include/leveldb/options.h" |
(...skipping 26 matching lines...) Expand all Loading... |
42 // | namespace-1-origin1 | 1 (mapid) | | 42 // | namespace-1-origin1 | 1 (mapid) | |
43 // | namespace-1-origin2 | 2 | | 43 // | namespace-1-origin2 | 2 | |
44 // | namespace-2- | dummy | | 44 // | namespace-2- | dummy | |
45 // | namespace-2-origin1 | 1 (shallow copy) | | 45 // | namespace-2-origin1 | 1 (shallow copy) | |
46 // | namespace-2-origin2 | 2 (shallow copy) | | 46 // | namespace-2-origin2 | 2 (shallow copy) | |
47 // | namespace-3- | dummy | | 47 // | namespace-3- | dummy | |
48 // | namespace-3-origin1 | 3 (deep copy) | | 48 // | namespace-3-origin1 | 3 (deep copy) | |
49 // | namespace-3-origin2 | 2 (shallow copy) | | 49 // | namespace-3-origin2 | 2 (shallow copy) | |
50 // | next-map-id | 4 | | 50 // | next-map-id | 4 | |
51 | 51 |
52 namespace dom_storage { | 52 namespace content { |
53 | 53 |
54 SessionStorageDatabase::SessionStorageDatabase(const base::FilePath& file_path) | 54 SessionStorageDatabase::SessionStorageDatabase(const base::FilePath& file_path) |
55 : file_path_(file_path), | 55 : file_path_(file_path), |
56 db_error_(false), | 56 db_error_(false), |
57 is_inconsistent_(false) { | 57 is_inconsistent_(false) { |
58 } | 58 } |
59 | 59 |
60 SessionStorageDatabase::~SessionStorageDatabase() { | 60 SessionStorageDatabase::~SessionStorageDatabase() { |
61 } | 61 } |
62 | 62 |
63 void SessionStorageDatabase::ReadAreaValues(const std::string& namespace_id, | 63 void SessionStorageDatabase::ReadAreaValues(const std::string& namespace_id, |
64 const GURL& origin, | 64 const GURL& origin, |
65 ValuesMap* result) { | 65 DOMStorageValuesMap* result) { |
66 // We don't create a database if it doesn't exist. In that case, there is | 66 // We don't create a database if it doesn't exist. In that case, there is |
67 // nothing to be added to the result. | 67 // nothing to be added to the result. |
68 if (!LazyOpen(false)) | 68 if (!LazyOpen(false)) |
69 return; | 69 return; |
70 | 70 |
71 // While ReadAreaValues is in progress, another thread can call | 71 // While ReadAreaValues is in progress, another thread can call |
72 // CommitAreaChanges. CommitAreaChanges might update map ref count key while | 72 // CommitAreaChanges. CommitAreaChanges might update map ref count key while |
73 // this thread is iterating over the map ref count key. To protect the reading | 73 // this thread is iterating over the map ref count key. To protect the reading |
74 // operation, create a snapshot and read from it. | 74 // operation, create a snapshot and read from it. |
75 leveldb::ReadOptions options; | 75 leveldb::ReadOptions options; |
76 options.snapshot = db_->GetSnapshot(); | 76 options.snapshot = db_->GetSnapshot(); |
77 | 77 |
78 std::string map_id; | 78 std::string map_id; |
79 bool exists; | 79 bool exists; |
80 if (GetMapForArea(namespace_id, origin.spec(), options, &exists, &map_id) && | 80 if (GetMapForArea(namespace_id, origin.spec(), options, &exists, &map_id) && |
81 exists) | 81 exists) |
82 ReadMap(map_id, options, result, false); | 82 ReadMap(map_id, options, result, false); |
83 db_->ReleaseSnapshot(options.snapshot); | 83 db_->ReleaseSnapshot(options.snapshot); |
84 } | 84 } |
85 | 85 |
86 bool SessionStorageDatabase::CommitAreaChanges(const std::string& namespace_id, | 86 bool SessionStorageDatabase::CommitAreaChanges( |
87 const GURL& origin, | 87 const std::string& namespace_id, |
88 bool clear_all_first, | 88 const GURL& origin, |
89 const ValuesMap& changes) { | 89 bool clear_all_first, |
| 90 const DOMStorageValuesMap& changes) { |
90 // Even if |changes| is empty, we need to write the appropriate placeholders | 91 // Even if |changes| is empty, we need to write the appropriate placeholders |
91 // in the database, so that it can be later shallow-copied succssfully. | 92 // in the database, so that it can be later shallow-copied succssfully. |
92 if (!LazyOpen(true)) | 93 if (!LazyOpen(true)) |
93 return false; | 94 return false; |
94 | 95 |
95 leveldb::WriteBatch batch; | 96 leveldb::WriteBatch batch; |
96 // Ensure that the keys "namespace-" "namespace-N" (see the schema above) | 97 // Ensure that the keys "namespace-" "namespace-N" (see the schema above) |
97 // exist. | 98 // exist. |
98 const bool kOkIfExists = true; | 99 const bool kOkIfExists = true; |
99 if (!CreateNamespace(namespace_id, kOkIfExists, &batch)) | 100 if (!CreateNamespace(namespace_id, kOkIfExists, &batch)) |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 } | 496 } |
496 batch->Put(next_map_id_key, base::Int64ToString(++next_map_id)); | 497 batch->Put(next_map_id_key, base::Int64ToString(++next_map_id)); |
497 std::string namespace_key = NamespaceKey(namespace_id, origin.spec()); | 498 std::string namespace_key = NamespaceKey(namespace_id, origin.spec()); |
498 batch->Put(namespace_key, *map_id); | 499 batch->Put(namespace_key, *map_id); |
499 batch->Put(MapRefCountKey(*map_id), "1"); | 500 batch->Put(MapRefCountKey(*map_id), "1"); |
500 return true; | 501 return true; |
501 } | 502 } |
502 | 503 |
503 bool SessionStorageDatabase::ReadMap(const std::string& map_id, | 504 bool SessionStorageDatabase::ReadMap(const std::string& map_id, |
504 const leveldb::ReadOptions& options, | 505 const leveldb::ReadOptions& options, |
505 ValuesMap* result, | 506 DOMStorageValuesMap* result, |
506 bool only_keys) { | 507 bool only_keys) { |
507 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options)); | 508 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options)); |
508 std::string map_start_key = MapRefCountKey(map_id); | 509 std::string map_start_key = MapRefCountKey(map_id); |
509 it->Seek(map_start_key); | 510 it->Seek(map_start_key); |
510 // If the key is not found, the status of the iterator won't be IsNotFound(), | 511 // If the key is not found, the status of the iterator won't be IsNotFound(), |
511 // but the iterator will be invalid. The map needs to exist, otherwise we have | 512 // but the iterator will be invalid. The map needs to exist, otherwise we have |
512 // a stale map_id in the database. | 513 // a stale map_id in the database. |
513 if (!ConsistencyCheck(it->Valid())) | 514 if (!ConsistencyCheck(it->Valid())) |
514 return false; | 515 return false; |
515 if (!DatabaseErrorCheck(it->status().ok())) | 516 if (!DatabaseErrorCheck(it->status().ok())) |
(...skipping 16 matching lines...) Expand all Loading... |
532 const char16* data_ptr = | 533 const char16* data_ptr = |
533 reinterpret_cast<const char16*>(it->value().data()); | 534 reinterpret_cast<const char16*>(it->value().data()); |
534 (*result)[key16] = | 535 (*result)[key16] = |
535 base::NullableString16(base::string16(data_ptr, len), false); | 536 base::NullableString16(base::string16(data_ptr, len), false); |
536 } | 537 } |
537 } | 538 } |
538 return true; | 539 return true; |
539 } | 540 } |
540 | 541 |
541 void SessionStorageDatabase::WriteValuesToMap(const std::string& map_id, | 542 void SessionStorageDatabase::WriteValuesToMap(const std::string& map_id, |
542 const ValuesMap& values, | 543 const DOMStorageValuesMap& values, |
543 leveldb::WriteBatch* batch) { | 544 leveldb::WriteBatch* batch) { |
544 for (ValuesMap::const_iterator it = values.begin(); it != values.end(); | 545 for (DOMStorageValuesMap::const_iterator it = values.begin(); |
| 546 it != values.end(); |
545 ++it) { | 547 ++it) { |
546 base::NullableString16 value = it->second; | 548 base::NullableString16 value = it->second; |
547 std::string key = MapKey(map_id, UTF16ToUTF8(it->first)); | 549 std::string key = MapKey(map_id, UTF16ToUTF8(it->first)); |
548 if (value.is_null()) { | 550 if (value.is_null()) { |
549 batch->Delete(key); | 551 batch->Delete(key); |
550 } else { | 552 } else { |
551 // Convert the raw data stored in base::string16 to raw data stored in | 553 // Convert the raw data stored in base::string16 to raw data stored in |
552 // std::string. | 554 // std::string. |
553 const char* data = reinterpret_cast<const char*>(value.string().data()); | 555 const char* data = reinterpret_cast<const char*>(value.string().data()); |
554 size_t size = value.string().size() * 2; | 556 size_t size = value.string().size() * 2; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 // Clear all keys in the map. | 596 // Clear all keys in the map. |
595 if (!ClearMap(map_id, batch)) | 597 if (!ClearMap(map_id, batch)) |
596 return false; | 598 return false; |
597 batch->Delete(MapRefCountKey(map_id)); | 599 batch->Delete(MapRefCountKey(map_id)); |
598 } | 600 } |
599 return true; | 601 return true; |
600 } | 602 } |
601 | 603 |
602 bool SessionStorageDatabase::ClearMap(const std::string& map_id, | 604 bool SessionStorageDatabase::ClearMap(const std::string& map_id, |
603 leveldb::WriteBatch* batch) { | 605 leveldb::WriteBatch* batch) { |
604 ValuesMap values; | 606 DOMStorageValuesMap values; |
605 if (!ReadMap(map_id, leveldb::ReadOptions(), &values, true)) | 607 if (!ReadMap(map_id, leveldb::ReadOptions(), &values, true)) |
606 return false; | 608 return false; |
607 for (ValuesMap::const_iterator it = values.begin(); it != values.end(); ++it) | 609 for (DOMStorageValuesMap::const_iterator it = values.begin(); |
| 610 it != values.end(); ++it) |
608 batch->Delete(MapKey(map_id, UTF16ToUTF8(it->first))); | 611 batch->Delete(MapKey(map_id, UTF16ToUTF8(it->first))); |
609 return true; | 612 return true; |
610 } | 613 } |
611 | 614 |
612 bool SessionStorageDatabase::DeepCopyArea( | 615 bool SessionStorageDatabase::DeepCopyArea( |
613 const std::string& namespace_id, const GURL& origin, bool copy_data, | 616 const std::string& namespace_id, const GURL& origin, bool copy_data, |
614 std::string* map_id, leveldb::WriteBatch* batch) { | 617 std::string* map_id, leveldb::WriteBatch* batch) { |
615 // Example, data before deep copy: | 618 // Example, data before deep copy: |
616 // | namespace-1- (1 = namespace id)| dummy | | 619 // | namespace-1- (1 = namespace id)| dummy | |
617 // | namespace-1-origin1 | 1 (mapid) | | 620 // | namespace-1-origin1 | 1 (mapid) | |
618 // | namespace-2- | dummy | | 621 // | namespace-2- | dummy | |
619 // | namespace-2-origin1 | 1 (mapid) << references the same map | 622 // | namespace-2-origin1 | 1 (mapid) << references the same map |
620 // | map-1- | 2 (refcount) | | 623 // | map-1- | 2 (refcount) | |
621 // | map-1-a | b | | 624 // | map-1-a | b | |
622 | 625 |
623 // Example, data after deep copy copy: | 626 // Example, data after deep copy copy: |
624 // | namespace-1-(1 = namespace id) | dummy | | 627 // | namespace-1-(1 = namespace id) | dummy | |
625 // | namespace-1-origin1 | 1 (mapid) | | 628 // | namespace-1-origin1 | 1 (mapid) | |
626 // | namespace-2- | dummy | | 629 // | namespace-2- | dummy | |
627 // | namespace-2-origin1 | 2 (mapid) << references the new map | 630 // | namespace-2-origin1 | 2 (mapid) << references the new map |
628 // | map-1- | 1 (dec. refcount) | | 631 // | map-1- | 1 (dec. refcount) | |
629 // | map-1-a | b | | 632 // | map-1-a | b | |
630 // | map-2- | 1 (refcount) | | 633 // | map-2- | 1 (refcount) | |
631 // | map-2-a | b | | 634 // | map-2-a | b | |
632 | 635 |
633 // Read the values from the old map here. If we don't need to copy the data, | 636 // Read the values from the old map here. If we don't need to copy the data, |
634 // this can stay empty. | 637 // this can stay empty. |
635 ValuesMap values; | 638 DOMStorageValuesMap values; |
636 if (copy_data && !ReadMap(*map_id, leveldb::ReadOptions(), &values, false)) | 639 if (copy_data && !ReadMap(*map_id, leveldb::ReadOptions(), &values, false)) |
637 return false; | 640 return false; |
638 if (!DecreaseMapRefCount(*map_id, 1, batch)) | 641 if (!DecreaseMapRefCount(*map_id, 1, batch)) |
639 return false; | 642 return false; |
640 // Create a new map (this will also break the association to the old map) and | 643 // Create a new map (this will also break the association to the old map) and |
641 // write the old data into it. This will write the id of the created map into | 644 // write the old data into it. This will write the id of the created map into |
642 // |map_id|. | 645 // |map_id|. |
643 if (!CreateMapForArea(namespace_id, origin, map_id, batch)) | 646 if (!CreateMapForArea(namespace_id, origin, map_id, batch)) |
644 return false; | 647 return false; |
645 WriteValuesToMap(*map_id, values, batch); | 648 WriteValuesToMap(*map_id, values, batch); |
(...skipping 21 matching lines...) Expand all Loading... |
667 | 670 |
668 std::string SessionStorageDatabase::MapKey(const std::string& map_id, | 671 std::string SessionStorageDatabase::MapKey(const std::string& map_id, |
669 const std::string& key) { | 672 const std::string& key) { |
670 return base::StringPrintf("map-%s-%s", map_id.c_str(), key.c_str()); | 673 return base::StringPrintf("map-%s-%s", map_id.c_str(), key.c_str()); |
671 } | 674 } |
672 | 675 |
673 const char* SessionStorageDatabase::NextMapIdKey() { | 676 const char* SessionStorageDatabase::NextMapIdKey() { |
674 return "next-map-id"; | 677 return "next-map-id"; |
675 } | 678 } |
676 | 679 |
677 } // namespace dom_storage | 680 } // namespace content |
OLD | NEW |