| 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/dom_storage/session_storage_database.h" | 5 #include "webkit/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/stringprintf.h" | 9 #include "base/stringprintf.h" |
| 10 #include "base/string_number_conversions.h" | 10 #include "base/string_number_conversions.h" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 // exist. | 75 // exist. |
| 76 const bool kOkIfExists = true; | 76 const bool kOkIfExists = true; |
| 77 if (!CreateNamespace(namespace_id, kOkIfExists, &batch)) | 77 if (!CreateNamespace(namespace_id, kOkIfExists, &batch)) |
| 78 return false; | 78 return false; |
| 79 | 79 |
| 80 std::string map_id; | 80 std::string map_id; |
| 81 bool exists; | 81 bool exists; |
| 82 if (!GetMapForArea(namespace_id, origin, &exists, &map_id)) | 82 if (!GetMapForArea(namespace_id, origin, &exists, &map_id)) |
| 83 return false; | 83 return false; |
| 84 if (exists) { | 84 if (exists) { |
| 85 // We shouldn't write data into a shallow copy. If this is a shallow copy, | |
| 86 // it's a caller error (not an inconsistency in the database). | |
| 87 int64 ref_count; | 85 int64 ref_count; |
| 88 if (!GetMapRefCount(map_id, &ref_count)) | 86 if (!GetMapRefCount(map_id, &ref_count)) |
| 89 return false; | 87 return false; |
| 90 if (!CallerErrorCheck(ref_count == 1)) | 88 if (ref_count > 1) { |
| 91 return false; | 89 if (!DeepCopyArea(namespace_id, origin, !clear_all_first, |
| 92 | 90 &map_id, &batch)) |
| 93 if (clear_all_first) { | 91 return false; |
| 92 } |
| 93 else if (clear_all_first) { |
| 94 if (!ClearMap(map_id, &batch)) | 94 if (!ClearMap(map_id, &batch)) |
| 95 return false; | 95 return false; |
| 96 } | 96 } |
| 97 } else { | 97 } else { |
| 98 // Map doesn't exist, create it now if needed. | 98 // Map doesn't exist, create it now if needed. |
| 99 if (!changes.empty()) { | 99 if (!changes.empty()) { |
| 100 if (!CreateMapForArea(namespace_id, origin, &map_id, &batch)) | 100 if (!CreateMapForArea(namespace_id, origin, &map_id, &batch)) |
| 101 return false; | 101 return false; |
| 102 } | 102 } |
| 103 } | 103 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 const std::string& origin = it->first; | 144 const std::string& origin = it->first; |
| 145 const std::string& map_id = it->second; | 145 const std::string& map_id = it->second; |
| 146 if (!IncreaseMapRefCount(map_id, &batch)) | 146 if (!IncreaseMapRefCount(map_id, &batch)) |
| 147 return false; | 147 return false; |
| 148 AddAreaToNamespace(new_namespace_id, origin, map_id, &batch); | 148 AddAreaToNamespace(new_namespace_id, origin, map_id, &batch); |
| 149 } | 149 } |
| 150 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); | 150 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); |
| 151 return DatabaseErrorCheck(s.ok()); | 151 return DatabaseErrorCheck(s.ok()); |
| 152 } | 152 } |
| 153 | 153 |
| 154 bool SessionStorageDatabase::DeepCopyArea(int64 namespace_id, | |
| 155 const GURL& origin) { | |
| 156 // Example, data before deep copy: | |
| 157 // | namespace-1 (1 = namespace id) | dummy | | |
| 158 // | namespace-1-origin1 | 1 (mapid) | | |
| 159 // | namespace-2 | dummy | | |
| 160 // | namespace-2-origin1 | 1 (mapid) << references the same map | |
| 161 // | map-1 | 2 (refcount) | | |
| 162 // | map-1-a | b | | |
| 163 | |
| 164 // Example, data after deep copy copy: | |
| 165 // | namespace-1 (1 = namespace id) | dummy | | |
| 166 // | namespace-1-origin1 | 1 (mapid) | | |
| 167 // | namespace-2 | dummy | | |
| 168 // | namespace-2-origin1 | 2 (mapid) << references the new map | |
| 169 // | map-1 | 1 (dec. refcount) | | |
| 170 // | map-1-a | b | | |
| 171 // | map-2 | 1 (refcount) | | |
| 172 // | map-2-a | b | | |
| 173 | |
| 174 if (!LazyOpen(true)) | |
| 175 return false; | |
| 176 | |
| 177 std::string old_map_id; | |
| 178 bool exists; | |
| 179 if (!GetMapForArea(namespace_id, origin, &exists, &old_map_id)) | |
| 180 return false; | |
| 181 | |
| 182 // If the area doesn't exist, or if it's not a shallow copy, it's a caller | |
| 183 // error. | |
| 184 if (!CallerErrorCheck(exists)) | |
| 185 return false; | |
| 186 int64 ref_count; | |
| 187 if (!GetMapRefCount(old_map_id, &ref_count)) | |
| 188 return false; | |
| 189 if (!CallerErrorCheck(ref_count > 1)) | |
| 190 return false; | |
| 191 | |
| 192 leveldb::WriteBatch batch; | |
| 193 std::string new_map_id; | |
| 194 if (!CreateMapForArea(namespace_id, origin, &new_map_id, &batch)) | |
| 195 return false; | |
| 196 | |
| 197 // Copy the values in the map. | |
| 198 ValuesMap values; | |
| 199 if (!ReadMap(old_map_id, &values, false)) | |
| 200 return false; | |
| 201 WriteValuesToMap(new_map_id, values, &batch); | |
| 202 | |
| 203 if (!DecreaseMapRefCount(old_map_id, 1, &batch)) | |
| 204 return false; | |
| 205 | |
| 206 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); | |
| 207 return DatabaseErrorCheck(s.ok()); | |
| 208 } | |
| 209 | |
| 210 bool SessionStorageDatabase::DeleteArea(int64 namespace_id, | 154 bool SessionStorageDatabase::DeleteArea(int64 namespace_id, |
| 211 const GURL& origin) { | 155 const GURL& origin) { |
| 212 if (!LazyOpen(false)) { | 156 if (!LazyOpen(false)) { |
| 213 // No need to create the database if it doesn't exist. | 157 // No need to create the database if it doesn't exist. |
| 214 return true; | 158 return true; |
| 215 } | 159 } |
| 216 leveldb::WriteBatch batch; | 160 leveldb::WriteBatch batch; |
| 217 if (!DeleteArea(namespace_id, origin.spec(), &batch)) | 161 if (!DeleteArea(namespace_id, origin.spec(), &batch)) |
| 218 return false; | 162 return false; |
| 219 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); | 163 leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 bool SessionStorageDatabase::ClearMap(const std::string& map_id, | 540 bool SessionStorageDatabase::ClearMap(const std::string& map_id, |
| 597 leveldb::WriteBatch* batch) { | 541 leveldb::WriteBatch* batch) { |
| 598 ValuesMap values; | 542 ValuesMap values; |
| 599 if (!ReadMap(map_id, &values, true)) | 543 if (!ReadMap(map_id, &values, true)) |
| 600 return false; | 544 return false; |
| 601 for (ValuesMap::const_iterator it = values.begin(); it != values.end(); ++it) | 545 for (ValuesMap::const_iterator it = values.begin(); it != values.end(); ++it) |
| 602 batch->Delete(MapKey(map_id, UTF16ToUTF8(it->first))); | 546 batch->Delete(MapKey(map_id, UTF16ToUTF8(it->first))); |
| 603 return true; | 547 return true; |
| 604 } | 548 } |
| 605 | 549 |
| 550 bool SessionStorageDatabase::DeepCopyArea( |
| 551 int64 namespace_id, const GURL& origin, bool copy_data, |
| 552 std::string* map_id, leveldb::WriteBatch* batch) { |
| 553 // Example, data before deep copy: |
| 554 // | namespace-1 (1 = namespace id) | dummy | |
| 555 // | namespace-1-origin1 | 1 (mapid) | |
| 556 // | namespace-2 | dummy | |
| 557 // | namespace-2-origin1 | 1 (mapid) << references the same map |
| 558 // | map-1 | 2 (refcount) | |
| 559 // | map-1-a | b | |
| 560 |
| 561 // Example, data after deep copy copy: |
| 562 // | namespace-1 (1 = namespace id) | dummy | |
| 563 // | namespace-1-origin1 | 1 (mapid) | |
| 564 // | namespace-2 | dummy | |
| 565 // | namespace-2-origin1 | 2 (mapid) << references the new map |
| 566 // | map-1 | 1 (dec. refcount) | |
| 567 // | map-1-a | b | |
| 568 // | map-2 | 1 (refcount) | |
| 569 // | map-2-a | b | |
| 570 |
| 571 // Read the values from the old map here. If we don't need to copy the data, |
| 572 // this can stay empty. |
| 573 ValuesMap values; |
| 574 if (copy_data && !ReadMap(*map_id, &values, false)) |
| 575 return false; |
| 576 if (!DecreaseMapRefCount(*map_id, 1, batch)) |
| 577 return false; |
| 578 // Create a new map (this will also break the association to the old map) and |
| 579 // write the old data into it. This will write the id of the created map into |
| 580 // |map_id|. |
| 581 if (!CreateMapForArea(namespace_id, origin, map_id, batch)) |
| 582 return false; |
| 583 WriteValuesToMap(*map_id, values, batch); |
| 584 return true; |
| 585 } |
| 586 |
| 606 std::string SessionStorageDatabase::NamespaceStartKey( | 587 std::string SessionStorageDatabase::NamespaceStartKey( |
| 607 const std::string& namespace_id_str) { | 588 const std::string& namespace_id_str) { |
| 608 return base::StringPrintf("namespace-%s", namespace_id_str.c_str()); | 589 return base::StringPrintf("namespace-%s", namespace_id_str.c_str()); |
| 609 } | 590 } |
| 610 | 591 |
| 611 std::string SessionStorageDatabase::NamespaceStartKey(int64 namespace_id, | 592 std::string SessionStorageDatabase::NamespaceStartKey(int64 namespace_id, |
| 612 int64 namespace_offset) { | 593 int64 namespace_offset) { |
| 613 return NamespaceStartKey(NamespaceIdStr(namespace_id, namespace_offset)); | 594 return NamespaceStartKey(NamespaceIdStr(namespace_id, namespace_offset)); |
| 614 } | 595 } |
| 615 | 596 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 | 630 |
| 650 const char* SessionStorageDatabase::NextNamespaceIdKey() { | 631 const char* SessionStorageDatabase::NextNamespaceIdKey() { |
| 651 return "next-namespace-id"; | 632 return "next-namespace-id"; |
| 652 } | 633 } |
| 653 | 634 |
| 654 const char* SessionStorageDatabase::NextMapIdKey() { | 635 const char* SessionStorageDatabase::NextMapIdKey() { |
| 655 return "next-map-id"; | 636 return "next-map-id"; |
| 656 } | 637 } |
| 657 | 638 |
| 658 } // namespace dom_storage | 639 } // namespace dom_storage |
| OLD | NEW |