OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/service_worker/service_worker_database.h" | 5 #include "content/browser/service_worker/service_worker_database.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 status = ReadResourceRecords(value.version_id, resources); | 405 status = ReadResourceRecords(value.version_id, resources); |
406 if (status != STATUS_OK) | 406 if (status != STATUS_OK) |
407 return status; | 407 return status; |
408 | 408 |
409 *registration = value; | 409 *registration = value; |
410 return STATUS_OK; | 410 return STATUS_OK; |
411 } | 411 } |
412 | 412 |
413 ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration( | 413 ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration( |
414 const RegistrationData& registration, | 414 const RegistrationData& registration, |
415 const std::vector<ResourceRecord>& resources) { | 415 const std::vector<ResourceRecord>& resources, |
| 416 std::vector<int64>* newly_purgeable_resources) { |
416 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 417 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
417 Status status = LazyOpen(true); | 418 Status status = LazyOpen(true); |
418 if (status != STATUS_OK) | 419 if (status != STATUS_OK) |
419 return status; | 420 return status; |
420 | 421 |
421 leveldb::WriteBatch batch; | 422 leveldb::WriteBatch batch; |
422 BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch); | 423 BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch); |
423 BumpNextVersionIdIfNeeded(registration.version_id, &batch); | 424 BumpNextVersionIdIfNeeded(registration.version_id, &batch); |
424 | 425 |
425 // TODO(nhiroki): Skip to add the origin into the unique origin list if it | 426 // TODO(nhiroki): Skip to add the origin into the unique origin list if it |
426 // has already been added. | 427 // has already been added. |
427 PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch); | 428 PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch); |
428 | 429 |
429 PutRegistrationDataToBatch(registration, &batch); | 430 PutRegistrationDataToBatch(registration, &batch); |
430 | 431 |
431 // Retrieve a previous version to sweep purgeable resources. | 432 // Retrieve a previous version to sweep purgeable resources. |
432 RegistrationData old_registration; | 433 RegistrationData old_registration; |
433 status = ReadRegistrationData(registration.registration_id, | 434 status = ReadRegistrationData(registration.registration_id, |
434 registration.scope.GetOrigin(), | 435 registration.scope.GetOrigin(), |
435 &old_registration); | 436 &old_registration); |
436 if (status != STATUS_OK && status != STATUS_ERROR_NOT_FOUND) | 437 if (status != STATUS_OK && status != STATUS_ERROR_NOT_FOUND) |
437 return status; | 438 return status; |
438 if (status == STATUS_OK) { | 439 if (status == STATUS_OK) { |
439 DCHECK_LT(old_registration.version_id, registration.version_id); | 440 DCHECK_LT(old_registration.version_id, registration.version_id); |
440 // Currently resource sharing across versions and registrations is not | 441 // Currently resource sharing across versions and registrations is not |
441 // suppported, so resource ids should not be overlapped between | 442 // suppported, so resource ids should not be overlapped between |
442 // |registration| and |old_registration|. | 443 // |registration| and |old_registration|. |
443 // TODO(nhiroki): Add DCHECK to make sure the overlap does not exist. | 444 // TODO(nhiroki): Add DCHECK to make sure the overlap does not exist. |
444 status = DeleteResourceRecords(old_registration.version_id, &batch); | 445 status = DeleteResourceRecords( |
| 446 old_registration.version_id, newly_purgeable_resources, &batch); |
445 if (status != STATUS_OK) | 447 if (status != STATUS_OK) |
446 return status; | 448 return status; |
447 } | 449 } |
448 | 450 |
449 // Used for avoiding multiple writes for the same resource id or url. | 451 // Used for avoiding multiple writes for the same resource id or url. |
450 std::set<int64> pushed_resources; | 452 std::set<int64> pushed_resources; |
451 std::set<GURL> pushed_urls; | 453 std::set<GURL> pushed_urls; |
452 for (std::vector<ResourceRecord>::const_iterator itr = resources.begin(); | 454 for (std::vector<ResourceRecord>::const_iterator itr = resources.begin(); |
453 itr != resources.end(); ++itr) { | 455 itr != resources.end(); ++itr) { |
454 if (!itr->url.is_valid()) | 456 if (!itr->url.is_valid()) |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 | 514 |
513 registration.last_update_check = time; | 515 registration.last_update_check = time; |
514 | 516 |
515 leveldb::WriteBatch batch; | 517 leveldb::WriteBatch batch; |
516 PutRegistrationDataToBatch(registration, &batch); | 518 PutRegistrationDataToBatch(registration, &batch); |
517 return WriteBatch(&batch); | 519 return WriteBatch(&batch); |
518 } | 520 } |
519 | 521 |
520 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteRegistration( | 522 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteRegistration( |
521 int64 registration_id, | 523 int64 registration_id, |
522 const GURL& origin) { | 524 const GURL& origin, |
| 525 std::vector<int64>* newly_purgeable_resources) { |
523 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 526 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
524 Status status = LazyOpen(false); | 527 Status status = LazyOpen(false); |
525 if (IsNewOrNonexistentDatabase(status)) | 528 if (IsNewOrNonexistentDatabase(status)) |
526 return STATUS_OK; | 529 return STATUS_OK; |
527 if (status != STATUS_OK) | 530 if (status != STATUS_OK) |
528 return status; | 531 return status; |
529 if (!origin.is_valid()) | 532 if (!origin.is_valid()) |
530 return STATUS_ERROR_FAILED; | 533 return STATUS_ERROR_FAILED; |
531 | 534 |
532 leveldb::WriteBatch batch; | 535 leveldb::WriteBatch batch; |
(...skipping 11 matching lines...) Expand all Loading... |
544 batch.Delete(CreateUniqueOriginKey(origin)); | 547 batch.Delete(CreateUniqueOriginKey(origin)); |
545 } | 548 } |
546 | 549 |
547 // Delete a registration specified by |registration_id|. | 550 // Delete a registration specified by |registration_id|. |
548 batch.Delete(CreateRegistrationKey(registration_id, origin)); | 551 batch.Delete(CreateRegistrationKey(registration_id, origin)); |
549 | 552 |
550 // Delete resource records associated with the registration. | 553 // Delete resource records associated with the registration. |
551 for (std::vector<RegistrationData>::const_iterator itr = | 554 for (std::vector<RegistrationData>::const_iterator itr = |
552 registrations.begin(); itr != registrations.end(); ++itr) { | 555 registrations.begin(); itr != registrations.end(); ++itr) { |
553 if (itr->registration_id == registration_id) { | 556 if (itr->registration_id == registration_id) { |
554 status = DeleteResourceRecords(itr->version_id, &batch); | 557 status = DeleteResourceRecords( |
| 558 itr->version_id, newly_purgeable_resources, &batch); |
555 if (status != STATUS_OK) | 559 if (status != STATUS_OK) |
556 return status; | 560 return status; |
557 break; | 561 break; |
558 } | 562 } |
559 } | 563 } |
560 | 564 |
561 return WriteBatch(&batch); | 565 return WriteBatch(&batch); |
562 } | 566 } |
563 | 567 |
564 ServiceWorkerDatabase::Status | 568 ServiceWorkerDatabase::Status |
(...skipping 20 matching lines...) Expand all Loading... |
585 ServiceWorkerDatabase::WritePurgeableResourceIds(const std::set<int64>& ids) { | 589 ServiceWorkerDatabase::WritePurgeableResourceIds(const std::set<int64>& ids) { |
586 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids); | 590 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids); |
587 } | 591 } |
588 | 592 |
589 ServiceWorkerDatabase::Status | 593 ServiceWorkerDatabase::Status |
590 ServiceWorkerDatabase::ClearPurgeableResourceIds(const std::set<int64>& ids) { | 594 ServiceWorkerDatabase::ClearPurgeableResourceIds(const std::set<int64>& ids) { |
591 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids); | 595 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids); |
592 } | 596 } |
593 | 597 |
594 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigin( | 598 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigin( |
595 const GURL& origin) { | 599 const GURL& origin, |
| 600 std::vector<int64>* newly_purgeable_resources) { |
596 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 601 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
597 Status status = LazyOpen(false); | 602 Status status = LazyOpen(false); |
598 if (IsNewOrNonexistentDatabase(status)) | 603 if (IsNewOrNonexistentDatabase(status)) |
599 return STATUS_OK; | 604 return STATUS_OK; |
600 if (status != STATUS_OK) | 605 if (status != STATUS_OK) |
601 return status; | 606 return status; |
602 if (!origin.is_valid()) | 607 if (!origin.is_valid()) |
603 return STATUS_ERROR_FAILED; | 608 return STATUS_ERROR_FAILED; |
604 | 609 |
605 leveldb::WriteBatch batch; | 610 leveldb::WriteBatch batch; |
606 | 611 |
607 // Delete from the unique origin list. | 612 // Delete from the unique origin list. |
608 batch.Delete(CreateUniqueOriginKey(origin)); | 613 batch.Delete(CreateUniqueOriginKey(origin)); |
609 | 614 |
610 std::vector<RegistrationData> registrations; | 615 std::vector<RegistrationData> registrations; |
611 status = GetRegistrationsForOrigin(origin, ®istrations); | 616 status = GetRegistrationsForOrigin(origin, ®istrations); |
612 if (status != STATUS_OK) | 617 if (status != STATUS_OK) |
613 return status; | 618 return status; |
614 | 619 |
615 // Delete registrations and resource records. | 620 // Delete registrations and resource records. |
616 for (std::vector<RegistrationData>::const_iterator itr = | 621 for (std::vector<RegistrationData>::const_iterator itr = |
617 registrations.begin(); itr != registrations.end(); ++itr) { | 622 registrations.begin(); itr != registrations.end(); ++itr) { |
618 batch.Delete(CreateRegistrationKey(itr->registration_id, origin)); | 623 batch.Delete(CreateRegistrationKey(itr->registration_id, origin)); |
619 status = DeleteResourceRecords(itr->version_id, &batch); | 624 status = DeleteResourceRecords( |
| 625 itr->version_id, newly_purgeable_resources, &batch); |
620 if (status != STATUS_OK) | 626 if (status != STATUS_OK) |
621 return status; | 627 return status; |
622 } | 628 } |
623 | 629 |
624 return WriteBatch(&batch); | 630 return WriteBatch(&batch); |
625 } | 631 } |
626 | 632 |
627 ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen( | 633 ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen( |
628 bool create_if_missing) { | 634 bool create_if_missing) { |
629 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 635 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 resources->clear(); | 767 resources->clear(); |
762 return STATUS_ERROR_CORRUPTED; | 768 return STATUS_ERROR_CORRUPTED; |
763 } | 769 } |
764 resources->push_back(resource); | 770 resources->push_back(resource); |
765 } | 771 } |
766 return STATUS_OK; | 772 return STATUS_OK; |
767 } | 773 } |
768 | 774 |
769 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceRecords( | 775 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceRecords( |
770 int64 version_id, | 776 int64 version_id, |
| 777 std::vector<int64>* newly_purgeable_resources, |
771 leveldb::WriteBatch* batch) { | 778 leveldb::WriteBatch* batch) { |
772 DCHECK(batch); | 779 DCHECK(batch); |
773 | 780 |
774 std::string prefix = CreateResourceRecordKeyPrefix(version_id); | 781 std::string prefix = CreateResourceRecordKeyPrefix(version_id); |
775 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); | 782 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
776 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { | 783 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { |
777 if (!itr->status().ok()) { | 784 if (!itr->status().ok()) { |
778 HandleError(FROM_HERE, itr->status()); | 785 HandleError(FROM_HERE, itr->status()); |
779 return LevelDBStatusToStatus(itr->status()); | 786 return LevelDBStatusToStatus(itr->status()); |
780 } | 787 } |
781 | 788 |
782 std::string key = itr->key().ToString(); | 789 std::string key = itr->key().ToString(); |
783 std::string unprefixed; | 790 std::string unprefixed; |
784 if (!RemovePrefix(key, prefix, &unprefixed)) | 791 if (!RemovePrefix(key, prefix, &unprefixed)) |
785 break; | 792 break; |
786 | 793 |
787 int64 resource_id; | 794 int64 resource_id; |
788 if (!base::StringToInt64(unprefixed, &resource_id)) { | 795 if (!base::StringToInt64(unprefixed, &resource_id)) { |
789 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 796 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
790 return STATUS_ERROR_CORRUPTED; | 797 return STATUS_ERROR_CORRUPTED; |
791 } | 798 } |
792 | 799 |
793 // Remove a resource record. | 800 // Remove a resource record. |
794 batch->Delete(key); | 801 batch->Delete(key); |
795 | 802 |
796 // Currently resource sharing across versions and registrations is not | 803 // Currently resource sharing across versions and registrations is not |
797 // supported, so we can purge this without caring about it. | 804 // supported, so we can purge this without caring about it. |
798 PutPurgeableResourceIdToBatch(resource_id, batch); | 805 PutPurgeableResourceIdToBatch(resource_id, batch); |
| 806 newly_purgeable_resources->push_back(resource_id); |
799 } | 807 } |
800 return STATUS_OK; | 808 return STATUS_OK; |
801 } | 809 } |
802 | 810 |
803 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceIds( | 811 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceIds( |
804 const char* id_key_prefix, | 812 const char* id_key_prefix, |
805 std::set<int64>* ids) { | 813 std::set<int64>* ids) { |
806 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 814 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
807 DCHECK(id_key_prefix); | 815 DCHECK(id_key_prefix); |
808 DCHECK(ids->empty()); | 816 DCHECK(ids->empty()); |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
957 // TODO(nhiroki): Add an UMA histogram. | 965 // TODO(nhiroki): Add an UMA histogram. |
958 DLOG(ERROR) << "Failed at: " << from_here.ToString() | 966 DLOG(ERROR) << "Failed at: " << from_here.ToString() |
959 << " with error: " << status.ToString(); | 967 << " with error: " << status.ToString(); |
960 is_disabled_ = true; | 968 is_disabled_ = true; |
961 if (status.IsCorruption()) | 969 if (status.IsCorruption()) |
962 was_corruption_detected_ = true; | 970 was_corruption_detected_ = true; |
963 db_.reset(); | 971 db_.reset(); |
964 } | 972 } |
965 | 973 |
966 } // namespace content | 974 } // namespace content |
OLD | NEW |