Chromium Code Reviews| 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/dom_storage_area.h" | 5 #include "webkit/dom_storage/dom_storage_area.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/file_util.h" | |
| 9 #include "base/location.h" | 8 #include "base/location.h" |
| 10 #include "base/logging.h" | 9 #include "base/logging.h" |
| 11 #include "base/time.h" | 10 #include "base/time.h" |
| 12 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | 11 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
| 13 #include "webkit/database/database_util.h" | 12 #include "webkit/database/database_util.h" |
| 13 #include "webkit/dom_storage/dom_storage_database.h" | |
| 14 #include "webkit/dom_storage/dom_storage_map.h" | 14 #include "webkit/dom_storage/dom_storage_map.h" |
| 15 #include "webkit/dom_storage/dom_storage_namespace.h" | 15 #include "webkit/dom_storage/dom_storage_namespace.h" |
| 16 #include "webkit/dom_storage/dom_storage_task_runner.h" | 16 #include "webkit/dom_storage/dom_storage_task_runner.h" |
| 17 #include "webkit/dom_storage/dom_storage_types.h" | 17 #include "webkit/dom_storage/dom_storage_types.h" |
| 18 #include "webkit/dom_storage/local_storage_database_adapter.h" | |
| 19 #include "webkit/dom_storage/session_storage_database.h" | |
| 20 #include "webkit/dom_storage/session_storage_database_adapter.h" | |
| 18 #include "webkit/fileapi/file_system_util.h" | 21 #include "webkit/fileapi/file_system_util.h" |
| 19 #include "webkit/glue/webkit_glue.h" | 22 #include "webkit/glue/webkit_glue.h" |
| 20 | 23 |
| 21 using webkit_database::DatabaseUtil; | 24 using webkit_database::DatabaseUtil; |
| 22 | 25 |
| 23 namespace dom_storage { | 26 namespace dom_storage { |
| 24 | 27 |
| 25 static const int kCommitTimerSeconds = 1; | 28 static const int kCommitTimerSeconds = 1; |
| 26 | 29 |
| 27 DomStorageArea::CommitBatch::CommitBatch() | 30 DomStorageArea::CommitBatch::CommitBatch() |
| 28 : clear_all_first(false) { | 31 : clear_all_first(false), |
| 32 clear_all_after_deep_copy(false) { | |
| 29 } | 33 } |
| 30 DomStorageArea::CommitBatch::~CommitBatch() {} | 34 DomStorageArea::CommitBatch::~CommitBatch() {} |
| 31 | 35 |
| 32 | 36 |
| 33 // static | 37 // static |
| 34 const FilePath::CharType DomStorageArea::kDatabaseFileExtension[] = | 38 const FilePath::CharType DomStorageArea::kDatabaseFileExtension[] = |
| 35 FILE_PATH_LITERAL(".localstorage"); | 39 FILE_PATH_LITERAL(".localstorage"); |
| 36 | 40 |
| 37 // static | 41 // static |
| 38 FilePath DomStorageArea::DatabaseFileNameFromOrigin(const GURL& origin) { | 42 FilePath DomStorageArea::DatabaseFileNameFromOrigin(const GURL& origin) { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 52 return DatabaseUtil::GetOriginFromIdentifier(origin_id); | 56 return DatabaseUtil::GetOriginFromIdentifier(origin_id); |
| 53 } | 57 } |
| 54 | 58 |
| 55 DomStorageArea::DomStorageArea( | 59 DomStorageArea::DomStorageArea( |
| 56 int64 namespace_id, const GURL& origin, | 60 int64 namespace_id, const GURL& origin, |
| 57 const FilePath& directory, DomStorageTaskRunner* task_runner) | 61 const FilePath& directory, DomStorageTaskRunner* task_runner) |
| 58 : namespace_id_(namespace_id), origin_(origin), | 62 : namespace_id_(namespace_id), origin_(origin), |
| 59 directory_(directory), | 63 directory_(directory), |
| 60 task_runner_(task_runner), | 64 task_runner_(task_runner), |
| 61 map_(new DomStorageMap(kPerAreaQuota)), | 65 map_(new DomStorageMap(kPerAreaQuota)), |
| 66 is_initial_import_done_(false), | |
| 67 is_shutdown_(false), | |
| 68 is_shallow_copy_(false) { | |
| 69 DCHECK(!directory.empty()); | |
| 70 DCHECK_EQ(kLocalStorageNamespaceId, namespace_id); | |
| 71 FilePath path = directory.Append(DatabaseFileNameFromOrigin(origin_)); | |
| 72 backing_.reset(new LocalStorageDatabaseAdapter(new DomStorageDatabase(path))); | |
| 73 } | |
| 74 | |
| 75 DomStorageArea::DomStorageArea( | |
| 76 int64 namespace_id, const GURL& origin, | |
| 77 SessionStorageDatabase* session_storage_backing, | |
| 78 DomStorageTaskRunner* task_runner) | |
| 79 : namespace_id_(namespace_id), origin_(origin), | |
| 80 task_runner_(task_runner), | |
| 81 map_(new DomStorageMap(kPerAreaQuota)), | |
| 82 session_storage_backing_(session_storage_backing), | |
| 83 is_initial_import_done_(false), | |
| 84 is_shutdown_(false), | |
| 85 is_shallow_copy_(false) { | |
| 86 DCHECK(namespace_id != kLocalStorageNamespaceId); | |
| 87 backing_.reset(new SessionStorageDatabaseAdapter( | |
| 88 session_storage_backing, namespace_id, origin)); | |
| 89 } | |
| 90 | |
| 91 DomStorageArea::DomStorageArea(int64 namespace_id, | |
| 92 const GURL& origin, | |
| 93 DomStorageTaskRunner* task_runner) | |
| 94 : namespace_id_(namespace_id), origin_(origin), | |
| 95 task_runner_(task_runner), | |
| 96 map_(new DomStorageMap(kPerAreaQuota)), | |
| 62 is_initial_import_done_(true), | 97 is_initial_import_done_(true), |
| 63 is_shutdown_(false) { | 98 is_shutdown_(false), |
| 64 if (namespace_id == kLocalStorageNamespaceId && !directory.empty()) { | 99 is_shallow_copy_(false) { |
| 65 FilePath path = directory.Append(DatabaseFileNameFromOrigin(origin_)); | |
| 66 backing_.reset(new DomStorageDatabase(path)); | |
| 67 is_initial_import_done_ = false; | |
| 68 } | |
| 69 } | 100 } |
| 70 | 101 |
| 71 DomStorageArea::~DomStorageArea() { | 102 DomStorageArea::~DomStorageArea() { |
| 72 } | 103 } |
| 73 | 104 |
| 74 unsigned DomStorageArea::Length() { | 105 unsigned DomStorageArea::Length() { |
| 75 if (is_shutdown_) | 106 if (is_shutdown_) |
| 76 return 0; | 107 return 0; |
| 77 InitialImportIfNeeded(); | 108 InitialImportIfNeeded(); |
| 78 return map_->Length(); | 109 return map_->Length(); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 91 InitialImportIfNeeded(); | 122 InitialImportIfNeeded(); |
| 92 return map_->GetItem(key); | 123 return map_->GetItem(key); |
| 93 } | 124 } |
| 94 | 125 |
| 95 bool DomStorageArea::SetItem(const string16& key, | 126 bool DomStorageArea::SetItem(const string16& key, |
| 96 const string16& value, | 127 const string16& value, |
| 97 NullableString16* old_value) { | 128 NullableString16* old_value) { |
| 98 if (is_shutdown_) | 129 if (is_shutdown_) |
| 99 return false; | 130 return false; |
| 100 InitialImportIfNeeded(); | 131 InitialImportIfNeeded(); |
| 101 if (!map_->HasOneRef()) | 132 bool was_shallow_copy = is_shallow_copy_; |
| 102 map_ = map_->DeepCopy(); | 133 if (is_shallow_copy_) { |
| 134 // It's possible that the other DomStorageAreas referring to the same map | |
| 135 // already made a deep copy. If that's the case, we don't need to do | |
| 136 // anything. | |
|
michaeln
2012/04/22 21:43:35
i'd rather depend on HasOneRef() for this and nix
marja
2012/05/11 12:18:32
Done.
| |
| 137 if (!map_->HasOneRef()) | |
| 138 map_ = map_->DeepCopy(); | |
| 139 is_shallow_copy_ = false; | |
| 140 } | |
| 103 bool success = map_->SetItem(key, value, old_value); | 141 bool success = map_->SetItem(key, value, old_value); |
| 104 if (success && backing_.get()) { | 142 if (success && backing_.get()) { |
| 105 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | 143 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); |
| 106 commit_batch->changed_values[key] = NullableString16(value, false); | 144 // If this area was a shallow copy, the existing changes in the commit batch |
| 145 // should be committed before doing a deep copy. This change, and all the | |
| 146 // changes after this, should be committed after the deep copy. The database | |
| 147 // takes care of not doing a deep copy of a map which is only referred to | |
| 148 // once. | |
|
michaeln
2012/04/22 21:43:35
It might be a simplification to flush pending chan
michaeln
2012/04/22 23:48:02
or maybe a pattern like this that factors out more
marja
2012/05/11 12:18:32
- The deep copy problem was solved by http://coder
michaeln
2012/05/16 08:10:55
sgtm!
| |
| 149 if (was_shallow_copy || | |
| 150 !commit_batch->changed_values_after_deep_copy.empty() || | |
| 151 commit_batch->clear_all_after_deep_copy) { | |
| 152 commit_batch->changed_values_after_deep_copy[key] = | |
| 153 NullableString16(value, false); | |
| 154 } | |
| 155 else { | |
| 156 commit_batch->changed_values[key] = NullableString16(value, false); | |
| 157 } | |
| 107 } | 158 } |
| 108 return success; | 159 return success; |
| 109 } | 160 } |
| 110 | 161 |
| 111 bool DomStorageArea::RemoveItem(const string16& key, string16* old_value) { | 162 bool DomStorageArea::RemoveItem(const string16& key, string16* old_value) { |
| 112 if (is_shutdown_) | 163 if (is_shutdown_) |
| 113 return false; | 164 return false; |
| 114 InitialImportIfNeeded(); | 165 InitialImportIfNeeded(); |
| 115 if (!map_->HasOneRef()) | 166 // See comments in SetItem. |
| 116 map_ = map_->DeepCopy(); | 167 bool was_shallow_copy = is_shallow_copy_; |
| 168 if (is_shallow_copy_) { | |
| 169 if (!map_->HasOneRef()) | |
| 170 map_ = map_->DeepCopy(); | |
| 171 is_shallow_copy_ = false; | |
| 172 } | |
| 117 bool success = map_->RemoveItem(key, old_value); | 173 bool success = map_->RemoveItem(key, old_value); |
| 118 if (success && backing_.get()) { | 174 if (success && backing_.get()) { |
| 119 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | 175 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); |
| 120 commit_batch->changed_values[key] = NullableString16(true); | 176 if (was_shallow_copy || |
| 177 !commit_batch->changed_values_after_deep_copy.empty() || | |
| 178 commit_batch->clear_all_after_deep_copy) { | |
| 179 commit_batch->changed_values_after_deep_copy[key] = | |
| 180 NullableString16(true); | |
| 181 } else { | |
| 182 commit_batch->changed_values[key] = NullableString16(true); | |
| 183 } | |
| 121 } | 184 } |
| 122 return success; | 185 return success; |
| 123 } | 186 } |
| 124 | 187 |
| 125 bool DomStorageArea::Clear() { | 188 bool DomStorageArea::Clear() { |
| 126 if (is_shutdown_) | 189 if (is_shutdown_) |
| 127 return false; | 190 return false; |
| 128 InitialImportIfNeeded(); | 191 InitialImportIfNeeded(); |
| 129 if (map_->Length() == 0) | 192 if (map_->Length() == 0) |
| 130 return false; | 193 return false; |
| 131 | 194 |
| 195 // See comments in SetItem. | |
| 196 bool was_shallow_copy = is_shallow_copy_; | |
| 197 is_shallow_copy_ = false; | |
| 132 map_ = new DomStorageMap(kPerAreaQuota); | 198 map_ = new DomStorageMap(kPerAreaQuota); |
| 133 | 199 |
| 134 if (backing_.get()) { | 200 if (backing_.get()) { |
| 135 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | 201 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); |
| 136 commit_batch->clear_all_first = true; | 202 if (was_shallow_copy || |
| 137 commit_batch->changed_values.clear(); | 203 !commit_batch->changed_values_after_deep_copy.empty() || |
| 204 commit_batch->clear_all_after_deep_copy) { | |
| 205 commit_batch->clear_all_after_deep_copy = true; | |
| 206 commit_batch->changed_values_after_deep_copy.clear(); | |
| 207 } else { | |
| 208 commit_batch->clear_all_first = true; | |
| 209 commit_batch->changed_values.clear(); | |
| 210 } | |
| 138 } | 211 } |
| 139 | 212 |
| 140 return true; | 213 return true; |
| 141 } | 214 } |
| 142 | 215 |
| 143 DomStorageArea* DomStorageArea::ShallowCopy(int64 destination_namespace_id) { | 216 DomStorageArea* DomStorageArea::ShallowCopy(int64 destination_namespace_id) { |
| 144 DCHECK_NE(kLocalStorageNamespaceId, namespace_id_); | 217 DCHECK_NE(kLocalStorageNamespaceId, namespace_id_); |
| 145 DCHECK_NE(kLocalStorageNamespaceId, destination_namespace_id); | 218 DCHECK_NE(kLocalStorageNamespaceId, destination_namespace_id); |
| 146 DCHECK(!backing_.get()); // SessionNamespaces aren't stored on disk. | 219 DCHECK(session_storage_backing_.get()); |
| 147 | 220 |
| 148 DomStorageArea* copy = new DomStorageArea(destination_namespace_id, origin_, | 221 DomStorageArea* copy = new DomStorageArea( |
| 149 FilePath(), task_runner_); | 222 destination_namespace_id, origin_, session_storage_backing_, |
| 223 task_runner_); | |
| 224 copy->is_shallow_copy_ = true; | |
| 150 copy->map_ = map_; | 225 copy->map_ = map_; |
| 151 copy->is_shutdown_ = is_shutdown_; | 226 copy->is_shutdown_ = is_shutdown_; |
| 227 | |
| 228 // Also this area is now a shallow copy; changes to either of these 2 areas | |
| 229 // will initiate deep copying. | |
| 230 is_shallow_copy_ = true; | |
| 231 | |
| 232 if (session_storage_backing_.get()) { | |
| 233 // If this area has uncommitted changes, they need to happen before | |
| 234 // DomStorageNamespace does the shallow-copying of the database. Also, if | |
| 235 // the area is empty, we need to ensure that a placeholder for it exists in | |
| 236 // the database. An empty commit batch achieves this. | |
|
michaeln
2012/04/22 21:43:35
Does the empty placeholder really need to be there
marja
2012/05/11 12:18:32
Done. Empty placeholder is not needed any more.
| |
| 237 CreateCommitBatchIfNeeded(); | |
| 238 OnCommitTimer(); | |
| 239 } | |
| 152 return copy; | 240 return copy; |
| 153 } | 241 } |
| 154 | 242 |
| 155 bool DomStorageArea::HasUncommittedChanges() const { | 243 bool DomStorageArea::HasUncommittedChanges() const { |
| 156 DCHECK(!is_shutdown_); | 244 DCHECK(!is_shutdown_); |
| 157 return commit_batch_.get() || in_flight_commit_batch_.get(); | 245 return commit_batch_.get() || in_flight_commit_batch_.get(); |
| 158 } | 246 } |
| 159 | 247 |
| 160 void DomStorageArea::DeleteOrigin() { | 248 void DomStorageArea::DeleteOrigin() { |
| 161 DCHECK(!is_shutdown_); | 249 DCHECK(!is_shutdown_); |
| 162 if (HasUncommittedChanges()) { | 250 if (HasUncommittedChanges()) { |
| 163 // TODO(michaeln): This logically deletes the data immediately, | 251 // TODO(michaeln): This logically deletes the data immediately, |
| 164 // and in a matter of a second, deletes the rows from the backing | 252 // and in a matter of a second, deletes the rows from the backing |
| 165 // database file, but the file itself will linger until shutdown | 253 // database file, but the file itself will linger until shutdown |
| 166 // or purge time. Ideally, this should delete the file more | 254 // or purge time. Ideally, this should delete the file more |
| 167 // quickly. | 255 // quickly. |
| 168 Clear(); | 256 Clear(); |
| 169 return; | 257 return; |
| 170 } | 258 } |
| 171 map_ = new DomStorageMap(kPerAreaQuota); | 259 map_ = new DomStorageMap(kPerAreaQuota); |
| 172 if (backing_.get()) { | 260 if (backing_.get() && !session_storage_backing_.get()) { |
| 261 // This is localStorage. | |
| 173 is_initial_import_done_ = false; | 262 is_initial_import_done_ = false; |
| 174 backing_.reset(new DomStorageDatabase(backing_->file_path())); | 263 backing_->Reset(); |
| 175 file_util::Delete(backing_->file_path(), false); | 264 backing_->DeleteFiles(); |
| 176 file_util::Delete( | 265 } else if (session_storage_backing_.get()) { |
| 177 DomStorageDatabase::GetJournalFilePath(backing_->file_path()), false); | 266 // Delete the origin from the session storage by creating an empty commit |
| 267 // batch. | |
| 268 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | |
| 269 if (is_shallow_copy_) | |
| 270 commit_batch->clear_all_after_deep_copy = true; | |
| 271 else | |
| 272 commit_batch->clear_all_first = true; | |
| 178 } | 273 } |
| 179 } | 274 } |
| 180 | 275 |
| 181 void DomStorageArea::PurgeMemory() { | 276 void DomStorageArea::PurgeMemory() { |
| 182 DCHECK(!is_shutdown_); | 277 DCHECK(!is_shutdown_); |
| 183 if (!is_initial_import_done_ || // We're not using any memory. | 278 if (!is_initial_import_done_ || // We're not using any memory. |
| 184 !backing_.get() || // We can't purge anything. | 279 !backing_.get() || // We can't purge anything. |
| 185 HasUncommittedChanges()) // We leave things alone with changes pending. | 280 HasUncommittedChanges()) // We leave things alone with changes pending. |
| 186 return; | 281 return; |
| 187 | 282 |
| 188 // Drop the in memory cache, we'll reload when needed. | 283 // Drop the in memory cache, we'll reload when needed. |
| 189 is_initial_import_done_ = false; | 284 is_initial_import_done_ = false; |
| 190 map_ = new DomStorageMap(kPerAreaQuota); | 285 map_ = new DomStorageMap(kPerAreaQuota); |
| 191 | 286 |
| 192 // Recreate the database object, this frees up the open sqlite connection | 287 // Recreate the database object, this frees up the open sqlite connection |
| 193 // and its page cache. | 288 // and its page cache. |
| 194 backing_.reset(new DomStorageDatabase(backing_->file_path())); | 289 backing_->Reset(); |
| 195 } | 290 } |
| 196 | 291 |
| 197 void DomStorageArea::Shutdown() { | 292 void DomStorageArea::Shutdown() { |
| 198 DCHECK(!is_shutdown_); | 293 DCHECK(!is_shutdown_); |
| 199 is_shutdown_ = true; | 294 is_shutdown_ = true; |
| 200 map_ = NULL; | 295 map_ = NULL; |
| 201 if (!backing_.get()) | 296 if (!backing_.get()) |
| 202 return; | 297 return; |
| 203 | 298 |
| 204 bool success = task_runner_->PostShutdownBlockingTask( | 299 bool success = task_runner_->PostShutdownBlockingTask( |
| 205 FROM_HERE, | 300 FROM_HERE, |
| 206 DomStorageTaskRunner::COMMIT_SEQUENCE, | 301 DomStorageTaskRunner::COMMIT_SEQUENCE, |
| 207 base::Bind(&DomStorageArea::ShutdownInCommitSequence, this)); | 302 base::Bind(&DomStorageArea::ShutdownInCommitSequence, this)); |
| 208 DCHECK(success); | 303 DCHECK(success); |
| 209 } | 304 } |
| 210 | 305 |
| 211 void DomStorageArea::InitialImportIfNeeded() { | 306 void DomStorageArea::InitialImportIfNeeded() { |
| 212 if (is_initial_import_done_) | 307 if (is_initial_import_done_) |
| 213 return; | 308 return; |
| 214 | 309 |
| 215 DCHECK_EQ(kLocalStorageNamespaceId, namespace_id_); | |
| 216 DCHECK(backing_.get()); | 310 DCHECK(backing_.get()); |
| 217 | 311 |
| 218 ValuesMap initial_values; | 312 ValuesMap initial_values; |
| 219 backing_->ReadAllValues(&initial_values); | 313 backing_->ReadAllValues(&initial_values); |
| 220 map_->SwapValues(&initial_values); | 314 map_->SwapValues(&initial_values); |
| 221 is_initial_import_done_ = true; | 315 is_initial_import_done_ = true; |
| 222 } | 316 } |
| 223 | 317 |
| 224 DomStorageArea::CommitBatch* DomStorageArea::CreateCommitBatchIfNeeded() { | 318 DomStorageArea::CommitBatch* DomStorageArea::CreateCommitBatchIfNeeded() { |
| 225 DCHECK(!is_shutdown_); | 319 DCHECK(!is_shutdown_); |
| 226 if (!commit_batch_.get()) { | 320 if (!commit_batch_.get()) { |
| 227 commit_batch_.reset(new CommitBatch()); | 321 commit_batch_.reset(new CommitBatch()); |
| 228 | 322 |
| 229 // Start a timer to commit any changes that accrue in the batch, | 323 // Start a timer to commit any changes that accrue in the batch, |
| 230 // but only if a commit is not currently in flight. In that case | 324 // but only if a commit is not currently in flight. In that case |
| 231 // the timer will be started after the current commit has happened. | 325 // the timer will be started after the current commit has happened. |
| 232 if (!in_flight_commit_batch_.get()) { | 326 if (!in_flight_commit_batch_.get()) { |
| 233 task_runner_->PostDelayedTask( | 327 task_runner_->PostDelayedTask( |
| 234 FROM_HERE, | 328 FROM_HERE, |
| 235 base::Bind(&DomStorageArea::OnCommitTimer, this), | 329 base::Bind(&DomStorageArea::OnCommitTimer, this), |
| 236 base::TimeDelta::FromSeconds(kCommitTimerSeconds)); | 330 base::TimeDelta::FromSeconds(kCommitTimerSeconds)); |
| 237 } | 331 } |
| 238 } | 332 } |
| 239 return commit_batch_.get(); | 333 return commit_batch_.get(); |
| 240 } | 334 } |
| 241 | 335 |
| 242 void DomStorageArea::OnCommitTimer() { | 336 void DomStorageArea::OnCommitTimer() { |
| 243 DCHECK_EQ(kLocalStorageNamespaceId, namespace_id_); | |
| 244 if (is_shutdown_) | 337 if (is_shutdown_) |
| 245 return; | 338 return; |
| 246 | 339 |
| 247 DCHECK(backing_.get()); | 340 DCHECK(backing_.get()); |
| 248 DCHECK(commit_batch_.get()); | 341 // It's possible that there is nothing to commit, since a shallow copy occured |
| 342 // before the timer fired. | |
| 343 if (!commit_batch_.get()) | |
| 344 return; | |
| 345 | |
| 249 DCHECK(!in_flight_commit_batch_.get()); | 346 DCHECK(!in_flight_commit_batch_.get()); |
| 250 | 347 |
| 251 // This method executes on the primary sequence, we schedule | 348 // This method executes on the primary sequence, we schedule |
| 252 // a task for immediate execution on the commit sequence. | 349 // a task for immediate execution on the commit sequence. |
| 253 DCHECK(task_runner_->IsRunningOnPrimarySequence()); | 350 DCHECK(task_runner_->IsRunningOnPrimarySequence()); |
| 254 in_flight_commit_batch_ = commit_batch_.Pass(); | 351 in_flight_commit_batch_ = commit_batch_.Pass(); |
| 255 bool success = task_runner_->PostShutdownBlockingTask( | 352 bool success = task_runner_->PostShutdownBlockingTask( |
| 256 FROM_HERE, | 353 FROM_HERE, |
| 257 DomStorageTaskRunner::COMMIT_SEQUENCE, | 354 DomStorageTaskRunner::COMMIT_SEQUENCE, |
| 258 base::Bind(&DomStorageArea::CommitChanges, this)); | 355 base::Bind(&DomStorageArea::CommitChanges, this)); |
| 259 DCHECK(success); | 356 DCHECK(success); |
| 260 } | 357 } |
| 261 | 358 |
| 262 void DomStorageArea::CommitChanges() { | 359 void DomStorageArea::CommitChanges() { |
| 263 // This method executes on the commit sequence. | 360 // This method executes on the commit sequence. |
| 264 DCHECK(task_runner_->IsRunningOnCommitSequence()); | 361 DCHECK(task_runner_->IsRunningOnCommitSequence()); |
| 265 DCHECK(in_flight_commit_batch_.get()); | 362 DCHECK(in_flight_commit_batch_.get()); |
| 266 bool success = backing_->CommitChanges( | 363 bool success = backing_->CommitChanges( |
| 267 in_flight_commit_batch_->clear_all_first, | 364 in_flight_commit_batch_->clear_all_first, |
| 268 in_flight_commit_batch_->changed_values); | 365 in_flight_commit_batch_->changed_values); |
| 269 DCHECK(success); // TODO(michaeln): what if it fails? | 366 DCHECK(success); // TODO(michaeln): what if it fails? |
| 367 if (session_storage_backing_.get() && | |
| 368 (in_flight_commit_batch_->clear_all_after_deep_copy || | |
| 369 !in_flight_commit_batch_->changed_values_after_deep_copy.empty())) { | |
| 370 if (in_flight_commit_batch_->clear_all_after_deep_copy) { | |
| 371 // Shortcut: If we're going to make a deep copy and clear the area, no | |
| 372 // need to create the deep copy first. We will just break the association | |
| 373 // to the existing map. A new map will be created when data is inserted | |
| 374 // into it. | |
| 375 session_storage_backing_->DisassociateMap(namespace_id_, origin_); | |
| 376 } else { | |
| 377 session_storage_backing_->DeepCopy(namespace_id_, origin_); | |
| 378 } | |
| 379 bool success = backing_->CommitChanges( | |
| 380 false, in_flight_commit_batch_->changed_values_after_deep_copy); | |
| 381 DCHECK(success); // TODO(michaeln): what if it fails? | |
| 382 } | |
| 383 | |
| 270 task_runner_->PostTask( | 384 task_runner_->PostTask( |
| 271 FROM_HERE, | 385 FROM_HERE, |
| 272 base::Bind(&DomStorageArea::OnCommitComplete, this)); | 386 base::Bind(&DomStorageArea::OnCommitComplete, this)); |
| 273 } | 387 } |
| 274 | 388 |
| 275 void DomStorageArea::OnCommitComplete() { | 389 void DomStorageArea::OnCommitComplete() { |
| 276 // We're back on the primary sequence in this method. | 390 // We're back on the primary sequence in this method. |
| 277 DCHECK(task_runner_->IsRunningOnPrimarySequence()); | 391 DCHECK(task_runner_->IsRunningOnPrimarySequence()); |
| 278 if (is_shutdown_) | 392 if (is_shutdown_) |
| 279 return; | 393 return; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 294 if (commit_batch_.get()) { | 408 if (commit_batch_.get()) { |
| 295 // Commit any changes that accrued prior to the timer firing. | 409 // Commit any changes that accrued prior to the timer firing. |
| 296 bool success = backing_->CommitChanges( | 410 bool success = backing_->CommitChanges( |
| 297 commit_batch_->clear_all_first, | 411 commit_batch_->clear_all_first, |
| 298 commit_batch_->changed_values); | 412 commit_batch_->changed_values); |
| 299 DCHECK(success); | 413 DCHECK(success); |
| 300 } | 414 } |
| 301 commit_batch_.reset(); | 415 commit_batch_.reset(); |
| 302 in_flight_commit_batch_.reset(); | 416 in_flight_commit_batch_.reset(); |
| 303 backing_.reset(); | 417 backing_.reset(); |
| 418 session_storage_backing_ = NULL; | |
| 304 } | 419 } |
| 305 | 420 |
| 306 } // namespace dom_storage | 421 } // namespace dom_storage |
| OLD | NEW |