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

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

Issue 1108253002: (Reland) Evict Service Worker when reading it from disk cache fails. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: check context Created 5 years, 7 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
« no previous file with comments | « no previous file | content/browser/service_worker/service_worker_read_from_cache_job.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "base/bind.h" 5 #include "base/bind.h"
6 #include "base/callback.h" 6 #include "base/callback.h"
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/run_loop.h" 8 #include "base/run_loop.h"
9 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
10 #include "content/browser/fileapi/chrome_blob_storage_context.h" 10 #include "content/browser/fileapi/chrome_blob_storage_context.h"
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 ServiceWorkerVersion::FetchCallback CreateResponseReceiver( 124 ServiceWorkerVersion::FetchCallback CreateResponseReceiver(
125 BrowserThread::ID run_quit_thread, 125 BrowserThread::ID run_quit_thread,
126 const base::Closure& quit, 126 const base::Closure& quit,
127 ChromeBlobStorageContext* blob_context, 127 ChromeBlobStorageContext* blob_context,
128 FetchResult* result) { 128 FetchResult* result) {
129 return base::Bind(&ReceiveFetchResult, run_quit_thread, quit, 129 return base::Bind(&ReceiveFetchResult, run_quit_thread, quit,
130 make_scoped_refptr<ChromeBlobStorageContext>(blob_context), 130 make_scoped_refptr<ChromeBlobStorageContext>(blob_context),
131 result); 131 result);
132 } 132 }
133 133
134 void ReceiveFindRegistrationStatus(
135 BrowserThread::ID run_quit_thread,
136 const base::Closure& quit,
137 ServiceWorkerStatusCode* out_status,
138 ServiceWorkerStatusCode status,
139 const scoped_refptr<ServiceWorkerRegistration>& registration) {
140 *out_status = status;
141 if (!quit.is_null())
142 BrowserThread::PostTask(run_quit_thread, FROM_HERE, quit);
143 }
144
145 ServiceWorkerStorage::FindRegistrationCallback CreateFindRegistrationReceiver(
146 BrowserThread::ID run_quit_thread,
147 const base::Closure& quit,
148 ServiceWorkerStatusCode* status) {
149 return base::Bind(&ReceiveFindRegistrationStatus, run_quit_thread, quit,
150 status);
151 }
152
134 void ReadResponseBody(std::string* body, 153 void ReadResponseBody(std::string* body,
135 storage::BlobDataHandle* blob_data_handle) { 154 storage::BlobDataHandle* blob_data_handle) {
136 ASSERT_TRUE(blob_data_handle); 155 ASSERT_TRUE(blob_data_handle);
137 scoped_ptr<storage::BlobDataSnapshot> data = 156 scoped_ptr<storage::BlobDataSnapshot> data =
138 blob_data_handle->CreateSnapshot(); 157 blob_data_handle->CreateSnapshot();
139 ASSERT_EQ(1U, data->items().size()); 158 ASSERT_EQ(1U, data->items().size());
140 *body = std::string(data->items()[0]->bytes(), data->items()[0]->length()); 159 *body = std::string(data->items()[0]->bytes(), data->items()[0]->length());
141 } 160 }
142 161
143 void ExpectResultAndRun(bool expected, 162 void ExpectResultAndRun(bool expected,
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 void FetchTestHelper(const std::string& worker_url, 560 void FetchTestHelper(const std::string& worker_url,
542 ServiceWorkerFetchEventResult* result, 561 ServiceWorkerFetchEventResult* result,
543 ServiceWorkerResponse* response, 562 ServiceWorkerResponse* response,
544 scoped_ptr<storage::BlobDataHandle>* blob_data_handle) { 563 scoped_ptr<storage::BlobDataHandle>* blob_data_handle) {
545 RunOnIOThread( 564 RunOnIOThread(
546 base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url)); 565 base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url));
547 FetchOnRegisteredWorker(result, response, blob_data_handle); 566 FetchOnRegisteredWorker(result, response, blob_data_handle);
548 } 567 }
549 568
550 void SetUpRegistrationOnIOThread(const std::string& worker_url) { 569 void SetUpRegistrationOnIOThread(const std::string& worker_url) {
570 DCHECK_CURRENTLY_ON(BrowserThread::IO);
551 const GURL pattern = embedded_test_server()->GetURL("/service_worker/"); 571 const GURL pattern = embedded_test_server()->GetURL("/service_worker/");
552 registration_ = new ServiceWorkerRegistration( 572 registration_ = new ServiceWorkerRegistration(
553 pattern, 573 pattern,
554 wrapper()->context()->storage()->NewRegistrationId(), 574 wrapper()->context()->storage()->NewRegistrationId(),
555 wrapper()->context()->AsWeakPtr()); 575 wrapper()->context()->AsWeakPtr());
556 version_ = new ServiceWorkerVersion( 576 version_ = new ServiceWorkerVersion(
557 registration_.get(), 577 registration_.get(),
558 embedded_test_server()->GetURL(worker_url), 578 embedded_test_server()->GetURL(worker_url),
559 wrapper()->context()->storage()->NewVersionId(), 579 wrapper()->context()->storage()->NewVersionId(),
560 wrapper()->context()->AsWeakPtr()); 580 wrapper()->context()->AsWeakPtr());
561 581
562 // Make the registration findable via storage functions. 582 // Make the registration findable via storage functions.
563 wrapper()->context()->storage()->NotifyInstallingRegistration( 583 wrapper()->context()->storage()->NotifyInstallingRegistration(
564 registration_.get()); 584 registration_.get());
565 585
566 AssociateRendererProcessToPattern(pattern); 586 AssociateRendererProcessToPattern(pattern);
567 } 587 }
568 588
569 void TimeoutWorkerOnIOThread() { 589 void TimeoutWorkerOnIOThread() {
570 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 590 DCHECK_CURRENTLY_ON(BrowserThread::IO);
kinuko 2015/04/28 08:34:05 nit: I think we prefer ASSERT when in tests
falken 2015/04/28 09:00:11 Oh, didn't know that... done.
571 version_->PingWorker(); 591 version_->PingWorker();
572 version_->OnPingTimeout(); 592 version_->OnPingTimeout();
573 } 593 }
574 594
595 void AddControlleeOnIOThread() {
596 DCHECK_CURRENTLY_ON(BrowserThread::IO);
597 scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
598 33 /* dummy render process id */,
599 MSG_ROUTING_NONE /* render_frame_id */, 1 /* dummy provider_id */,
600 SERVICE_WORKER_PROVIDER_FOR_WINDOW, wrapper()->context()->AsWeakPtr(),
601 NULL));
602 host->SetDocumentUrl(
603 embedded_test_server()->GetURL("/service_worker/host"));
604 host->AssociateRegistration(registration_.get(),
605 false /* notify_controllerchange */);
606 wrapper()->context()->AddProviderHost(host.Pass());
607 }
608
609 void AddWaitingWorkerOnIOThread(const std::string& worker_url) {
610 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
611 scoped_refptr<ServiceWorkerVersion> waiting_version(
612 new ServiceWorkerVersion(
613 registration_.get(), embedded_test_server()->GetURL(worker_url),
614 wrapper()->context()->storage()->NewVersionId(),
615 wrapper()->context()->AsWeakPtr()));
616 waiting_version->SetStatus(ServiceWorkerVersion::INSTALLED);
617 registration_->SetWaitingVersion(waiting_version.get());
618 registration_->ActivateWaitingVersionWhenReady();
619 }
620
575 void StartWorker(ServiceWorkerStatusCode expected_status) { 621 void StartWorker(ServiceWorkerStatusCode expected_status) {
576 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); 622 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
577 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; 623 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
578 base::RunLoop start_run_loop; 624 base::RunLoop start_run_loop;
579 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 625 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
580 base::Bind(&self::StartOnIOThread, this, 626 base::Bind(&self::StartOnIOThread, this,
581 start_run_loop.QuitClosure(), 627 start_run_loop.QuitClosure(),
582 &status)); 628 &status));
583 start_run_loop.Run(); 629 start_run_loop.Run();
584 ASSERT_EQ(expected_status, status); 630 ASSERT_EQ(expected_status, status);
585 } 631 }
586 632
587 void StopWorker(ServiceWorkerStatusCode expected_status) { 633 void StopWorker(ServiceWorkerStatusCode expected_status) {
588 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI)); 634 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
589 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; 635 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
590 base::RunLoop stop_run_loop; 636 base::RunLoop stop_run_loop;
591 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 637 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
592 base::Bind(&self::StopOnIOThread, this, 638 base::Bind(&self::StopOnIOThread, this,
593 stop_run_loop.QuitClosure(), 639 stop_run_loop.QuitClosure(),
594 &status)); 640 &status));
595 stop_run_loop.Run(); 641 stop_run_loop.Run();
596 ASSERT_EQ(expected_status, status); 642 ASSERT_EQ(expected_status, status);
597 } 643 }
598 644
645 void StoreRegistration(int64 version_id,
646 ServiceWorkerStatusCode expected_status) {
647 DCHECK_CURRENTLY_ON(BrowserThread::UI);
648 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
649 base::RunLoop store_run_loop;
650 BrowserThread::PostTask(
651 BrowserThread::IO, FROM_HERE,
652 base::Bind(&self::StoreOnIOThread, this, store_run_loop.QuitClosure(),
653 &status, version_id));
654 store_run_loop.Run();
655 ASSERT_EQ(expected_status, status);
656
657 RunOnIOThread(base::Bind(&self::NotifyDoneInstallingRegistrationOnIOThread,
658 this, status));
659 }
660
661 void FindRegistrationForId(int64 id,
662 const GURL& origin,
663 ServiceWorkerStatusCode expected_status) {
664 DCHECK_CURRENTLY_ON(BrowserThread::UI);
665 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
666 base::RunLoop run_loop;
667 BrowserThread::PostTask(
668 BrowserThread::IO, FROM_HERE,
669 base::Bind(&self::FindRegistrationForIdOnIOThread, this,
670 run_loop.QuitClosure(), &status, id, origin));
671 run_loop.Run();
672 ASSERT_EQ(expected_status, status);
673 }
674
675 void FindRegistrationForIdOnIOThread(const base::Closure& done,
676 ServiceWorkerStatusCode* result,
677 int64 id,
678 const GURL& origin) {
679 DCHECK_CURRENTLY_ON(BrowserThread::IO);
680 wrapper()->context()->storage()->FindRegistrationForId(
681 id, origin,
682 CreateFindRegistrationReceiver(BrowserThread::UI, done, result));
683 }
684
685 void NotifyDoneInstallingRegistrationOnIOThread(
686 ServiceWorkerStatusCode status) {
687 DCHECK_CURRENTLY_ON(BrowserThread::IO);
688 wrapper()->context()->storage()->NotifyDoneInstallingRegistration(
689 registration_.get(), version_.get(), status);
690 }
691
692 void RemoveLiveRegistrationOnIOThread(int64 id) {
693 DCHECK_CURRENTLY_ON(BrowserThread::IO);
694 wrapper()->context()->RemoveLiveRegistration(id);
695 }
696
599 void StartOnIOThread(const base::Closure& done, 697 void StartOnIOThread(const base::Closure& done,
600 ServiceWorkerStatusCode* result) { 698 ServiceWorkerStatusCode* result) {
601 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 699 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
602 version_->StartWorker(CreateReceiver(BrowserThread::UI, done, result)); 700 version_->StartWorker(CreateReceiver(BrowserThread::UI, done, result));
603 } 701 }
604 702
605 void InstallOnIOThread(const base::Closure& done, 703 void InstallOnIOThread(const base::Closure& done,
606 ServiceWorkerStatusCode* result) { 704 ServiceWorkerStatusCode* result) {
607 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 705 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
608 version_->SetStatus(ServiceWorkerVersion::INSTALLING); 706 version_->SetStatus(ServiceWorkerVersion::INSTALLING);
609 version_->DispatchInstallEvent( 707 version_->DispatchInstallEvent(
610 CreateReceiver(BrowserThread::UI, done, result)); 708 CreateReceiver(BrowserThread::UI, done, result));
611 } 709 }
612 710
711 void StoreOnIOThread(const base::Closure& done,
712 ServiceWorkerStatusCode* result,
713 int64 version_id) {
714 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
715 ServiceWorkerVersion* version =
716 wrapper()->context()->GetLiveVersion(version_id);
717 wrapper()->context()->storage()->StoreRegistration(
718 registration_.get(), version,
719 CreateReceiver(BrowserThread::UI, done, result));
720 }
721
613 void ActivateOnIOThread(const base::Closure& done, 722 void ActivateOnIOThread(const base::Closure& done,
614 ServiceWorkerStatusCode* result) { 723 ServiceWorkerStatusCode* result) {
615 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 724 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
616 version_->SetStatus(ServiceWorkerVersion::ACTIVATING); 725 version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
726 registration_->SetActiveVersion(version_.get());
617 version_->DispatchActivateEvent( 727 version_->DispatchActivateEvent(
618 CreateReceiver(BrowserThread::UI, done, result)); 728 CreateReceiver(BrowserThread::UI, done, result));
619 } 729 }
620 730
621 void FetchOnIOThread(const base::Closure& done, 731 void FetchOnIOThread(const base::Closure& done,
622 bool* prepare_result, 732 bool* prepare_result,
623 FetchResult* result) { 733 FetchResult* result) {
624 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); 734 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
625 ServiceWorkerFetchRequest request( 735 ServiceWorkerFetchRequest request(
626 embedded_test_server()->GetURL("/service_worker/empty.html"), 736 embedded_test_server()->GetURL("/service_worker/empty.html"),
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 } 833 }
724 834
725 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) { 835 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) {
726 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this, 836 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
727 "/service_worker/nonexistent.js")); 837 "/service_worker/nonexistent.js"));
728 838
729 // Start a worker for nonexistent URL. 839 // Start a worker for nonexistent URL.
730 StartWorker(SERVICE_WORKER_ERROR_NETWORK); 840 StartWorker(SERVICE_WORKER_ERROR_NETWORK);
731 } 841 }
732 842
843 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, ReadResourceFailure) {
844 // Create and store a registration.
845 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
846 "/service_worker/worker.js"));
847 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
848 StoreRegistration(version_->version_id(), SERVICE_WORKER_OK);
849
850 // Add a non-existent resource to the version.
851 std::vector<ServiceWorkerDatabase::ResourceRecord> records;
852 records.push_back(
853 ServiceWorkerDatabase::ResourceRecord(30, version_->script_url(), 100));
854 version_->script_cache_map()->SetResources(records);
855
856 // Start the worker. We'll fail to read the resource.
857 StartWorker(SERVICE_WORKER_ERROR_DISK_CACHE);
858 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
859
860 // The registration should be deleted from storage since the broken worker was
861 // the stored one.
862 RunOnIOThread(base::Bind(&self::RemoveLiveRegistrationOnIOThread, this,
863 registration_->id()));
864 FindRegistrationForId(registration_->id(),
865 registration_->pattern().GetOrigin(),
866 SERVICE_WORKER_ERROR_NOT_FOUND);
867 }
868
869 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
870 ReadResourceFailure_WaitingWorker) {
871 RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
872 "/service_worker/worker.js"));
873 base::RunLoop activate_run_loop;
874 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
875 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
876 base::Bind(&self::ActivateOnIOThread, this,
877 activate_run_loop.QuitClosure(), &status));
878 activate_run_loop.Run();
879 EXPECT_EQ(SERVICE_WORKER_OK, status);
880 ASSERT_TRUE(registration_->active_version());
881
882 // Give the version a controllee.
883 RunOnIOThread(base::Bind(&self::AddControlleeOnIOThread, this));
884
885 // Add a non-existent resource to the version.
886 std::vector<ServiceWorkerDatabase::ResourceRecord> records;
887 records.push_back(
888 ServiceWorkerDatabase::ResourceRecord(30, version_->script_url(), 100));
889 version_->script_cache_map()->SetResources(records);
890
891 // Make a waiting version and store it.
892 RunOnIOThread(base::Bind(&self::AddWaitingWorkerOnIOThread, this,
893 "/service_worker/worker.js"));
894 StoreRegistration(registration_->waiting_version()->version_id(),
895 SERVICE_WORKER_OK);
896
897 // Start the broken worker. We'll fail to read from disk and the worker should
898 // be doomed.
899 StopWorker(SERVICE_WORKER_OK); // in case it's already running
900 StartWorker(SERVICE_WORKER_ERROR_DISK_CACHE);
901 EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version_->status());
902
903 // The registration should still be in storage since the waiting worker was
904 // the stored one.
905 RunOnIOThread(base::Bind(&self::RemoveLiveRegistrationOnIOThread, this,
906 registration_->id()));
907 FindRegistrationForId(registration_->id(),
908 registration_->pattern().GetOrigin(),
909 SERVICE_WORKER_OK);
910 }
911
733 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) { 912 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) {
734 InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK); 913 InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
735 } 914 }
736 915
737 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, 916 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
738 InstallWithWaitUntil_Fulfilled) { 917 InstallWithWaitUntil_Fulfilled) {
739 InstallTestHelper("/service_worker/worker_install_fulfilled.js", 918 InstallTestHelper("/service_worker/worker_install_fulfilled.js",
740 SERVICE_WORKER_OK); 919 SERVICE_WORKER_OK);
741 } 920 }
742 921
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
1271 1450
1272 // Start a worker. 1451 // Start a worker.
1273 StartWorker(SERVICE_WORKER_OK); 1452 StartWorker(SERVICE_WORKER_OK);
1274 1453
1275 // Wait for the matadata is stored. This run loop should finish when 1454 // Wait for the matadata is stored. This run loop should finish when
1276 // OnCachedMetadataUpdated() is called. 1455 // OnCachedMetadataUpdated() is called.
1277 cached_metadata_run_loop.Run(); 1456 cached_metadata_run_loop.Run();
1278 1457
1279 // Activate the worker. 1458 // Activate the worker.
1280 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; 1459 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
1281 base::RunLoop acrivate_run_loop; 1460 base::RunLoop activate_run_loop;
1282 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 1461 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
1283 base::Bind(&self::ActivateOnIOThread, this, 1462 base::Bind(&self::ActivateOnIOThread, this,
1284 acrivate_run_loop.QuitClosure(), &status)); 1463 activate_run_loop.QuitClosure(), &status));
1285 acrivate_run_loop.Run(); 1464 activate_run_loop.Run();
1286 ASSERT_EQ(SERVICE_WORKER_OK, status); 1465 ASSERT_EQ(SERVICE_WORKER_OK, status);
1287 // Stop the worker. 1466 // Stop the worker.
1288 StopWorker(SERVICE_WORKER_OK); 1467 StopWorker(SERVICE_WORKER_OK);
1289 // Restart the worker. 1468 // Restart the worker.
1290 StartWorker(SERVICE_WORKER_OK); 1469 StartWorker(SERVICE_WORKER_OK);
1291 // Stop the worker. 1470 // Stop the worker.
1292 StopWorker(SERVICE_WORKER_OK); 1471 StopWorker(SERVICE_WORKER_OK);
1293 } 1472 }
1294 1473
1295 } // namespace content 1474 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/browser/service_worker/service_worker_read_from_cache_job.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698