| 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 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 if (!ParseRegistrationData(itr->value().ToString(), ®istration)) { | 377 if (!ParseRegistrationData(itr->value().ToString(), ®istration)) { |
| 378 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 378 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
| 379 registrations->clear(); | 379 registrations->clear(); |
| 380 return STATUS_ERROR_CORRUPTED; | 380 return STATUS_ERROR_CORRUPTED; |
| 381 } | 381 } |
| 382 registrations->push_back(registration); | 382 registrations->push_back(registration); |
| 383 } | 383 } |
| 384 return STATUS_OK; | 384 return STATUS_OK; |
| 385 } | 385 } |
| 386 | 386 |
| 387 bool ServiceWorkerDatabase::ReadRegistration( | 387 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistration( |
| 388 int64 registration_id, | 388 int64 registration_id, |
| 389 const GURL& origin, | 389 const GURL& origin, |
| 390 RegistrationData* registration, | 390 RegistrationData* registration, |
| 391 std::vector<ResourceRecord>* resources) { | 391 std::vector<ResourceRecord>* resources) { |
| 392 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 392 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 393 DCHECK(registration); | 393 DCHECK(registration); |
| 394 DCHECK(resources); | 394 DCHECK(resources); |
| 395 | 395 |
| 396 Status status = LazyOpen(false); | 396 Status status = LazyOpen(false); |
| 397 if (IsNewOrNonexistentDatabase(status) || status != STATUS_OK) | 397 if (IsNewOrNonexistentDatabase(status) || status != STATUS_OK) |
| 398 return false; | 398 return status; |
| 399 | 399 |
| 400 RegistrationData value; | 400 RegistrationData value; |
| 401 if (!ReadRegistrationData(registration_id, origin, &value)) | 401 status = ReadRegistrationData(registration_id, origin, &value); |
| 402 return false; | 402 if (status != STATUS_OK) |
| 403 return status; |
| 403 | 404 |
| 404 if (!ReadResourceRecords(value.version_id, resources)) | 405 status = ReadResourceRecords(value.version_id, resources); |
| 405 return false; | 406 if (status != STATUS_OK) |
| 407 return status; |
| 406 | 408 |
| 407 *registration = value; | 409 *registration = value; |
| 408 return true; | 410 return STATUS_OK; |
| 409 } | 411 } |
| 410 | 412 |
| 411 bool ServiceWorkerDatabase::WriteRegistration( | 413 ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration( |
| 412 const RegistrationData& registration, | 414 const RegistrationData& registration, |
| 413 const std::vector<ResourceRecord>& resources) { | 415 const std::vector<ResourceRecord>& resources) { |
| 414 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 416 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 415 if (LazyOpen(true) != STATUS_OK) | 417 Status status = LazyOpen(true); |
| 416 return false; | 418 if (status != STATUS_OK) |
| 419 return status; |
| 417 | 420 |
| 418 leveldb::WriteBatch batch; | 421 leveldb::WriteBatch batch; |
| 419 BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch); | 422 BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch); |
| 420 BumpNextVersionIdIfNeeded(registration.version_id, &batch); | 423 BumpNextVersionIdIfNeeded(registration.version_id, &batch); |
| 421 | 424 |
| 422 // TODO(nhiroki): Skip to add the origin into the unique origin list if it | 425 // TODO(nhiroki): Skip to add the origin into the unique origin list if it |
| 423 // has already been added. | 426 // has already been added. |
| 424 PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch); | 427 PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch); |
| 425 | 428 |
| 426 PutRegistrationDataToBatch(registration, &batch); | 429 PutRegistrationDataToBatch(registration, &batch); |
| 427 | 430 |
| 428 // Retrieve a previous version to sweep purgeable resources. | 431 // Retrieve a previous version to sweep purgeable resources. |
| 429 RegistrationData old_registration; | 432 RegistrationData old_registration; |
| 430 if (!ReadRegistrationData(registration.registration_id, | 433 status = ReadRegistrationData(registration.registration_id, |
| 431 registration.scope.GetOrigin(), | 434 registration.scope.GetOrigin(), |
| 432 &old_registration)) { | 435 &old_registration); |
| 433 if (is_disabled_) | 436 if (status != STATUS_OK && status != STATUS_ERROR_NOT_FOUND) |
| 434 return false; | 437 return status; |
| 435 // Just not found. | 438 if (status == STATUS_OK) { |
| 436 } else { | |
| 437 DCHECK_LT(old_registration.version_id, registration.version_id); | 439 DCHECK_LT(old_registration.version_id, registration.version_id); |
| 438 // Currently resource sharing across versions and registrations is not | 440 // Currently resource sharing across versions and registrations is not |
| 439 // suppported, so resource ids should not be overlapped between | 441 // suppported, so resource ids should not be overlapped between |
| 440 // |registration| and |old_registration|. | 442 // |registration| and |old_registration|. |
| 441 // TODO(nhiroki): Add DCHECK to make sure the overlap does not exist. | 443 // TODO(nhiroki): Add DCHECK to make sure the overlap does not exist. |
| 442 if (!DeleteResourceRecords(old_registration.version_id, &batch)) | 444 status = DeleteResourceRecords(old_registration.version_id, &batch); |
| 443 return false; | 445 if (status != STATUS_OK) |
| 446 return status; |
| 444 } | 447 } |
| 445 | 448 |
| 446 // Used for avoiding multiple writes for the same resource id or url. | 449 // Used for avoiding multiple writes for the same resource id or url. |
| 447 std::set<int64> pushed_resources; | 450 std::set<int64> pushed_resources; |
| 448 std::set<GURL> pushed_urls; | 451 std::set<GURL> pushed_urls; |
| 449 for (std::vector<ResourceRecord>::const_iterator itr = resources.begin(); | 452 for (std::vector<ResourceRecord>::const_iterator itr = resources.begin(); |
| 450 itr != resources.end(); ++itr) { | 453 itr != resources.end(); ++itr) { |
| 451 if (!itr->url.is_valid()) | 454 if (!itr->url.is_valid()) |
| 452 return false; | 455 return STATUS_ERROR_FAILED; |
| 453 | 456 |
| 454 // Duplicated resource id or url should not exist. | 457 // Duplicated resource id or url should not exist. |
| 455 DCHECK(pushed_resources.insert(itr->resource_id).second); | 458 DCHECK(pushed_resources.insert(itr->resource_id).second); |
| 456 DCHECK(pushed_urls.insert(itr->url).second); | 459 DCHECK(pushed_urls.insert(itr->url).second); |
| 457 | 460 |
| 458 PutResourceRecordToBatch(*itr, registration.version_id, &batch); | 461 PutResourceRecordToBatch(*itr, registration.version_id, &batch); |
| 459 | 462 |
| 460 // Delete a resource from the uncommitted list. | 463 // Delete a resource from the uncommitted list. |
| 461 batch.Delete(CreateResourceIdKey( | 464 batch.Delete(CreateResourceIdKey( |
| 462 kUncommittedResIdKeyPrefix, itr->resource_id)); | 465 kUncommittedResIdKeyPrefix, itr->resource_id)); |
| 463 } | 466 } |
| 464 | 467 |
| 465 return WriteBatch(&batch); | 468 return WriteBatch(&batch); |
| 466 } | 469 } |
| 467 | 470 |
| 468 bool ServiceWorkerDatabase::UpdateVersionToActive(int64 registration_id, | 471 ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateVersionToActive( |
| 469 const GURL& origin) { | 472 int64 registration_id, |
| 473 const GURL& origin) { |
| 470 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 474 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 471 ServiceWorkerDatabase::Status status = LazyOpen(false); | 475 ServiceWorkerDatabase::Status status = LazyOpen(false); |
| 472 if (IsNewOrNonexistentDatabase(status) || status != STATUS_OK) | 476 if (IsNewOrNonexistentDatabase(status)) |
| 473 return false; | 477 return STATUS_ERROR_NOT_FOUND; |
| 478 if (status != STATUS_OK) |
| 479 return status; |
| 480 if (!origin.is_valid()) |
| 481 return STATUS_ERROR_FAILED; |
| 474 | 482 |
| 475 RegistrationData registration; | 483 RegistrationData registration; |
| 476 if (!ReadRegistrationData(registration_id, origin, ®istration)) | 484 status = ReadRegistrationData(registration_id, origin, ®istration); |
| 477 return false; | 485 if (status != STATUS_OK) |
| 486 return status; |
| 478 | 487 |
| 479 registration.is_active = true; | 488 registration.is_active = true; |
| 480 | 489 |
| 481 leveldb::WriteBatch batch; | 490 leveldb::WriteBatch batch; |
| 482 PutRegistrationDataToBatch(registration, &batch); | 491 PutRegistrationDataToBatch(registration, &batch); |
| 483 return WriteBatch(&batch); | 492 return WriteBatch(&batch); |
| 484 } | 493 } |
| 485 | 494 |
| 486 bool ServiceWorkerDatabase::UpdateLastCheckTime(int64 registration_id, | 495 ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateLastCheckTime( |
| 487 const GURL& origin, | 496 int64 registration_id, |
| 488 const base::Time& time) { | 497 const GURL& origin, |
| 498 const base::Time& time) { |
| 489 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 499 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 490 ServiceWorkerDatabase::Status status = LazyOpen(false); | 500 ServiceWorkerDatabase::Status status = LazyOpen(false); |
| 491 if (IsNewOrNonexistentDatabase(status) || status != STATUS_OK) | 501 if (IsNewOrNonexistentDatabase(status)) |
| 492 return false; | 502 return STATUS_ERROR_NOT_FOUND; |
| 503 if (status != STATUS_OK) |
| 504 return status; |
| 505 if (!origin.is_valid()) |
| 506 return STATUS_ERROR_FAILED; |
| 493 | 507 |
| 494 RegistrationData registration; | 508 RegistrationData registration; |
| 495 if (!ReadRegistrationData(registration_id, origin, ®istration)) | 509 status = ReadRegistrationData(registration_id, origin, ®istration); |
| 496 return false; | 510 if (status != STATUS_OK) |
| 511 return status; |
| 497 | 512 |
| 498 registration.last_update_check = time; | 513 registration.last_update_check = time; |
| 499 | 514 |
| 500 leveldb::WriteBatch batch; | 515 leveldb::WriteBatch batch; |
| 501 PutRegistrationDataToBatch(registration, &batch); | 516 PutRegistrationDataToBatch(registration, &batch); |
| 502 return WriteBatch(&batch); | 517 return WriteBatch(&batch); |
| 503 } | 518 } |
| 504 | 519 |
| 505 bool ServiceWorkerDatabase::DeleteRegistration(int64 registration_id, | 520 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteRegistration( |
| 506 const GURL& origin) { | 521 int64 registration_id, |
| 522 const GURL& origin) { |
| 507 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 523 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 508 Status status = LazyOpen(false); | 524 Status status = LazyOpen(false); |
| 509 if (IsNewOrNonexistentDatabase(status)) | 525 if (IsNewOrNonexistentDatabase(status)) |
| 510 return STATUS_OK; | 526 return STATUS_OK; |
| 511 if (status != STATUS_OK || !origin.is_valid()) | 527 if (status != STATUS_OK) |
| 512 return false; | 528 return status; |
| 529 if (!origin.is_valid()) |
| 530 return STATUS_ERROR_FAILED; |
| 513 | 531 |
| 514 leveldb::WriteBatch batch; | 532 leveldb::WriteBatch batch; |
| 515 | 533 |
| 516 // Remove |origin| from unique origins if a registration specified by | 534 // Remove |origin| from unique origins if a registration specified by |
| 517 // |registration_id| is the only one for |origin|. | 535 // |registration_id| is the only one for |origin|. |
| 518 // TODO(nhiroki): Check the uniqueness by more efficient way. | 536 // TODO(nhiroki): Check the uniqueness by more efficient way. |
| 519 std::vector<RegistrationData> registrations; | 537 std::vector<RegistrationData> registrations; |
| 520 if (GetRegistrationsForOrigin(origin, ®istrations) != STATUS_OK) | 538 status = GetRegistrationsForOrigin(origin, ®istrations); |
| 521 return false; | 539 if (status != STATUS_OK) |
| 540 return status; |
| 541 |
| 522 if (registrations.size() == 1 && | 542 if (registrations.size() == 1 && |
| 523 registrations[0].registration_id == registration_id) { | 543 registrations[0].registration_id == registration_id) { |
| 524 batch.Delete(CreateUniqueOriginKey(origin)); | 544 batch.Delete(CreateUniqueOriginKey(origin)); |
| 525 } | 545 } |
| 526 | 546 |
| 527 // Delete a registration specified by |registration_id|. | 547 // Delete a registration specified by |registration_id|. |
| 528 batch.Delete(CreateRegistrationKey(registration_id, origin)); | 548 batch.Delete(CreateRegistrationKey(registration_id, origin)); |
| 529 | 549 |
| 530 // Delete resource records associated with the registration. | 550 // Delete resource records associated with the registration. |
| 531 for (std::vector<RegistrationData>::const_iterator itr = | 551 for (std::vector<RegistrationData>::const_iterator itr = |
| 532 registrations.begin(); itr != registrations.end(); ++itr) { | 552 registrations.begin(); itr != registrations.end(); ++itr) { |
| 533 if (itr->registration_id == registration_id) { | 553 if (itr->registration_id == registration_id) { |
| 534 if (!DeleteResourceRecords(itr->version_id, &batch)) | 554 status = DeleteResourceRecords(itr->version_id, &batch); |
| 535 return false; | 555 if (status != STATUS_OK) |
| 556 return status; |
| 536 break; | 557 break; |
| 537 } | 558 } |
| 538 } | 559 } |
| 539 | 560 |
| 540 return WriteBatch(&batch); | 561 return WriteBatch(&batch); |
| 541 } | 562 } |
| 542 | 563 |
| 543 bool ServiceWorkerDatabase::GetUncommittedResourceIds(std::set<int64>* ids) { | 564 ServiceWorkerDatabase::Status |
| 565 ServiceWorkerDatabase::GetUncommittedResourceIds(std::set<int64>* ids) { |
| 544 return ReadResourceIds(kUncommittedResIdKeyPrefix, ids); | 566 return ReadResourceIds(kUncommittedResIdKeyPrefix, ids); |
| 545 } | 567 } |
| 546 | 568 |
| 547 bool ServiceWorkerDatabase::WriteUncommittedResourceIds( | 569 ServiceWorkerDatabase::Status |
| 548 const std::set<int64>& ids) { | 570 ServiceWorkerDatabase::WriteUncommittedResourceIds(const std::set<int64>& ids) { |
| 549 return WriteResourceIds(kUncommittedResIdKeyPrefix, ids); | 571 return WriteResourceIds(kUncommittedResIdKeyPrefix, ids); |
| 550 } | 572 } |
| 551 | 573 |
| 552 bool ServiceWorkerDatabase::ClearUncommittedResourceIds( | 574 ServiceWorkerDatabase::Status |
| 553 const std::set<int64>& ids) { | 575 ServiceWorkerDatabase::ClearUncommittedResourceIds(const std::set<int64>& ids) { |
| 554 return DeleteResourceIds(kUncommittedResIdKeyPrefix, ids); | 576 return DeleteResourceIds(kUncommittedResIdKeyPrefix, ids); |
| 555 } | 577 } |
| 556 | 578 |
| 557 bool ServiceWorkerDatabase::GetPurgeableResourceIds(std::set<int64>* ids) { | 579 ServiceWorkerDatabase::Status |
| 580 ServiceWorkerDatabase::GetPurgeableResourceIds(std::set<int64>* ids) { |
| 558 return ReadResourceIds(kPurgeableResIdKeyPrefix, ids); | 581 return ReadResourceIds(kPurgeableResIdKeyPrefix, ids); |
| 559 } | 582 } |
| 560 | 583 |
| 561 bool ServiceWorkerDatabase::WritePurgeableResourceIds( | 584 ServiceWorkerDatabase::Status |
| 562 const std::set<int64>& ids) { | 585 ServiceWorkerDatabase::WritePurgeableResourceIds(const std::set<int64>& ids) { |
| 563 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids); | 586 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids); |
| 564 } | 587 } |
| 565 | 588 |
| 566 bool ServiceWorkerDatabase::ClearPurgeableResourceIds( | 589 ServiceWorkerDatabase::Status |
| 567 const std::set<int64>& ids) { | 590 ServiceWorkerDatabase::ClearPurgeableResourceIds(const std::set<int64>& ids) { |
| 568 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids); | 591 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids); |
| 569 } | 592 } |
| 570 | 593 |
| 571 bool ServiceWorkerDatabase::DeleteAllDataForOrigin(const GURL& origin) { | 594 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigin( |
| 595 const GURL& origin) { |
| 572 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 596 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 573 Status status = LazyOpen(false); | 597 Status status = LazyOpen(false); |
| 574 if (IsNewOrNonexistentDatabase(status)) | 598 if (IsNewOrNonexistentDatabase(status)) |
| 575 return STATUS_OK; | 599 return STATUS_OK; |
| 576 if (status != STATUS_OK || !origin.is_valid()) | 600 if (status != STATUS_OK) |
| 577 return false; | 601 return status; |
| 602 if (!origin.is_valid()) |
| 603 return STATUS_ERROR_FAILED; |
| 578 | 604 |
| 579 leveldb::WriteBatch batch; | 605 leveldb::WriteBatch batch; |
| 580 | 606 |
| 581 // Delete from the unique origin list. | 607 // Delete from the unique origin list. |
| 582 batch.Delete(CreateUniqueOriginKey(origin)); | 608 batch.Delete(CreateUniqueOriginKey(origin)); |
| 583 | 609 |
| 584 std::vector<RegistrationData> registrations; | 610 std::vector<RegistrationData> registrations; |
| 585 if (GetRegistrationsForOrigin(origin, ®istrations) != STATUS_OK) | 611 status = GetRegistrationsForOrigin(origin, ®istrations); |
| 586 return false; | 612 if (status != STATUS_OK) |
| 613 return status; |
| 587 | 614 |
| 588 // Delete registrations and resource records. | 615 // Delete registrations and resource records. |
| 589 for (std::vector<RegistrationData>::const_iterator itr = | 616 for (std::vector<RegistrationData>::const_iterator itr = |
| 590 registrations.begin(); itr != registrations.end(); ++itr) { | 617 registrations.begin(); itr != registrations.end(); ++itr) { |
| 591 batch.Delete(CreateRegistrationKey(itr->registration_id, origin)); | 618 batch.Delete(CreateRegistrationKey(itr->registration_id, origin)); |
| 592 if (!DeleteResourceRecords(itr->version_id, &batch)) | 619 status = DeleteResourceRecords(itr->version_id, &batch); |
| 593 return false; | 620 if (status != STATUS_OK) |
| 621 return status; |
| 594 } | 622 } |
| 595 | 623 |
| 596 return WriteBatch(&batch); | 624 return WriteBatch(&batch); |
| 597 } | 625 } |
| 598 | 626 |
| 599 ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen( | 627 ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen( |
| 600 bool create_if_missing) { | 628 bool create_if_missing) { |
| 601 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 629 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 602 | 630 |
| 603 // Do not try to open a database if we tried and failed once. | 631 // Do not try to open a database if we tried and failed once. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 int64 parsed; | 705 int64 parsed; |
| 678 if (!base::StringToInt64(value, &parsed)) { | 706 if (!base::StringToInt64(value, &parsed)) { |
| 679 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 707 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
| 680 return STATUS_ERROR_CORRUPTED; | 708 return STATUS_ERROR_CORRUPTED; |
| 681 } | 709 } |
| 682 | 710 |
| 683 *next_avail_id = parsed; | 711 *next_avail_id = parsed; |
| 684 return STATUS_OK; | 712 return STATUS_OK; |
| 685 } | 713 } |
| 686 | 714 |
| 687 bool ServiceWorkerDatabase::ReadRegistrationData( | 715 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationData( |
| 688 int64 registration_id, | 716 int64 registration_id, |
| 689 const GURL& origin, | 717 const GURL& origin, |
| 690 RegistrationData* registration) { | 718 RegistrationData* registration) { |
| 691 DCHECK(registration); | 719 DCHECK(registration); |
| 692 | 720 |
| 693 std::string key = CreateRegistrationKey(registration_id, origin); | 721 std::string key = CreateRegistrationKey(registration_id, origin); |
| 694 | 722 |
| 695 std::string value; | 723 std::string value; |
| 696 leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value); | 724 leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value); |
| 697 if (!status.ok()) { | 725 if (!status.ok()) { |
| 698 if (!status.IsNotFound()) | 726 if (!status.IsNotFound()) |
| 699 HandleError(FROM_HERE, status); | 727 HandleError(FROM_HERE, status); |
| 700 return false; | 728 return LevelDBStatusToStatus(status); |
| 701 } | 729 } |
| 702 | 730 |
| 703 RegistrationData parsed; | 731 RegistrationData parsed; |
| 704 if (!ParseRegistrationData(value, &parsed)) { | 732 if (!ParseRegistrationData(value, &parsed)) { |
| 705 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 733 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
| 706 return false; | 734 return STATUS_ERROR_CORRUPTED; |
| 707 } | 735 } |
| 708 | 736 |
| 709 *registration = parsed; | 737 *registration = parsed; |
| 710 return true; | 738 return STATUS_OK; |
| 711 } | 739 } |
| 712 | 740 |
| 713 bool ServiceWorkerDatabase::ReadResourceRecords( | 741 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceRecords( |
| 714 int64 version_id, | 742 int64 version_id, |
| 715 std::vector<ResourceRecord>* resources) { | 743 std::vector<ResourceRecord>* resources) { |
| 716 DCHECK(resources); | 744 DCHECK(resources); |
| 717 | 745 |
| 718 std::string prefix = CreateResourceRecordKeyPrefix(version_id); | 746 std::string prefix = CreateResourceRecordKeyPrefix(version_id); |
| 719 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); | 747 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
| 720 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { | 748 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { |
| 721 if (!itr->status().ok()) { | 749 if (!itr->status().ok()) { |
| 722 HandleError(FROM_HERE, itr->status()); | 750 HandleError(FROM_HERE, itr->status()); |
| 723 resources->clear(); | 751 resources->clear(); |
| 724 return false; | 752 return LevelDBStatusToStatus(itr->status()); |
| 725 } | 753 } |
| 726 | 754 |
| 727 if (!RemovePrefix(itr->key().ToString(), prefix, NULL)) | 755 if (!RemovePrefix(itr->key().ToString(), prefix, NULL)) |
| 728 break; | 756 break; |
| 729 | 757 |
| 730 ResourceRecord resource; | 758 ResourceRecord resource; |
| 731 if (!ParseResourceRecord(itr->value().ToString(), &resource)) { | 759 if (!ParseResourceRecord(itr->value().ToString(), &resource)) { |
| 732 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 760 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
| 733 resources->clear(); | 761 resources->clear(); |
| 734 return false; | 762 return STATUS_ERROR_CORRUPTED; |
| 735 } | 763 } |
| 736 resources->push_back(resource); | 764 resources->push_back(resource); |
| 737 } | 765 } |
| 738 return true; | 766 return STATUS_OK; |
| 739 } | 767 } |
| 740 | 768 |
| 741 bool ServiceWorkerDatabase::DeleteResourceRecords( | 769 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceRecords( |
| 742 int64 version_id, | 770 int64 version_id, |
| 743 leveldb::WriteBatch* batch) { | 771 leveldb::WriteBatch* batch) { |
| 744 DCHECK(batch); | 772 DCHECK(batch); |
| 745 | 773 |
| 746 std::string prefix = CreateResourceRecordKeyPrefix(version_id); | 774 std::string prefix = CreateResourceRecordKeyPrefix(version_id); |
| 747 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); | 775 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
| 748 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { | 776 for (itr->Seek(prefix); itr->Valid(); itr->Next()) { |
| 749 if (!itr->status().ok()) { | 777 if (!itr->status().ok()) { |
| 750 HandleError(FROM_HERE, itr->status()); | 778 HandleError(FROM_HERE, itr->status()); |
| 751 return false; | 779 return LevelDBStatusToStatus(itr->status()); |
| 752 } | 780 } |
| 753 | 781 |
| 754 std::string key = itr->key().ToString(); | 782 std::string key = itr->key().ToString(); |
| 755 std::string unprefixed; | 783 std::string unprefixed; |
| 756 if (!RemovePrefix(key, prefix, &unprefixed)) | 784 if (!RemovePrefix(key, prefix, &unprefixed)) |
| 757 break; | 785 break; |
| 758 | 786 |
| 759 int64 resource_id; | 787 int64 resource_id; |
| 760 if (!base::StringToInt64(unprefixed, &resource_id)) { | 788 if (!base::StringToInt64(unprefixed, &resource_id)) { |
| 761 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 789 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
| 762 return false; | 790 return STATUS_ERROR_CORRUPTED; |
| 763 } | 791 } |
| 764 | 792 |
| 765 // Remove a resource record. | 793 // Remove a resource record. |
| 766 batch->Delete(key); | 794 batch->Delete(key); |
| 767 | 795 |
| 768 // Currently resource sharing across versions and registrations is not | 796 // Currently resource sharing across versions and registrations is not |
| 769 // supported, so we can purge this without caring about it. | 797 // supported, so we can purge this without caring about it. |
| 770 PutPurgeableResourceIdToBatch(resource_id, batch); | 798 PutPurgeableResourceIdToBatch(resource_id, batch); |
| 771 } | 799 } |
| 772 return true; | 800 return STATUS_OK; |
| 773 } | 801 } |
| 774 | 802 |
| 775 bool ServiceWorkerDatabase::ReadResourceIds(const char* id_key_prefix, | 803 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceIds( |
| 776 std::set<int64>* ids) { | 804 const char* id_key_prefix, |
| 805 std::set<int64>* ids) { |
| 777 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 806 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 778 DCHECK(id_key_prefix); | 807 DCHECK(id_key_prefix); |
| 779 DCHECK(ids->empty()); | 808 DCHECK(ids->empty()); |
| 780 | 809 |
| 781 Status status = LazyOpen(false); | 810 Status status = LazyOpen(false); |
| 782 if (IsNewOrNonexistentDatabase(status)) | 811 if (IsNewOrNonexistentDatabase(status)) |
| 783 return true; | 812 return STATUS_OK; |
| 784 if (status != STATUS_OK) | 813 if (status != STATUS_OK) |
| 785 return false; | 814 return status; |
| 786 | 815 |
| 787 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); | 816 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
| 788 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) { | 817 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) { |
| 789 if (!itr->status().ok()) { | 818 if (!itr->status().ok()) { |
| 790 HandleError(FROM_HERE, itr->status()); | 819 HandleError(FROM_HERE, itr->status()); |
| 791 ids->clear(); | 820 ids->clear(); |
| 792 return false; | 821 return LevelDBStatusToStatus(itr->status()); |
| 793 } | 822 } |
| 794 | 823 |
| 795 std::string unprefixed; | 824 std::string unprefixed; |
| 796 if (!RemovePrefix(itr->key().ToString(), id_key_prefix, &unprefixed)) | 825 if (!RemovePrefix(itr->key().ToString(), id_key_prefix, &unprefixed)) |
| 797 break; | 826 break; |
| 798 | 827 |
| 799 int64 resource_id; | 828 int64 resource_id; |
| 800 if (!base::StringToInt64(unprefixed, &resource_id)) { | 829 if (!base::StringToInt64(unprefixed, &resource_id)) { |
| 801 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 830 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
| 802 ids->clear(); | 831 ids->clear(); |
| 803 return false; | 832 return STATUS_ERROR_CORRUPTED; |
| 804 } | 833 } |
| 805 ids->insert(resource_id); | 834 ids->insert(resource_id); |
| 806 } | 835 } |
| 807 return true; | 836 return STATUS_OK; |
| 808 } | 837 } |
| 809 | 838 |
| 810 bool ServiceWorkerDatabase::WriteResourceIds(const char* id_key_prefix, | 839 ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteResourceIds( |
| 811 const std::set<int64>& ids) { | 840 const char* id_key_prefix, |
| 841 const std::set<int64>& ids) { |
| 812 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 842 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 813 DCHECK(id_key_prefix); | 843 DCHECK(id_key_prefix); |
| 814 | 844 |
| 815 if (LazyOpen(true) != STATUS_OK) | 845 Status status = LazyOpen(true); |
| 816 return false; | 846 if (status != STATUS_OK) |
| 847 return status; |
| 817 if (ids.empty()) | 848 if (ids.empty()) |
| 818 return true; | 849 return STATUS_OK; |
| 819 | 850 |
| 820 leveldb::WriteBatch batch; | 851 leveldb::WriteBatch batch; |
| 821 for (std::set<int64>::const_iterator itr = ids.begin(); | 852 for (std::set<int64>::const_iterator itr = ids.begin(); |
| 822 itr != ids.end(); ++itr) { | 853 itr != ids.end(); ++itr) { |
| 823 // Value should be empty. | 854 // Value should be empty. |
| 824 batch.Put(CreateResourceIdKey(id_key_prefix, *itr), ""); | 855 batch.Put(CreateResourceIdKey(id_key_prefix, *itr), ""); |
| 825 } | 856 } |
| 857 |
| 826 return WriteBatch(&batch); | 858 return WriteBatch(&batch); |
| 827 } | 859 } |
| 828 | 860 |
| 829 bool ServiceWorkerDatabase::DeleteResourceIds(const char* id_key_prefix, | 861 ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceIds( |
| 830 const std::set<int64>& ids) { | 862 const char* id_key_prefix, |
| 863 const std::set<int64>& ids) { |
| 831 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 864 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 832 DCHECK(id_key_prefix); | 865 DCHECK(id_key_prefix); |
| 833 | 866 |
| 834 Status status = LazyOpen(false); | 867 Status status = LazyOpen(false); |
| 835 if (IsNewOrNonexistentDatabase(status)) | 868 if (IsNewOrNonexistentDatabase(status)) |
| 836 return true; | 869 return STATUS_OK; |
| 837 if (status != STATUS_OK) | 870 if (status != STATUS_OK) |
| 838 return false; | 871 return status; |
| 839 | |
| 840 if (ids.empty()) | 872 if (ids.empty()) |
| 841 return true; | 873 return STATUS_OK; |
| 842 | 874 |
| 843 leveldb::WriteBatch batch; | 875 leveldb::WriteBatch batch; |
| 844 for (std::set<int64>::const_iterator itr = ids.begin(); | 876 for (std::set<int64>::const_iterator itr = ids.begin(); |
| 845 itr != ids.end(); ++itr) { | 877 itr != ids.end(); ++itr) { |
| 846 batch.Delete(CreateResourceIdKey(id_key_prefix, *itr)); | 878 batch.Delete(CreateResourceIdKey(id_key_prefix, *itr)); |
| 847 } | 879 } |
| 880 |
| 848 return WriteBatch(&batch); | 881 return WriteBatch(&batch); |
| 849 } | 882 } |
| 850 | 883 |
| 851 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadDatabaseVersion( | 884 ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadDatabaseVersion( |
| 852 int64* db_version) { | 885 int64* db_version) { |
| 853 std::string value; | 886 std::string value; |
| 854 leveldb::Status status = | 887 leveldb::Status status = |
| 855 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value); | 888 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value); |
| 856 if (status.IsNotFound()) { | 889 if (status.IsNotFound()) { |
| 857 // The database hasn't been initialized yet. | 890 // The database hasn't been initialized yet. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 872 const int kFirstValidVersion = 1; | 905 const int kFirstValidVersion = 1; |
| 873 if (parsed < kFirstValidVersion || kCurrentSchemaVersion < parsed) { | 906 if (parsed < kFirstValidVersion || kCurrentSchemaVersion < parsed) { |
| 874 HandleError(FROM_HERE, leveldb::Status::Corruption("invalid DB version")); | 907 HandleError(FROM_HERE, leveldb::Status::Corruption("invalid DB version")); |
| 875 return STATUS_ERROR_CORRUPTED; | 908 return STATUS_ERROR_CORRUPTED; |
| 876 } | 909 } |
| 877 | 910 |
| 878 *db_version = parsed; | 911 *db_version = parsed; |
| 879 return STATUS_OK; | 912 return STATUS_OK; |
| 880 } | 913 } |
| 881 | 914 |
| 882 bool ServiceWorkerDatabase::WriteBatch(leveldb::WriteBatch* batch) { | 915 ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteBatch( |
| 916 leveldb::WriteBatch* batch) { |
| 883 DCHECK(batch); | 917 DCHECK(batch); |
| 884 DCHECK(!is_disabled_); | 918 DCHECK(!is_disabled_); |
| 885 | 919 |
| 886 if (!is_initialized_) { | 920 if (!is_initialized_) { |
| 887 // Write the database schema version. | 921 // Write the database schema version. |
| 888 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion)); | 922 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion)); |
| 889 is_initialized_ = true; | 923 is_initialized_ = true; |
| 890 } | 924 } |
| 891 | 925 |
| 892 leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch); | 926 leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch); |
| 893 if (!status.ok()) { | 927 if (!status.ok()) |
| 894 HandleError(FROM_HERE, status); | 928 HandleError(FROM_HERE, status); |
| 895 return false; | 929 return LevelDBStatusToStatus(status); |
| 896 } | |
| 897 return true; | |
| 898 } | 930 } |
| 899 | 931 |
| 900 void ServiceWorkerDatabase::BumpNextRegistrationIdIfNeeded( | 932 void ServiceWorkerDatabase::BumpNextRegistrationIdIfNeeded( |
| 901 int64 used_id, leveldb::WriteBatch* batch) { | 933 int64 used_id, leveldb::WriteBatch* batch) { |
| 902 DCHECK(batch); | 934 DCHECK(batch); |
| 903 if (next_avail_registration_id_ <= used_id) { | 935 if (next_avail_registration_id_ <= used_id) { |
| 904 next_avail_registration_id_ = used_id + 1; | 936 next_avail_registration_id_ = used_id + 1; |
| 905 batch->Put(kNextRegIdKey, base::Int64ToString(next_avail_registration_id_)); | 937 batch->Put(kNextRegIdKey, base::Int64ToString(next_avail_registration_id_)); |
| 906 } | 938 } |
| 907 } | 939 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 925 // TODO(nhiroki): Add an UMA histogram. | 957 // TODO(nhiroki): Add an UMA histogram. |
| 926 DLOG(ERROR) << "Failed at: " << from_here.ToString() | 958 DLOG(ERROR) << "Failed at: " << from_here.ToString() |
| 927 << " with error: " << status.ToString(); | 959 << " with error: " << status.ToString(); |
| 928 is_disabled_ = true; | 960 is_disabled_ = true; |
| 929 if (status.IsCorruption()) | 961 if (status.IsCorruption()) |
| 930 was_corruption_detected_ = true; | 962 was_corruption_detected_ = true; |
| 931 db_.reset(); | 963 db_.reset(); |
| 932 } | 964 } |
| 933 | 965 |
| 934 } // namespace content | 966 } // namespace content |
| OLD | NEW |