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 |