Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(783)

Side by Side Diff: content/browser/service_worker/service_worker_cache.cc

Issue 863263003: [ServiceWorkerCache] Make the cache operations run serially. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Change Close to run serially too Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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();
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();
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();
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();
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 base::Closure pending_callback =
604 if (pending_ops_ > 0) { 553 base::Bind(&ServiceWorkerCache::PendingClosure,
605 DCHECK(ops_complete_callback_.is_null()); 554 weak_ptr_factory_.GetWeakPtr(), callback);
606 ops_complete_callback_ =
607 base::Bind(&ServiceWorkerCache::CloseImpl,
608 weak_ptr_factory_.GetWeakPtr(), callback);
609 return;
610 }
611 555
612 CloseImpl(callback); 556 pending_operations_.push_back(base::Bind(&ServiceWorkerCache::CloseImpl,
557 weak_ptr_factory_.GetWeakPtr(),
558 pending_callback));
559 RunOperationIfIdle();
613 } 560 }
614 561
615 int64 ServiceWorkerCache::MemoryBackedSize() const { 562 int64 ServiceWorkerCache::MemoryBackedSize() const {
616 if (backend_state_ != BACKEND_OPEN || !memory_only_) 563 if (backend_state_ != BACKEND_OPEN || !memory_only_)
617 return 0; 564 return 0;
618 565
619 scoped_ptr<disk_cache::Backend::Iterator> backend_iter = 566 scoped_ptr<disk_cache::Backend::Iterator> backend_iter =
620 backend_->CreateIterator(); 567 backend_->CreateIterator();
621 disk_cache::Entry* entry = nullptr; 568 disk_cache::Entry* entry = nullptr;
622 569
(...skipping 22 matching lines...) Expand all
645 const base::FilePath& path, 592 const base::FilePath& path,
646 net::URLRequestContext* request_context, 593 net::URLRequestContext* request_context,
647 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy, 594 const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
648 base::WeakPtr<storage::BlobStorageContext> blob_context) 595 base::WeakPtr<storage::BlobStorageContext> blob_context)
649 : origin_(origin), 596 : origin_(origin),
650 path_(path), 597 path_(path),
651 request_context_(request_context), 598 request_context_(request_context),
652 quota_manager_proxy_(quota_manager_proxy), 599 quota_manager_proxy_(quota_manager_proxy),
653 blob_storage_context_(blob_context), 600 blob_storage_context_(blob_context),
654 backend_state_(BACKEND_UNINITIALIZED), 601 backend_state_(BACKEND_UNINITIALIZED),
602 operation_running_(false),
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
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
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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 req_headers.insert(std::make_pair(header.name(), header.value())); 1140 req_headers.insert(std::make_pair(header.name(), header.value()));
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
1152 backend_state_ = BACKEND_CLOSED;
1118 backend_.reset(); 1153 backend_.reset();
1119 callback.Run(); 1154 callback.Run();
1120 } 1155 }
1121 1156
1122 void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) { 1157 void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) {
1123 DCHECK(!backend_); 1158 DCHECK(!backend_);
1124 1159
1125 // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction. 1160 // 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; 1161 net::CacheType cache_type = memory_only_ ? net::MEMORY_CACHE : net::APP_CACHE;
1127 1162
(...skipping 29 matching lines...) Expand all
1157 int rv) { 1192 int rv) {
1158 if (rv != net::OK) { 1193 if (rv != net::OK) {
1159 callback.Run(ServiceWorkerCache::ErrorTypeStorage); 1194 callback.Run(ServiceWorkerCache::ErrorTypeStorage);
1160 return; 1195 return;
1161 } 1196 }
1162 1197
1163 backend_ = backend_ptr->Pass(); 1198 backend_ = backend_ptr->Pass();
1164 callback.Run(ServiceWorkerCache::ErrorTypeOK); 1199 callback.Run(ServiceWorkerCache::ErrorTypeOK);
1165 } 1200 }
1166 1201
1167 void ServiceWorkerCache::InitBackend(const base::Closure& callback) { 1202 void ServiceWorkerCache::InitBackend() {
1168 DCHECK(backend_state_ == BACKEND_UNINITIALIZED); 1203 DCHECK(backend_state_ == BACKEND_UNINITIALIZED);
1169 init_callbacks_.push_back(callback);
1170 1204
1171 // If this isn't the first call to Init then return as the initialization 1205 if (initializing_) {
1172 // has already started. 1206 DCHECK(operation_running_);
1173 if (init_callbacks_.size() > 1u)
1174 return; 1207 return;
1208 }
1175 1209
1176 CreateBackend(base::Bind(&ServiceWorkerCache::InitDone, 1210 DCHECK(!operation_running_); // All ops should wait for backend init.
1177 weak_ptr_factory_.GetWeakPtr())); 1211 initializing_ = true;
1212 // Note that this operation pushes to the front of the queue.
1213 pending_operations_.push_front(base::Bind(
1214 &ServiceWorkerCache::CreateBackend, weak_ptr_factory_.GetWeakPtr(),
1215 base::Bind(&ServiceWorkerCache::InitDone,
1216 weak_ptr_factory_.GetWeakPtr())));
1217 RunOperationIfIdle();
1178 } 1218 }
1179 1219
1180 void ServiceWorkerCache::InitDone(ErrorType error) { 1220 void ServiceWorkerCache::InitDone(ErrorType error) {
1221 initializing_ = false;
1181 backend_state_ = (error == ErrorTypeOK && backend_ && 1222 backend_state_ = (error == ErrorTypeOK && backend_ &&
1182 backend_state_ == BACKEND_UNINITIALIZED) 1223 backend_state_ == BACKEND_UNINITIALIZED)
1183 ? BACKEND_OPEN 1224 ? BACKEND_OPEN
1184 : BACKEND_CLOSED; 1225 : BACKEND_CLOSED;
1185 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); 1226 CompleteOperationAndRunNext();
1186 it != init_callbacks_.end(); ++it) {
1187 it->Run();
1188 }
1189 init_callbacks_.clear();
1190 } 1227 }
1191 1228
1192 void ServiceWorkerCache::DecPendingOps() { 1229 void ServiceWorkerCache::CompleteOperationAndRunNext() {
1193 DCHECK(pending_ops_ > 0); 1230 DCHECK(!pending_operations_.empty());
1194 pending_ops_--; 1231 operation_running_ = false;
1195 if (pending_ops_ == 0 && !ops_complete_callback_.is_null()) { 1232 pending_operations_.pop_front();
1196 ops_complete_callback_.Run(); 1233 RunOperationIfIdle();
1197 ops_complete_callback_.Reset(); 1234 }
1235
1236 void ServiceWorkerCache::RunOperationIfIdle() {
1237 DCHECK(!operation_running_ || !pending_operations_.empty());
1238
1239 if (!operation_running_ && !pending_operations_.empty()) {
1240 operation_running_ = true;
1241 // TODO(jkarlin): Run multiple operations in parallel where allowed (e.g.,
1242 // if they're for different keys then they won't interfere). See
1243 // https://crbug.com/451174.
1244 pending_operations_.front().Run();
1198 } 1245 }
1199 } 1246 }
1200 1247
1248 void ServiceWorkerCache::PendingClosure(const base::Closure& callback) {
1249 callback.Run();
1250 CompleteOperationAndRunNext();
1251 }
1252
1201 void ServiceWorkerCache::PendingErrorCallback(const ErrorCallback& callback, 1253 void ServiceWorkerCache::PendingErrorCallback(const ErrorCallback& callback,
1202 ErrorType error) { 1254 ErrorType error) {
1203 callback.Run(error); 1255 callback.Run(error);
1204 DecPendingOps(); 1256 CompleteOperationAndRunNext();
1205 } 1257 }
1206 1258
1207 void ServiceWorkerCache::PendingResponseCallback( 1259 void ServiceWorkerCache::PendingResponseCallback(
1208 const ResponseCallback& callback, 1260 const ResponseCallback& callback,
1209 ErrorType error, 1261 ErrorType error,
1210 scoped_ptr<ServiceWorkerResponse> response, 1262 scoped_ptr<ServiceWorkerResponse> response,
1211 scoped_ptr<storage::BlobDataHandle> blob_data_handle) { 1263 scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
1212 callback.Run(error, response.Pass(), blob_data_handle.Pass()); 1264 callback.Run(error, response.Pass(), blob_data_handle.Pass());
1213 DecPendingOps(); 1265 CompleteOperationAndRunNext();
1214 } 1266 }
1215 1267
1216 void ServiceWorkerCache::PendingRequestsCallback( 1268 void ServiceWorkerCache::PendingRequestsCallback(
1217 const RequestsCallback& callback, 1269 const RequestsCallback& callback,
1218 ErrorType error, 1270 ErrorType error,
1219 scoped_ptr<Requests> requests) { 1271 scoped_ptr<Requests> requests) {
1220 callback.Run(error, requests.Pass()); 1272 callback.Run(error, requests.Pass());
1221 DecPendingOps(); 1273 CompleteOperationAndRunNext();
1222 } 1274 }
1223 1275
1224 } // namespace content 1276 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/service_worker/service_worker_cache.h ('k') | content/browser/service_worker/service_worker_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698