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_cache.h" | 5 #include "content/browser/service_worker/service_worker_cache.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/guid.h" | 10 #include "base/guid.h" |
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
421 ServiceWorkerCache::~ServiceWorkerCache() { | 421 ServiceWorkerCache::~ServiceWorkerCache() { |
422 } | 422 } |
423 | 423 |
424 base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() { | 424 base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() { |
425 return weak_ptr_factory_.GetWeakPtr(); | 425 return weak_ptr_factory_.GetWeakPtr(); |
426 } | 426 } |
427 | 427 |
428 void ServiceWorkerCache::Put(scoped_ptr<ServiceWorkerFetchRequest> request, | 428 void ServiceWorkerCache::Put(scoped_ptr<ServiceWorkerFetchRequest> request, |
429 scoped_ptr<ServiceWorkerResponse> response, | 429 scoped_ptr<ServiceWorkerResponse> response, |
430 const ResponseCallback& callback) { | 430 const ResponseCallback& callback) { |
431 IncPendingOps(); | |
432 ResponseCallback pending_callback = | |
433 base::Bind(&ServiceWorkerCache::PendingResponseCallback, | |
434 weak_ptr_factory_.GetWeakPtr(), callback); | |
435 scoped_ptr<storage::BlobDataHandle> blob_data_handle; | 431 scoped_ptr<storage::BlobDataHandle> blob_data_handle; |
436 | 432 |
437 if (!response->blob_uuid.empty()) { | 433 if (!response->blob_uuid.empty()) { |
438 if (!blob_storage_context_) { | 434 if (!blob_storage_context_) { |
439 pending_callback.Run(ErrorTypeStorage, | 435 callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), |
440 scoped_ptr<ServiceWorkerResponse>(), | 436 scoped_ptr<storage::BlobDataHandle>()); |
441 scoped_ptr<storage::BlobDataHandle>()); | |
442 return; | 437 return; |
443 } | 438 } |
444 blob_data_handle = | 439 blob_data_handle = |
445 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid); | 440 blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid); |
446 if (!blob_data_handle) { | 441 if (!blob_data_handle) { |
447 pending_callback.Run(ErrorTypeStorage, | 442 callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), |
448 scoped_ptr<ServiceWorkerResponse>(), | 443 scoped_ptr<storage::BlobDataHandle>()); |
449 scoped_ptr<storage::BlobDataHandle>()); | |
450 return; | 444 return; |
451 } | 445 } |
452 } | 446 } |
453 | 447 |
448 ResponseCallback pending_callback = | |
449 base::Bind(&ServiceWorkerCache::PendingResponseCallback, | |
450 weak_ptr_factory_.GetWeakPtr(), callback); | |
451 | |
454 scoped_ptr<PutContext> put_context(new PutContext( | 452 scoped_ptr<PutContext> put_context(new PutContext( |
455 origin_, request.Pass(), response.Pass(), blob_data_handle.Pass(), | 453 origin_, request.Pass(), response.Pass(), blob_data_handle.Pass(), |
456 pending_callback, request_context_, quota_manager_proxy_)); | 454 pending_callback, request_context_, quota_manager_proxy_)); |
457 | 455 |
458 if (put_context->blob_data_handle) { | 456 if (put_context->blob_data_handle) { |
459 // Grab another handle to the blob for the callback response. | 457 // Grab another handle to the blob for the callback response. |
460 put_context->out_blob_data_handle = | 458 put_context->out_blob_data_handle = |
461 blob_storage_context_->GetBlobDataFromUUID( | 459 blob_storage_context_->GetBlobDataFromUUID( |
462 put_context->response->blob_uuid); | 460 put_context->response->blob_uuid); |
463 } | 461 } |
464 | 462 |
465 base::Closure continuation = | 463 pending_operations_.push_back(base::Bind(&ServiceWorkerCache::PutImpl, |
466 base::Bind(&ServiceWorkerCache::PutImpl, weak_ptr_factory_.GetWeakPtr(), | 464 weak_ptr_factory_.GetWeakPtr(), |
467 base::Passed(put_context.Pass())); | 465 base::Passed(put_context.Pass()))); |
468 | 466 |
469 if (backend_state_ == BACKEND_UNINITIALIZED) { | 467 if (backend_state_ == BACKEND_UNINITIALIZED) { |
470 InitBackend(continuation); | 468 InitBackend(pending_operations_.back()); |
471 return; | 469 return; |
472 } | 470 } |
473 | 471 |
474 continuation.Run(); | 472 RunOperationIfIdle(); |
475 } | 473 } |
476 | 474 |
477 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, | 475 void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, |
478 const ResponseCallback& callback) { | 476 const ResponseCallback& callback) { |
479 IncPendingOps(); | |
480 ResponseCallback pending_callback = | 477 ResponseCallback pending_callback = |
481 base::Bind(&ServiceWorkerCache::PendingResponseCallback, | 478 base::Bind(&ServiceWorkerCache::PendingResponseCallback, |
482 weak_ptr_factory_.GetWeakPtr(), callback); | 479 weak_ptr_factory_.GetWeakPtr(), callback); |
480 pending_operations_.push_back( | |
481 base::Bind(&ServiceWorkerCache::MatchImpl, weak_ptr_factory_.GetWeakPtr(), | |
482 base::Passed(request.Pass()), pending_callback)); | |
483 | 483 |
484 switch (backend_state_) { | 484 switch (backend_state_) { |
485 case BACKEND_UNINITIALIZED: | 485 case BACKEND_UNINITIALIZED: |
486 InitBackend(base::Bind(&ServiceWorkerCache::Match, | 486 InitBackend(pending_operations_.back()); |
487 weak_ptr_factory_.GetWeakPtr(), | |
488 base::Passed(request.Pass()), pending_callback)); | |
489 return; | 487 return; |
490 case BACKEND_CLOSED: | 488 case BACKEND_CLOSED: |
491 pending_callback.Run(ErrorTypeStorage, | 489 pending_callback.Run(ErrorTypeStorage, |
492 scoped_ptr<ServiceWorkerResponse>(), | 490 scoped_ptr<ServiceWorkerResponse>(), |
493 scoped_ptr<storage::BlobDataHandle>()); | 491 scoped_ptr<storage::BlobDataHandle>()); |
494 return; | 492 return; |
495 case BACKEND_OPEN: | 493 case BACKEND_OPEN: |
496 DCHECK(backend_); | 494 DCHECK(backend_); |
497 break; | 495 RunOperationIfIdle(); |
496 return; | |
498 } | 497 } |
499 | 498 NOTREACHED(); |
500 scoped_ptr<MatchContext> match_context(new MatchContext( | |
501 request.Pass(), pending_callback, blob_storage_context_)); | |
502 | |
503 disk_cache::Entry** entry_ptr = &match_context->entry; | |
504 ServiceWorkerFetchRequest* request_ptr = match_context->request.get(); | |
505 | |
506 net::CompletionCallback open_entry_callback = base::Bind( | |
507 &ServiceWorkerCache::MatchDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), | |
508 base::Passed(match_context.Pass())); | |
509 | |
510 int rv = backend_->OpenEntry( | |
511 request_ptr->url.spec(), entry_ptr, open_entry_callback); | |
512 if (rv != net::ERR_IO_PENDING) | |
513 open_entry_callback.Run(rv); | |
514 } | 499 } |
515 | 500 |
516 void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request, | 501 void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request, |
517 const ErrorCallback& callback) { | 502 const ErrorCallback& callback) { |
518 IncPendingOps(); | |
519 ErrorCallback pending_callback = | 503 ErrorCallback pending_callback = |
520 base::Bind(&ServiceWorkerCache::PendingErrorCallback, | 504 base::Bind(&ServiceWorkerCache::PendingErrorCallback, |
521 weak_ptr_factory_.GetWeakPtr(), callback); | 505 weak_ptr_factory_.GetWeakPtr(), callback); |
506 pending_operations_.push_back(base::Bind( | |
507 &ServiceWorkerCache::DeleteImpl, weak_ptr_factory_.GetWeakPtr(), | |
508 base::Passed(request.Pass()), pending_callback)); | |
522 | 509 |
523 switch (backend_state_) { | 510 switch (backend_state_) { |
524 case BACKEND_UNINITIALIZED: | 511 case BACKEND_UNINITIALIZED: |
525 InitBackend(base::Bind(&ServiceWorkerCache::Delete, | 512 InitBackend(pending_operations_.back()); |
526 weak_ptr_factory_.GetWeakPtr(), | |
527 base::Passed(request.Pass()), pending_callback)); | |
528 return; | 513 return; |
529 case BACKEND_CLOSED: | 514 case BACKEND_CLOSED: |
530 pending_callback.Run(ErrorTypeStorage); | 515 pending_callback.Run(ErrorTypeStorage); |
531 return; | 516 return; |
532 case BACKEND_OPEN: | 517 case BACKEND_OPEN: |
533 DCHECK(backend_); | 518 DCHECK(backend_); |
534 break; | 519 RunOperationIfIdle(); |
520 return; | |
535 } | 521 } |
536 | 522 NOTREACHED(); |
537 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); | |
538 | |
539 disk_cache::Entry** entry_ptr = entry.get(); | |
540 | |
541 ServiceWorkerFetchRequest* request_ptr = request.get(); | |
542 | |
543 net::CompletionCallback open_entry_callback = base::Bind( | |
544 &ServiceWorkerCache::DeleteDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), | |
545 origin_, base::Passed(request.Pass()), pending_callback, | |
546 base::Passed(entry.Pass()), quota_manager_proxy_); | |
547 | |
548 int rv = backend_->OpenEntry( | |
549 request_ptr->url.spec(), entry_ptr, open_entry_callback); | |
550 if (rv != net::ERR_IO_PENDING) | |
551 open_entry_callback.Run(rv); | |
552 } | 523 } |
553 | 524 |
554 void ServiceWorkerCache::Keys(const RequestsCallback& callback) { | 525 void ServiceWorkerCache::Keys(const RequestsCallback& callback) { |
555 IncPendingOps(); | |
556 RequestsCallback pending_callback = | 526 RequestsCallback pending_callback = |
557 base::Bind(&ServiceWorkerCache::PendingRequestsCallback, | 527 base::Bind(&ServiceWorkerCache::PendingRequestsCallback, |
558 weak_ptr_factory_.GetWeakPtr(), callback); | 528 weak_ptr_factory_.GetWeakPtr(), callback); |
529 pending_operations_.push_back(base::Bind(&ServiceWorkerCache::KeysImpl, | |
530 weak_ptr_factory_.GetWeakPtr(), | |
531 pending_callback)); | |
559 | 532 |
560 switch (backend_state_) { | 533 switch (backend_state_) { |
561 case BACKEND_UNINITIALIZED: | 534 case BACKEND_UNINITIALIZED: |
562 InitBackend(base::Bind(&ServiceWorkerCache::Keys, | 535 InitBackend(pending_operations_.back()); |
563 weak_ptr_factory_.GetWeakPtr(), pending_callback)); | |
564 return; | 536 return; |
565 case BACKEND_CLOSED: | 537 case BACKEND_CLOSED: |
566 pending_callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); | 538 pending_callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); |
567 return; | 539 return; |
568 case BACKEND_OPEN: | 540 case BACKEND_OPEN: |
569 DCHECK(backend_); | 541 DCHECK(backend_); |
570 break; | 542 RunOperationIfIdle(); |
543 return; | |
571 } | 544 } |
572 | 545 NOTREACHED(); |
573 // 1. Iterate through all of the entries, open them, and add them to a vector. | |
574 // 2. For each open entry: | |
575 // 2.1. Read the headers into a protobuf. | |
576 // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key"). | |
577 // 2.3. Push the response into a vector of requests to be returned. | |
578 // 3. Return the vector of requests (keys). | |
579 | |
580 // The entries have to be loaded into a vector first because enumeration loops | |
581 // forever if you read data from a cache entry while enumerating. | |
582 | |
583 scoped_ptr<KeysContext> keys_context(new KeysContext(pending_callback)); | |
584 | |
585 keys_context->backend_iterator = backend_->CreateIterator(); | |
586 disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; | |
587 disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; | |
588 | |
589 net::CompletionCallback open_entry_callback = base::Bind( | |
590 &ServiceWorkerCache::KeysDidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(), | |
591 base::Passed(keys_context.Pass())); | |
592 | |
593 int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); | |
594 | |
595 if (rv != net::ERR_IO_PENDING) | |
596 open_entry_callback.Run(rv); | |
597 } | 546 } |
598 | 547 |
599 void ServiceWorkerCache::Close(const base::Closure& callback) { | 548 void ServiceWorkerCache::Close(const base::Closure& callback) { |
600 DCHECK(backend_state_ != BACKEND_CLOSED) | 549 DCHECK(backend_state_ != BACKEND_CLOSED) |
601 << "Don't call ServiceWorkerCache::Close() twice."; | 550 << "Don't call ServiceWorkerCache::Close() twice."; |
602 | 551 |
603 backend_state_ = BACKEND_CLOSED; | 552 backend_state_ = BACKEND_CLOSED; |
604 if (pending_ops_ > 0) { | 553 base::Closure pending_callback = |
605 DCHECK(ops_complete_callback_.is_null()); | 554 base::Bind(&ServiceWorkerCache::PendingClosure, |
606 ops_complete_callback_ = | 555 weak_ptr_factory_.GetWeakPtr(), callback); |
607 base::Bind(&ServiceWorkerCache::CloseImpl, | |
608 weak_ptr_factory_.GetWeakPtr(), callback); | |
609 return; | |
610 } | |
611 | 556 |
612 CloseImpl(callback); | 557 pending_operations_.push_back(base::Bind(&ServiceWorkerCache::CloseImpl, |
558 weak_ptr_factory_.GetWeakPtr(), | |
559 pending_callback)); | |
560 RunOperationIfIdle(); | |
613 } | 561 } |
614 | 562 |
615 int64 ServiceWorkerCache::MemoryBackedSize() const { | 563 int64 ServiceWorkerCache::MemoryBackedSize() const { |
616 if (backend_state_ != BACKEND_OPEN || !memory_only_) | 564 if (backend_state_ != BACKEND_OPEN || !memory_only_) |
617 return 0; | 565 return 0; |
618 | 566 |
619 scoped_ptr<disk_cache::Backend::Iterator> backend_iter = | 567 scoped_ptr<disk_cache::Backend::Iterator> backend_iter = |
620 backend_->CreateIterator(); | 568 backend_->CreateIterator(); |
621 disk_cache::Entry* entry = nullptr; | 569 disk_cache::Entry* entry = nullptr; |
622 | 570 |
(...skipping 22 matching lines...) Expand all Loading... | |
645 const base::FilePath& path, | 593 const base::FilePath& path, |
646 net::URLRequestContext* request_context, | 594 net::URLRequestContext* request_context, |
647 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, | 595 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, |
648 base::WeakPtr<storage::BlobStorageContext> blob_context) | 596 base::WeakPtr<storage::BlobStorageContext> blob_context) |
649 : origin_(origin), | 597 : origin_(origin), |
650 path_(path), | 598 path_(path), |
651 request_context_(request_context), | 599 request_context_(request_context), |
652 quota_manager_proxy_(quota_manager_proxy), | 600 quota_manager_proxy_(quota_manager_proxy), |
653 blob_storage_context_(blob_context), | 601 blob_storage_context_(blob_context), |
654 backend_state_(BACKEND_UNINITIALIZED), | 602 backend_state_(BACKEND_UNINITIALIZED), |
603 initializing_(false), | |
655 memory_only_(path.empty()), | 604 memory_only_(path.empty()), |
656 pending_ops_(0), | |
657 weak_ptr_factory_(this) { | 605 weak_ptr_factory_(this) { |
658 } | 606 } |
659 | 607 |
608 void ServiceWorkerCache::MatchImpl( | |
609 scoped_ptr<ServiceWorkerFetchRequest> request, | |
610 const ResponseCallback& callback) { | |
611 DCHECK(backend_state_ != BACKEND_UNINITIALIZED); | |
612 if (backend_state_ != BACKEND_OPEN) { | |
613 callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), | |
614 scoped_ptr<storage::BlobDataHandle>()); | |
615 return; | |
616 } | |
617 | |
618 scoped_ptr<MatchContext> match_context( | |
619 new MatchContext(request.Pass(), callback, blob_storage_context_)); | |
620 | |
621 disk_cache::Entry** entry_ptr = &match_context->entry; | |
622 ServiceWorkerFetchRequest* request_ptr = match_context->request.get(); | |
623 | |
624 net::CompletionCallback open_entry_callback = base::Bind( | |
625 &ServiceWorkerCache::MatchDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), | |
626 base::Passed(match_context.Pass())); | |
627 | |
628 int rv = backend_->OpenEntry(request_ptr->url.spec(), entry_ptr, | |
629 open_entry_callback); | |
630 if (rv != net::ERR_IO_PENDING) | |
631 open_entry_callback.Run(rv); | |
632 } | |
633 | |
660 void ServiceWorkerCache::MatchDidOpenEntry( | 634 void ServiceWorkerCache::MatchDidOpenEntry( |
661 scoped_ptr<MatchContext> match_context, | 635 scoped_ptr<MatchContext> match_context, |
662 int rv) { | 636 int rv) { |
663 if (rv != net::OK) { | 637 if (rv != net::OK) { |
664 match_context->original_callback.Run(ServiceWorkerCache::ErrorTypeNotFound, | 638 match_context->original_callback.Run(ServiceWorkerCache::ErrorTypeNotFound, |
665 scoped_ptr<ServiceWorkerResponse>(), | 639 scoped_ptr<ServiceWorkerResponse>(), |
666 scoped_ptr<storage::BlobDataHandle>()); | 640 scoped_ptr<storage::BlobDataHandle>()); |
667 return; | 641 return; |
668 } | 642 } |
669 | 643 |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
811 scoped_ptr<storage::BlobDataHandle> blob_data_handle( | 785 scoped_ptr<storage::BlobDataHandle> blob_data_handle( |
812 match_context->blob_storage_context->AddFinishedBlob( | 786 match_context->blob_storage_context->AddFinishedBlob( |
813 match_context->blob_data.get())); | 787 match_context->blob_data.get())); |
814 | 788 |
815 match_context->original_callback.Run(ServiceWorkerCache::ErrorTypeOK, | 789 match_context->original_callback.Run(ServiceWorkerCache::ErrorTypeOK, |
816 match_context->response.Pass(), | 790 match_context->response.Pass(), |
817 blob_data_handle.Pass()); | 791 blob_data_handle.Pass()); |
818 } | 792 } |
819 | 793 |
820 void ServiceWorkerCache::PutImpl(scoped_ptr<PutContext> put_context) { | 794 void ServiceWorkerCache::PutImpl(scoped_ptr<PutContext> put_context) { |
795 DCHECK(backend_state_ != BACKEND_UNINITIALIZED); | |
821 if (backend_state_ != BACKEND_OPEN) { | 796 if (backend_state_ != BACKEND_OPEN) { |
822 put_context->callback.Run(ErrorTypeStorage, | 797 put_context->callback.Run(ErrorTypeStorage, |
823 scoped_ptr<ServiceWorkerResponse>(), | 798 scoped_ptr<ServiceWorkerResponse>(), |
824 scoped_ptr<storage::BlobDataHandle>()); | 799 scoped_ptr<storage::BlobDataHandle>()); |
825 return; | 800 return; |
826 } | 801 } |
827 | 802 |
828 scoped_ptr<ServiceWorkerFetchRequest> request_copy( | 803 scoped_ptr<ServiceWorkerFetchRequest> request_copy( |
829 new ServiceWorkerFetchRequest(*put_context->request)); | 804 new ServiceWorkerFetchRequest(*put_context->request)); |
830 | 805 |
831 Delete(request_copy.Pass(), base::Bind(&ServiceWorkerCache::PutDidDelete, | 806 DeleteImpl(request_copy.Pass(), base::Bind(&ServiceWorkerCache::PutDidDelete, |
832 weak_ptr_factory_.GetWeakPtr(), | 807 weak_ptr_factory_.GetWeakPtr(), |
833 base::Passed(put_context.Pass()))); | 808 base::Passed(put_context.Pass()))); |
834 } | 809 } |
835 | 810 |
836 void ServiceWorkerCache::PutDidDelete(scoped_ptr<PutContext> put_context, | 811 void ServiceWorkerCache::PutDidDelete(scoped_ptr<PutContext> put_context, |
837 ErrorType delete_error) { | 812 ErrorType delete_error) { |
838 if (backend_state_ != BACKEND_OPEN) { | 813 if (backend_state_ != BACKEND_OPEN) { |
839 put_context->callback.Run(ErrorTypeStorage, | 814 put_context->callback.Run(ErrorTypeStorage, |
840 scoped_ptr<ServiceWorkerResponse>(), | 815 scoped_ptr<ServiceWorkerResponse>(), |
841 scoped_ptr<storage::BlobDataHandle>()); | 816 scoped_ptr<storage::BlobDataHandle>()); |
842 return; | 817 return; |
843 } | 818 } |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
996 storage::kStorageTypeTemporary, | 971 storage::kStorageTypeTemporary, |
997 put_context->cache_entry->GetDataSize(INDEX_HEADERS) + | 972 put_context->cache_entry->GetDataSize(INDEX_HEADERS) + |
998 put_context->cache_entry->GetDataSize(INDEX_RESPONSE_BODY)); | 973 put_context->cache_entry->GetDataSize(INDEX_RESPONSE_BODY)); |
999 } | 974 } |
1000 | 975 |
1001 put_context->callback.Run(ServiceWorkerCache::ErrorTypeOK, | 976 put_context->callback.Run(ServiceWorkerCache::ErrorTypeOK, |
1002 put_context->response.Pass(), | 977 put_context->response.Pass(), |
1003 put_context->out_blob_data_handle.Pass()); | 978 put_context->out_blob_data_handle.Pass()); |
1004 } | 979 } |
1005 | 980 |
981 void ServiceWorkerCache::DeleteImpl( | |
982 scoped_ptr<ServiceWorkerFetchRequest> request, | |
983 const ErrorCallback& callback) { | |
984 DCHECK(backend_state_ != BACKEND_UNINITIALIZED); | |
985 if (backend_state_ != BACKEND_OPEN) { | |
986 callback.Run(ErrorTypeStorage); | |
987 return; | |
988 } | |
989 scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); | |
990 | |
991 disk_cache::Entry** entry_ptr = entry.get(); | |
992 | |
993 ServiceWorkerFetchRequest* request_ptr = request.get(); | |
994 | |
995 net::CompletionCallback open_entry_callback = base::Bind( | |
996 &ServiceWorkerCache::DeleteDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), | |
997 origin_, base::Passed(request.Pass()), callback, | |
998 base::Passed(entry.Pass()), quota_manager_proxy_); | |
999 | |
1000 int rv = backend_->OpenEntry(request_ptr->url.spec(), entry_ptr, | |
1001 open_entry_callback); | |
1002 if (rv != net::ERR_IO_PENDING) | |
1003 open_entry_callback.Run(rv); | |
1004 } | |
1005 | |
1006 void ServiceWorkerCache::DeleteDidOpenEntry( | 1006 void ServiceWorkerCache::DeleteDidOpenEntry( |
1007 const GURL& origin, | 1007 const GURL& origin, |
1008 scoped_ptr<ServiceWorkerFetchRequest> request, | 1008 scoped_ptr<ServiceWorkerFetchRequest> request, |
1009 const ServiceWorkerCache::ErrorCallback& callback, | 1009 const ServiceWorkerCache::ErrorCallback& callback, |
1010 scoped_ptr<disk_cache::Entry*> entry_ptr, | 1010 scoped_ptr<disk_cache::Entry*> entry_ptr, |
1011 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, | 1011 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, |
1012 int rv) { | 1012 int rv) { |
1013 if (rv != net::OK) { | 1013 if (rv != net::OK) { |
1014 callback.Run(ServiceWorkerCache::ErrorTypeNotFound); | 1014 callback.Run(ServiceWorkerCache::ErrorTypeNotFound); |
1015 return; | 1015 return; |
1016 } | 1016 } |
1017 | 1017 |
1018 DCHECK(entry_ptr); | 1018 DCHECK(entry_ptr); |
1019 disk_cache::ScopedEntryPtr entry(*entry_ptr); | 1019 disk_cache::ScopedEntryPtr entry(*entry_ptr); |
1020 | 1020 |
1021 if (quota_manager_proxy.get()) { | 1021 if (quota_manager_proxy.get()) { |
1022 quota_manager_proxy->NotifyStorageModified( | 1022 quota_manager_proxy->NotifyStorageModified( |
1023 storage::QuotaClient::kServiceWorkerCache, origin, | 1023 storage::QuotaClient::kServiceWorkerCache, origin, |
1024 storage::kStorageTypeTemporary, | 1024 storage::kStorageTypeTemporary, |
1025 -1 * (entry->GetDataSize(INDEX_HEADERS) + | 1025 -1 * (entry->GetDataSize(INDEX_HEADERS) + |
1026 entry->GetDataSize(INDEX_RESPONSE_BODY))); | 1026 entry->GetDataSize(INDEX_RESPONSE_BODY))); |
1027 } | 1027 } |
1028 | 1028 |
1029 entry->Doom(); | 1029 entry->Doom(); |
1030 callback.Run(ServiceWorkerCache::ErrorTypeOK); | 1030 callback.Run(ServiceWorkerCache::ErrorTypeOK); |
1031 } | 1031 } |
1032 | 1032 |
1033 void ServiceWorkerCache::KeysImpl(const RequestsCallback& callback) { | |
1034 DCHECK(backend_state_ != BACKEND_UNINITIALIZED); | |
1035 if (backend_state_ != BACKEND_OPEN) { | |
1036 callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); | |
1037 return; | |
1038 } | |
1039 | |
1040 // 1. Iterate through all of the entries, open them, and add them to a vector. | |
1041 // 2. For each open entry: | |
1042 // 2.1. Read the headers into a protobuf. | |
1043 // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key"). | |
1044 // 2.3. Push the response into a vector of requests to be returned. | |
1045 // 3. Return the vector of requests (keys). | |
1046 | |
1047 // The entries have to be loaded into a vector first because enumeration loops | |
1048 // forever if you read data from a cache entry while enumerating. | |
1049 | |
1050 scoped_ptr<KeysContext> keys_context(new KeysContext(callback)); | |
1051 | |
1052 keys_context->backend_iterator = backend_->CreateIterator(); | |
1053 disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; | |
1054 disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; | |
1055 | |
1056 net::CompletionCallback open_entry_callback = base::Bind( | |
1057 &ServiceWorkerCache::KeysDidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(), | |
1058 base::Passed(keys_context.Pass())); | |
1059 | |
1060 int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); | |
1061 | |
1062 if (rv != net::ERR_IO_PENDING) | |
1063 open_entry_callback.Run(rv); | |
1064 } | |
1065 | |
1033 void ServiceWorkerCache::KeysDidOpenNextEntry( | 1066 void ServiceWorkerCache::KeysDidOpenNextEntry( |
1034 scoped_ptr<KeysContext> keys_context, | 1067 scoped_ptr<KeysContext> keys_context, |
1035 int rv) { | 1068 int rv) { |
1036 if (rv == net::ERR_FAILED) { | 1069 if (rv == net::ERR_FAILED) { |
1037 DCHECK(!keys_context->enumerated_entry); | 1070 DCHECK(!keys_context->enumerated_entry); |
1038 // Enumeration is complete, extract the requests from the entries. | 1071 // Enumeration is complete, extract the requests from the entries. |
1039 Entries::iterator iter = keys_context->entries.begin(); | 1072 Entries::iterator iter = keys_context->entries.begin(); |
1040 KeysProcessNextEntry(keys_context.Pass(), iter); | 1073 KeysProcessNextEntry(keys_context.Pass(), iter); |
1041 return; | 1074 return; |
1042 } | 1075 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1108 } | 1141 } |
1109 } else { | 1142 } else { |
1110 entry->Doom(); | 1143 entry->Doom(); |
1111 } | 1144 } |
1112 | 1145 |
1113 KeysProcessNextEntry(keys_context.Pass(), iter + 1); | 1146 KeysProcessNextEntry(keys_context.Pass(), iter + 1); |
1114 } | 1147 } |
1115 | 1148 |
1116 void ServiceWorkerCache::CloseImpl(const base::Closure& callback) { | 1149 void ServiceWorkerCache::CloseImpl(const base::Closure& callback) { |
1117 DCHECK(backend_state_ == BACKEND_CLOSED); | 1150 DCHECK(backend_state_ == BACKEND_CLOSED); |
1151 DCHECK(pending_operations_.size() == 1u); | |
1118 backend_.reset(); | 1152 backend_.reset(); |
1119 callback.Run(); | 1153 callback.Run(); |
1120 } | 1154 } |
1121 | 1155 |
1122 void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) { | 1156 void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) { |
1123 DCHECK(!backend_); | 1157 DCHECK(!backend_); |
1124 | 1158 |
1125 // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction. | 1159 // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction. |
1126 net::CacheType cache_type = memory_only_ ? net::MEMORY_CACHE : net::APP_CACHE; | 1160 net::CacheType cache_type = memory_only_ ? net::MEMORY_CACHE : net::APP_CACHE; |
1127 | 1161 |
(...skipping 29 matching lines...) Expand all Loading... | |
1157 int rv) { | 1191 int rv) { |
1158 if (rv != net::OK) { | 1192 if (rv != net::OK) { |
1159 callback.Run(ServiceWorkerCache::ErrorTypeStorage); | 1193 callback.Run(ServiceWorkerCache::ErrorTypeStorage); |
1160 return; | 1194 return; |
1161 } | 1195 } |
1162 | 1196 |
1163 backend_ = backend_ptr->Pass(); | 1197 backend_ = backend_ptr->Pass(); |
1164 callback.Run(ServiceWorkerCache::ErrorTypeOK); | 1198 callback.Run(ServiceWorkerCache::ErrorTypeOK); |
1165 } | 1199 } |
1166 | 1200 |
1167 void ServiceWorkerCache::InitBackend(const base::Closure& callback) { | 1201 void ServiceWorkerCache::InitBackend(const base::Closure& callback) { |
michaeln
2015/01/23 00:55:25
The contract is a little odd, the 'callback' provi
jkarlin
2015/01/23 18:13:42
Done.
| |
1168 DCHECK(backend_state_ == BACKEND_UNINITIALIZED); | 1202 DCHECK(backend_state_ == BACKEND_UNINITIALIZED); |
1169 init_callbacks_.push_back(callback); | |
1170 | 1203 |
1171 // If this isn't the first call to Init then return as the initialization | 1204 if (initializing_) |
1172 // has already started. | |
1173 if (init_callbacks_.size() > 1u) | |
1174 return; | 1205 return; |
1175 | 1206 |
1207 initializing_ = true; | |
1176 CreateBackend(base::Bind(&ServiceWorkerCache::InitDone, | 1208 CreateBackend(base::Bind(&ServiceWorkerCache::InitDone, |
1177 weak_ptr_factory_.GetWeakPtr())); | 1209 weak_ptr_factory_.GetWeakPtr(), callback)); |
1178 } | 1210 } |
1179 | 1211 |
1180 void ServiceWorkerCache::InitDone(ErrorType error) { | 1212 void ServiceWorkerCache::InitDone(const base::Closure& callback, |
1213 ErrorType error) { | |
1214 initializing_ = false; | |
1181 backend_state_ = (error == ErrorTypeOK && backend_ && | 1215 backend_state_ = (error == ErrorTypeOK && backend_ && |
1182 backend_state_ == BACKEND_UNINITIALIZED) | 1216 backend_state_ == BACKEND_UNINITIALIZED) |
1183 ? BACKEND_OPEN | 1217 ? BACKEND_OPEN |
1184 : BACKEND_CLOSED; | 1218 : BACKEND_CLOSED; |
1185 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); | 1219 callback.Run(); |
1186 it != init_callbacks_.end(); ++it) { | |
1187 it->Run(); | |
1188 } | |
1189 init_callbacks_.clear(); | |
1190 } | 1220 } |
1191 | 1221 |
1192 void ServiceWorkerCache::DecPendingOps() { | 1222 void ServiceWorkerCache::CompleteOperationAndRunNext() { |
1193 DCHECK(pending_ops_ > 0); | 1223 DCHECK(!pending_operations_.empty()); |
1194 pending_ops_--; | 1224 |
1195 if (pending_ops_ == 0 && !ops_complete_callback_.is_null()) { | 1225 pending_operations_.pop_front(); |
1196 ops_complete_callback_.Run(); | 1226 |
1197 ops_complete_callback_.Reset(); | 1227 // TODO(jkarlin): Run multiple operations in parallel where allowed (e.g., if |
1198 } | 1228 // they're for different keys then they won't interfere). See |
1229 // https://crbug.com/451174. | |
1230 if (!pending_operations_.empty()) | |
1231 pending_operations_.front().Run(); | |
1232 } | |
1233 | |
1234 void ServiceWorkerCache::RunOperationIfIdle() { | |
michaeln
2015/01/23 00:55:25
nit: this method is a little dangerous, if called
jkarlin
2015/01/23 18:13:42
Done.
| |
1235 if (pending_operations_.size() == 1u) | |
1236 pending_operations_.front().Run(); | |
1237 } | |
1238 | |
1239 void ServiceWorkerCache::PendingClosure(const base::Closure& callback) { | |
1240 callback.Run(); | |
1241 CompleteOperationAndRunNext(); | |
1199 } | 1242 } |
1200 | 1243 |
1201 void ServiceWorkerCache::PendingErrorCallback(const ErrorCallback& callback, | 1244 void ServiceWorkerCache::PendingErrorCallback(const ErrorCallback& callback, |
1202 ErrorType error) { | 1245 ErrorType error) { |
1203 callback.Run(error); | 1246 callback.Run(error); |
1204 DecPendingOps(); | 1247 CompleteOperationAndRunNext(); |
1205 } | 1248 } |
1206 | 1249 |
1207 void ServiceWorkerCache::PendingResponseCallback( | 1250 void ServiceWorkerCache::PendingResponseCallback( |
1208 const ResponseCallback& callback, | 1251 const ResponseCallback& callback, |
1209 ErrorType error, | 1252 ErrorType error, |
1210 scoped_ptr<ServiceWorkerResponse> response, | 1253 scoped_ptr<ServiceWorkerResponse> response, |
1211 scoped_ptr<storage::BlobDataHandle> blob_data_handle) { | 1254 scoped_ptr<storage::BlobDataHandle> blob_data_handle) { |
1212 callback.Run(error, response.Pass(), blob_data_handle.Pass()); | 1255 callback.Run(error, response.Pass(), blob_data_handle.Pass()); |
1213 DecPendingOps(); | 1256 CompleteOperationAndRunNext(); |
1214 } | 1257 } |
1215 | 1258 |
1216 void ServiceWorkerCache::PendingRequestsCallback( | 1259 void ServiceWorkerCache::PendingRequestsCallback( |
1217 const RequestsCallback& callback, | 1260 const RequestsCallback& callback, |
1218 ErrorType error, | 1261 ErrorType error, |
1219 scoped_ptr<Requests> requests) { | 1262 scoped_ptr<Requests> requests) { |
1220 callback.Run(error, requests.Pass()); | 1263 callback.Run(error, requests.Pass()); |
1221 DecPendingOps(); | 1264 CompleteOperationAndRunNext(); |
1222 } | 1265 } |
1223 | 1266 |
1224 } // namespace content | 1267 } // namespace content |
OLD | NEW |