Index: webkit/dom_storage/session_storage_database.cc |
diff --git a/webkit/dom_storage/session_storage_database.cc b/webkit/dom_storage/session_storage_database.cc |
index e66d477442b9067d7bfb87b76296417023f49a48..11db6e5fbdd152c081c52751c334e26d0c6604e5 100644 |
--- a/webkit/dom_storage/session_storage_database.cc |
+++ b/webkit/dom_storage/session_storage_database.cc |
@@ -82,15 +82,15 @@ bool SessionStorageDatabase::CommitAreaChanges(int64 namespace_id, |
if (!GetMapForArea(namespace_id, origin, &exists, &map_id)) |
return false; |
if (exists) { |
- // We shouldn't write data into a shallow copy. If this is a shallow copy, |
- // it's a caller error (not an inconsistency in the database). |
int64 ref_count; |
if (!GetMapRefCount(map_id, &ref_count)) |
return false; |
- if (!CallerErrorCheck(ref_count == 1)) |
- return false; |
- |
- if (clear_all_first) { |
+ if (ref_count > 1) { |
+ if (!DeepCopyArea(namespace_id, origin, !clear_all_first, |
+ &map_id, &batch)) |
+ return false; |
+ } |
+ else if (clear_all_first) { |
if (!ClearMap(map_id, &batch)) |
return false; |
} |
@@ -151,62 +151,6 @@ bool SessionStorageDatabase::CloneNamespace(int64 namespace_id, |
return DatabaseErrorCheck(s.ok()); |
} |
-bool SessionStorageDatabase::DeepCopyArea(int64 namespace_id, |
- const GURL& origin) { |
- // Example, data before deep copy: |
- // | namespace-1 (1 = namespace id) | dummy | |
- // | namespace-1-origin1 | 1 (mapid) | |
- // | namespace-2 | dummy | |
- // | namespace-2-origin1 | 1 (mapid) << references the same map |
- // | map-1 | 2 (refcount) | |
- // | map-1-a | b | |
- |
- // Example, data after deep copy copy: |
- // | namespace-1 (1 = namespace id) | dummy | |
- // | namespace-1-origin1 | 1 (mapid) | |
- // | namespace-2 | dummy | |
- // | namespace-2-origin1 | 2 (mapid) << references the new map |
- // | map-1 | 1 (dec. refcount) | |
- // | map-1-a | b | |
- // | map-2 | 1 (refcount) | |
- // | map-2-a | b | |
- |
- if (!LazyOpen(true)) |
- return false; |
- |
- std::string old_map_id; |
- bool exists; |
- if (!GetMapForArea(namespace_id, origin, &exists, &old_map_id)) |
- return false; |
- |
- // If the area doesn't exist, or if it's not a shallow copy, it's a caller |
- // error. |
- if (!CallerErrorCheck(exists)) |
- return false; |
- int64 ref_count; |
- if (!GetMapRefCount(old_map_id, &ref_count)) |
- return false; |
- if (!CallerErrorCheck(ref_count > 1)) |
- return false; |
- |
- leveldb::WriteBatch batch; |
- std::string new_map_id; |
- if (!CreateMapForArea(namespace_id, origin, &new_map_id, &batch)) |
- return false; |
- |
- // Copy the values in the map. |
- ValuesMap values; |
- if (!ReadMap(old_map_id, &values, false)) |
- return false; |
- WriteValuesToMap(new_map_id, values, &batch); |
- |
- if (!DecreaseMapRefCount(old_map_id, 1, &batch)) |
- return false; |
- |
- leveldb::Status s = db_->Write(leveldb::WriteOptions(), &batch); |
- return DatabaseErrorCheck(s.ok()); |
-} |
- |
bool SessionStorageDatabase::DeleteArea(int64 namespace_id, |
const GURL& origin) { |
if (!LazyOpen(false)) { |
@@ -603,6 +547,43 @@ bool SessionStorageDatabase::ClearMap(const std::string& map_id, |
return true; |
} |
+bool SessionStorageDatabase::DeepCopyArea( |
+ int64 namespace_id, const GURL& origin, bool copy_data, |
+ std::string* map_id, leveldb::WriteBatch* batch) { |
+ // Example, data before deep copy: |
+ // | namespace-1 (1 = namespace id) | dummy | |
+ // | namespace-1-origin1 | 1 (mapid) | |
+ // | namespace-2 | dummy | |
+ // | namespace-2-origin1 | 1 (mapid) << references the same map |
+ // | map-1 | 2 (refcount) | |
+ // | map-1-a | b | |
+ |
+ // Example, data after deep copy copy: |
+ // | namespace-1 (1 = namespace id) | dummy | |
+ // | namespace-1-origin1 | 1 (mapid) | |
+ // | namespace-2 | dummy | |
+ // | namespace-2-origin1 | 2 (mapid) << references the new map |
+ // | map-1 | 1 (dec. refcount) | |
+ // | map-1-a | b | |
+ // | map-2 | 1 (refcount) | |
+ // | map-2-a | b | |
+ |
+ // Read the values from the old map here. If we don't need to copy the data, |
+ // this can stay empty. |
+ ValuesMap values; |
+ if (copy_data && !ReadMap(*map_id, &values, false)) |
+ return false; |
+ if (!DecreaseMapRefCount(*map_id, 1, batch)) |
+ return false; |
+ // Create a new map (this will also break the association to the old map) and |
+ // write the old data into it. This will write the id of the created map into |
+ // |map_id|. |
+ if (!CreateMapForArea(namespace_id, origin, map_id, batch)) |
+ return false; |
+ WriteValuesToMap(*map_id, values, batch); |
+ return true; |
+} |
+ |
std::string SessionStorageDatabase::NamespaceStartKey( |
const std::string& namespace_id_str) { |
return base::StringPrintf("namespace-%s", namespace_id_str.c_str()); |