| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/browser/dom_storage/dom_storage_area.h" | 5 #include "content/browser/dom_storage/dom_storage_area.h" |
| 6 | 6 |
| 7 #include <inttypes.h> | 7 #include <inttypes.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <cctype> // for std::isalnum | 10 #include <cctype> // for std::isalnum |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 base::NullableString16* old_value) { | 188 base::NullableString16* old_value) { |
| 189 if (is_shutdown_) | 189 if (is_shutdown_) |
| 190 return false; | 190 return false; |
| 191 InitialImportIfNeeded(); | 191 InitialImportIfNeeded(); |
| 192 if (!map_->HasOneRef()) | 192 if (!map_->HasOneRef()) |
| 193 map_ = map_->DeepCopy(); | 193 map_ = map_->DeepCopy(); |
| 194 bool success = map_->SetItem(key, value, old_value); | 194 bool success = map_->SetItem(key, value, old_value); |
| 195 if (success && backing_ && | 195 if (success && backing_ && |
| 196 (old_value->is_null() || old_value->string() != value)) { | 196 (old_value->is_null() || old_value->string() != value)) { |
| 197 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); | 197 CommitBatch* commit_batch = CreateCommitBatchIfNeeded(); |
| 198 commit_batch->changed_values[key] = base::NullableString16(value, false); | 198 // Values are populated later to avoid holding duplicate memory. |
| 199 commit_batch->changed_values[key] = base::NullableString16(); |
| 199 } | 200 } |
| 200 return success; | 201 return success; |
| 201 } | 202 } |
| 202 | 203 |
| 203 bool DOMStorageArea::RemoveItem(const base::string16& key, | 204 bool DOMStorageArea::RemoveItem(const base::string16& key, |
| 204 base::string16* old_value) { | 205 base::string16* old_value) { |
| 205 if (is_shutdown_) | 206 if (is_shutdown_) |
| 206 return false; | 207 return false; |
| 207 InitialImportIfNeeded(); | 208 InitialImportIfNeeded(); |
| 208 if (!map_->HasOneRef()) | 209 if (!map_->HasOneRef()) |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 kPerStorageAreaOverQuotaAllowance); | 321 kPerStorageAreaOverQuotaAllowance); |
| 321 | 322 |
| 322 // Recreate the database object, this frees up the open sqlite connection | 323 // Recreate the database object, this frees up the open sqlite connection |
| 323 // and its page cache. | 324 // and its page cache. |
| 324 backing_->Reset(); | 325 backing_->Reset(); |
| 325 } | 326 } |
| 326 | 327 |
| 327 void DOMStorageArea::Shutdown() { | 328 void DOMStorageArea::Shutdown() { |
| 328 DCHECK(!is_shutdown_); | 329 DCHECK(!is_shutdown_); |
| 329 is_shutdown_ = true; | 330 is_shutdown_ = true; |
| 331 |
| 332 if (commit_batch_) { |
| 333 DCHECK(backing_); |
| 334 PopulateCommitBatchValues(); |
| 335 } |
| 336 |
| 330 map_ = NULL; | 337 map_ = NULL; |
| 331 if (!backing_) | 338 if (!backing_) |
| 332 return; | 339 return; |
| 333 | 340 |
| 334 bool success = task_runner_->PostShutdownBlockingTask( | 341 bool success = task_runner_->PostShutdownBlockingTask( |
| 335 FROM_HERE, | 342 FROM_HERE, |
| 336 DOMStorageTaskRunner::COMMIT_SEQUENCE, | 343 DOMStorageTaskRunner::COMMIT_SEQUENCE, |
| 337 base::Bind(&DOMStorageArea::ShutdownInCommitSequence, this)); | 344 base::Bind(&DOMStorageArea::ShutdownInCommitSequence, this)); |
| 338 DCHECK(success); | 345 DCHECK(success); |
| 339 } | 346 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 DCHECK(!is_shutdown_); | 427 DCHECK(!is_shutdown_); |
| 421 if (!commit_batch_) { | 428 if (!commit_batch_) { |
| 422 commit_batch_.reset(new CommitBatch()); | 429 commit_batch_.reset(new CommitBatch()); |
| 423 BrowserThread::PostAfterStartupTask( | 430 BrowserThread::PostAfterStartupTask( |
| 424 FROM_HERE, task_runner_, | 431 FROM_HERE, task_runner_, |
| 425 base::Bind(&DOMStorageArea::StartCommitTimer, this)); | 432 base::Bind(&DOMStorageArea::StartCommitTimer, this)); |
| 426 } | 433 } |
| 427 return commit_batch_.get(); | 434 return commit_batch_.get(); |
| 428 } | 435 } |
| 429 | 436 |
| 437 void DOMStorageArea::PopulateCommitBatchValues() { |
| 438 DCHECK(task_runner_->IsRunningOnPrimarySequence()); |
| 439 for (auto& key_value : commit_batch_->changed_values) |
| 440 key_value.second = map_->GetItem(key_value.first); |
| 441 } |
| 442 |
| 430 void DOMStorageArea::StartCommitTimer() { | 443 void DOMStorageArea::StartCommitTimer() { |
| 431 if (is_shutdown_ || !commit_batch_) | 444 if (is_shutdown_ || !commit_batch_) |
| 432 return; | 445 return; |
| 433 | 446 |
| 434 // Start a timer to commit any changes that accrue in the batch, but only if | 447 // Start a timer to commit any changes that accrue in the batch, but only if |
| 435 // no commits are currently in flight. In that case the timer will be | 448 // no commits are currently in flight. In that case the timer will be |
| 436 // started after the commits have happened. | 449 // started after the commits have happened. |
| 437 if (commit_batches_in_flight_) | 450 if (commit_batches_in_flight_) |
| 438 return; | 451 return; |
| 439 | 452 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 466 | 479 |
| 467 PostCommitTask(); | 480 PostCommitTask(); |
| 468 } | 481 } |
| 469 | 482 |
| 470 void DOMStorageArea::PostCommitTask() { | 483 void DOMStorageArea::PostCommitTask() { |
| 471 if (is_shutdown_ || !commit_batch_) | 484 if (is_shutdown_ || !commit_batch_) |
| 472 return; | 485 return; |
| 473 | 486 |
| 474 DCHECK(backing_.get()); | 487 DCHECK(backing_.get()); |
| 475 | 488 |
| 489 PopulateCommitBatchValues(); |
| 476 commit_rate_limiter_.add_samples(1); | 490 commit_rate_limiter_.add_samples(1); |
| 477 data_rate_limiter_.add_samples(commit_batch_->GetDataSize()); | 491 data_rate_limiter_.add_samples(commit_batch_->GetDataSize()); |
| 478 | 492 |
| 479 // This method executes on the primary sequence, we schedule | 493 // This method executes on the primary sequence, we schedule |
| 480 // a task for immediate execution on the commit sequence. | 494 // a task for immediate execution on the commit sequence. |
| 481 DCHECK(task_runner_->IsRunningOnPrimarySequence()); | 495 DCHECK(task_runner_->IsRunningOnPrimarySequence()); |
| 482 bool success = task_runner_->PostShutdownBlockingTask( | 496 bool success = task_runner_->PostShutdownBlockingTask( |
| 483 FROM_HERE, | 497 FROM_HERE, |
| 484 DOMStorageTaskRunner::COMMIT_SEQUENCE, | 498 DOMStorageTaskRunner::COMMIT_SEQUENCE, |
| 485 base::Bind(&DOMStorageArea::CommitChanges, this, | 499 base::Bind(&DOMStorageArea::CommitChanges, this, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 commit_batch_->clear_all_first, | 538 commit_batch_->clear_all_first, |
| 525 commit_batch_->changed_values); | 539 commit_batch_->changed_values); |
| 526 DCHECK(success); | 540 DCHECK(success); |
| 527 } | 541 } |
| 528 commit_batch_.reset(); | 542 commit_batch_.reset(); |
| 529 backing_.reset(); | 543 backing_.reset(); |
| 530 session_storage_backing_ = NULL; | 544 session_storage_backing_ = NULL; |
| 531 } | 545 } |
| 532 | 546 |
| 533 } // namespace content | 547 } // namespace content |
| OLD | NEW |