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