Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_storage.h" | |
| 6 | |
| 7 #include "base/logging.h" | 5 #include "base/logging.h" |
| 8 #include "base/message_loop/message_loop.h" | 6 #include "base/message_loop/message_loop.h" |
| 9 #include "base/run_loop.h" | 7 #include "base/run_loop.h" |
| 10 #include "content/browser/browser_thread_impl.h" | 8 #include "content/browser/browser_thread_impl.h" |
| 11 #include "content/browser/service_worker/service_worker_context_core.h" | 9 #include "content/browser/service_worker/service_worker_context_core.h" |
| 10 #include "content/browser/service_worker/service_worker_disk_cache.h" | |
| 12 #include "content/browser/service_worker/service_worker_registration.h" | 11 #include "content/browser/service_worker/service_worker_registration.h" |
| 12 #include "content/browser/service_worker/service_worker_storage.h" | |
| 13 #include "content/browser/service_worker/service_worker_version.h" | 13 #include "content/browser/service_worker/service_worker_version.h" |
| 14 #include "content/public/test/test_browser_thread_bundle.h" | 14 #include "content/public/test/test_browser_thread_bundle.h" |
| 15 #include "net/base/io_buffer.h" | |
| 16 #include "net/base/net_errors.h" | |
| 17 #include "net/http/http_response_headers.h" | |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 19 |
| 20 using net::IOBuffer; | |
| 21 using net::WrappedIOBuffer; | |
| 22 | |
| 17 namespace content { | 23 namespace content { |
| 18 | 24 |
| 19 namespace { | 25 namespace { |
| 20 | 26 |
| 27 typedef ServiceWorkerDatabase::RegistrationData RegistrationData; | |
| 28 typedef ServiceWorkerDatabase::ResourceRecord ResourceRecord; | |
| 29 | |
| 21 void StatusCallback(bool* was_called, | 30 void StatusCallback(bool* was_called, |
| 22 ServiceWorkerStatusCode* result, | 31 ServiceWorkerStatusCode* result, |
| 23 ServiceWorkerStatusCode status) { | 32 ServiceWorkerStatusCode status) { |
| 24 *was_called = true; | 33 *was_called = true; |
| 25 *result = status; | 34 *result = status; |
| 26 } | 35 } |
| 27 | 36 |
| 28 ServiceWorkerStorage::StatusCallback MakeStatusCallback( | 37 ServiceWorkerStorage::StatusCallback MakeStatusCallback( |
| 29 bool* was_called, | 38 bool* was_called, |
| 30 ServiceWorkerStatusCode* result) { | 39 ServiceWorkerStatusCode* result) { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 56 *was_called = true; | 65 *was_called = true; |
| 57 *all_out = all; | 66 *all_out = all; |
| 58 } | 67 } |
| 59 | 68 |
| 60 ServiceWorkerStorage::GetAllRegistrationInfosCallback MakeGetAllCallback( | 69 ServiceWorkerStorage::GetAllRegistrationInfosCallback MakeGetAllCallback( |
| 61 bool* was_called, | 70 bool* was_called, |
| 62 std::vector<ServiceWorkerRegistrationInfo>* all) { | 71 std::vector<ServiceWorkerRegistrationInfo>* all) { |
| 63 return base::Bind(&GetAllCallback, was_called, all); | 72 return base::Bind(&GetAllCallback, was_called, all); |
| 64 } | 73 } |
| 65 | 74 |
| 75 void NoopCallback() { | |
|
nhiroki
2014/05/22 01:20:13
You may want to use DoNothing() in bind_helpers.h.
michaeln
2014/05/22 02:02:37
Done, ty!
| |
| 76 } | |
| 77 | |
| 78 void OnIOComplete(int* rv_out, int rv) { | |
| 79 *rv_out = rv; | |
| 80 } | |
| 81 | |
| 82 void WriteBasicResponse(ServiceWorkerStorage* storage, int64 id) { | |
| 83 scoped_ptr<ServiceWorkerResponseWriter> writer = | |
| 84 storage->CreateResponseWriter(id); | |
| 85 | |
| 86 const char kHttpHeaders[] = | |
| 87 "HTTP/1.0 200 HONKYDORY\0Content-Length: 6\0\0"; | |
| 88 const char kHttpBody[] = "Hello\0"; | |
| 89 scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody)); | |
| 90 std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders)); | |
| 91 scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo); | |
| 92 info->request_time = base::Time::Now(); | |
| 93 info->response_time = base::Time::Now(); | |
| 94 info->was_cached = false; | |
| 95 info->headers = new net::HttpResponseHeaders(raw_headers); | |
| 96 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer = | |
| 97 new HttpResponseInfoIOBuffer(info.release()); | |
| 98 | |
| 99 int rv = -1234; | |
| 100 writer->WriteInfo(info_buffer, base::Bind(&OnIOComplete, &rv)); | |
| 101 base::RunLoop().RunUntilIdle(); | |
| 102 EXPECT_LT(0, rv); | |
| 103 | |
| 104 rv = -1234; | |
| 105 writer->WriteData(body, arraysize(kHttpBody), | |
| 106 base::Bind(&OnIOComplete, &rv)); | |
|
nhiroki
2014/05/22 01:20:13
indent-nit.
michaeln
2014/05/22 02:02:37
Done.
| |
| 107 base::RunLoop().RunUntilIdle(); | |
| 108 EXPECT_EQ(arraysize(kHttpBody), rv); | |
| 109 } | |
| 110 | |
| 111 bool VerifyBasicResponse(ServiceWorkerStorage* storage, int64 id, | |
| 112 bool expected_positive_result) { | |
| 113 const char kExpectedHttpBody[] = "Hello\0"; | |
| 114 scoped_ptr<ServiceWorkerResponseReader> reader = | |
| 115 storage->CreateResponseReader(id); | |
| 116 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer = | |
| 117 new HttpResponseInfoIOBuffer(); | |
| 118 int rv = -1234; | |
| 119 reader->ReadInfo(info_buffer, base::Bind(&OnIOComplete, &rv)); | |
| 120 base::RunLoop().RunUntilIdle(); | |
| 121 if (expected_positive_result) { | |
| 122 EXPECT_LT(0, rv); | |
| 123 } | |
|
nhiroki
2014/05/22 01:20:13
nit: you can remove "{}"
michaeln
2014/05/22 02:02:37
Done. (mysterious macro w/o brackets spooks me tho
nhiroki
2014/05/22 03:15:34
Ah... sorry, I unthoughtfully commented this after
| |
| 124 if (rv <= 0) | |
| 125 return false; | |
| 126 | |
| 127 const int kBigEnough = 512; | |
| 128 scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough); | |
| 129 rv = -1234; | |
| 130 reader->ReadData(buffer, kBigEnough, base::Bind(&OnIOComplete, &rv)); | |
| 131 base::RunLoop().RunUntilIdle(); | |
| 132 EXPECT_EQ(arraysize(kExpectedHttpBody), rv); | |
| 133 if (rv <= 0) | |
| 134 return false; | |
| 135 | |
| 136 bool status_match = | |
| 137 std::string("HONKYDORY") == | |
| 138 info_buffer->http_info->headers->GetStatusText(); | |
| 139 bool data_match = | |
| 140 std::string(kExpectedHttpBody) == std::string(buffer->data()); | |
| 141 | |
| 142 EXPECT_TRUE(status_match); | |
| 143 EXPECT_TRUE(data_match); | |
| 144 return status_match && data_match; | |
| 145 } | |
| 146 | |
| 66 } // namespace | 147 } // namespace |
| 67 | 148 |
| 68 class ServiceWorkerStorageTest : public testing::Test { | 149 class ServiceWorkerStorageTest : public testing::Test { |
| 69 public: | 150 public: |
| 70 ServiceWorkerStorageTest() | 151 ServiceWorkerStorageTest() |
| 71 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) { | 152 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) { |
| 72 } | 153 } |
| 73 | 154 |
| 74 virtual void SetUp() OVERRIDE { | 155 virtual void SetUp() OVERRIDE { |
| 75 context_.reset(new ServiceWorkerContextCore( | 156 context_.reset(new ServiceWorkerContextCore( |
| 76 base::FilePath(), | 157 base::FilePath(), |
| 77 base::MessageLoopProxy::current(), | 158 base::MessageLoopProxy::current(), |
| 78 base::MessageLoopProxy::current(), | 159 base::MessageLoopProxy::current(), |
| 79 NULL, | 160 NULL, |
| 80 NULL, | 161 NULL, |
| 81 scoped_ptr<ServiceWorkerProcessManager>())); | 162 scoped_ptr<ServiceWorkerProcessManager>())); |
| 82 context_ptr_ = context_->AsWeakPtr(); | 163 context_ptr_ = context_->AsWeakPtr(); |
| 83 } | 164 } |
| 84 | 165 |
| 85 virtual void TearDown() OVERRIDE { | 166 virtual void TearDown() OVERRIDE { |
| 86 context_.reset(); | 167 context_.reset(); |
| 87 } | 168 } |
| 88 | 169 |
| 89 ServiceWorkerStorage* storage() { return context_->storage(); } | 170 ServiceWorkerStorage* storage() { return context_->storage(); } |
| 90 | 171 |
| 172 // A static class method for friendliness. | |
| 173 static void VerifyPurgeableListStatusCallback( | |
| 174 ServiceWorkerDatabase* database, | |
| 175 std::set<int64> *purgeable_ids, | |
| 176 bool* was_called, | |
| 177 ServiceWorkerStatusCode* result, | |
| 178 ServiceWorkerStatusCode status) { | |
| 179 *was_called = true; | |
| 180 *result = status; | |
| 181 database->GetPurgeableResourceIds(purgeable_ids); | |
|
nhiroki
2014/05/22 01:20:13
Can you check a status code of GetPurgeableResourc
michaeln
2014/05/22 02:02:37
Done.
| |
| 182 } | |
| 183 | |
| 91 protected: | 184 protected: |
| 92 scoped_ptr<ServiceWorkerContextCore> context_; | 185 scoped_ptr<ServiceWorkerContextCore> context_; |
| 93 base::WeakPtr<ServiceWorkerContextCore> context_ptr_; | 186 base::WeakPtr<ServiceWorkerContextCore> context_ptr_; |
| 94 TestBrowserThreadBundle browser_thread_bundle_; | 187 TestBrowserThreadBundle browser_thread_bundle_; |
| 95 }; | 188 }; |
| 96 | 189 |
| 97 TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) { | 190 TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) { |
| 98 const GURL kScope("http://www.test.com/scope/*"); | 191 const GURL kScope("http://www.test.com/scope/*"); |
| 99 const GURL kScript("http://www.test.com/script.js"); | 192 const GURL kScript("http://www.test.com/script.js"); |
| 100 const GURL kDocumentUrl("http://www.test.com/scope/document.html"); | 193 const GURL kDocumentUrl("http://www.test.com/scope/document.html"); |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 435 was_called = false; | 528 was_called = false; |
| 436 | 529 |
| 437 storage()->GetAllRegistrations( | 530 storage()->GetAllRegistrations( |
| 438 MakeGetAllCallback(&was_called, &all_registrations)); | 531 MakeGetAllCallback(&was_called, &all_registrations)); |
| 439 base::RunLoop().RunUntilIdle(); | 532 base::RunLoop().RunUntilIdle(); |
| 440 ASSERT_TRUE(was_called); | 533 ASSERT_TRUE(was_called); |
| 441 EXPECT_TRUE(all_registrations.empty()); | 534 EXPECT_TRUE(all_registrations.empty()); |
| 442 was_called = false; | 535 was_called = false; |
| 443 } | 536 } |
| 444 | 537 |
| 538 TEST_F(ServiceWorkerStorageTest, ResourceIdsAreStoredAndPurged) { | |
| 539 storage()->LazyInitialize(base::Bind(&NoopCallback)); | |
| 540 base::RunLoop().RunUntilIdle(); | |
| 541 const GURL kScope("http://www.test.com/scope/*"); | |
|
nhiroki
2014/05/22 01:20:13
"www.test.com" seems to be a domain for an actual
michaeln
2014/05/22 02:02:37
does it matter? no network traffic is generated by
nhiroki
2014/05/22 03:15:34
Yes, this doesn't generate any traffic.
Probably
| |
| 542 const GURL kScript("http://www.test.com/script.js"); | |
| 543 const GURL kImport("http://www.test.com/import.js"); | |
| 544 const GURL kDocumentUrl("http://www.test.com/scope/document.html"); | |
| 545 const int64 kRegistrationId = storage()->NewRegistrationId(); | |
| 546 const int64 kVersionId = storage()->NewVersionId(); | |
| 547 const int64 kResourceId1 = storage()->NewResourceId(); | |
| 548 const int64 kResourceId2 = storage()->NewResourceId(); | |
| 549 | |
| 550 // Cons up a new registration+version with two script resources. | |
| 551 RegistrationData data; | |
| 552 data.registration_id = kRegistrationId; | |
| 553 data.scope = kScope; | |
| 554 data.script = kScript; | |
| 555 data.version_id = kVersionId; | |
| 556 data.is_active = false; | |
| 557 std::vector<ResourceRecord> resources; | |
| 558 resources.push_back(ResourceRecord(kResourceId1, kScript)); | |
| 559 resources.push_back(ResourceRecord(kResourceId2, kImport)); | |
| 560 scoped_refptr<ServiceWorkerRegistration> registration = | |
| 561 storage()->GetOrCreateRegistration(data, resources); | |
| 562 registration->pending_version()->SetStatus(ServiceWorkerVersion::NEW); | |
| 563 | |
| 564 // Add the resources ids to the uncommitted list. | |
| 565 std::set<int64> resource_ids; | |
| 566 resource_ids.insert(kResourceId1); | |
| 567 resource_ids.insert(kResourceId2); | |
| 568 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, | |
| 569 storage()->database_->WriteUncommittedResourceIds(resource_ids)); | |
| 570 | |
| 571 // And dump something in the disk cache for them. | |
| 572 WriteBasicResponse(storage(), kResourceId1); | |
| 573 WriteBasicResponse(storage(), kResourceId2); | |
| 574 EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId1, true)); | |
| 575 EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId2, true)); | |
| 576 | |
| 577 // Storing the registration/version should take the resources ids out | |
| 578 // of the uncommitted list. | |
| 579 bool was_called = false; | |
| 580 ServiceWorkerStatusCode result = | |
| 581 ServiceWorkerStatusCode::SERVICE_WORKER_ERROR_FAILED; | |
| 582 storage()->StoreRegistration(registration, registration->pending_version(), | |
| 583 MakeStatusCallback(&was_called, &result)); | |
| 584 base::RunLoop().RunUntilIdle(); | |
| 585 ASSERT_TRUE(was_called); | |
| 586 EXPECT_EQ(ServiceWorkerStatusCode::SERVICE_WORKER_OK, result); | |
| 587 std::set<int64> verify_ids; | |
| 588 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, | |
| 589 storage()->database_->GetUncommittedResourceIds(&verify_ids)); | |
| 590 EXPECT_TRUE(verify_ids.empty()); | |
| 591 | |
| 592 // Deleting it should result in the resources being added to the | |
| 593 // purgable list and then doomed in the disk cache and removed from | |
|
nhiroki
2014/05/22 01:20:13
nit: s/purgable/purgeable/
michaeln
2014/05/22 02:02:37
Done.
| |
| 594 // that list. | |
| 595 was_called = false; | |
| 596 verify_ids.clear(); | |
| 597 storage()->DeleteRegistration( | |
| 598 registration->id(), kScope.GetOrigin(), | |
| 599 base::Bind(&VerifyPurgeableListStatusCallback, | |
| 600 base::Unretained(storage()->database_.get()), | |
| 601 &verify_ids, | |
| 602 &was_called, &result)); | |
|
nhiroki
2014/05/22 01:20:13
indent-nit.
michaeln
2014/05/22 02:02:37
Done.
| |
| 603 base::RunLoop().RunUntilIdle(); | |
| 604 ASSERT_TRUE(was_called); | |
| 605 EXPECT_EQ(ServiceWorkerStatusCode::SERVICE_WORKER_OK, result); | |
| 606 EXPECT_EQ(2u, verify_ids.size()); | |
| 607 verify_ids.clear(); | |
| 608 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, | |
| 609 storage()->database_->GetPurgeableResourceIds(&verify_ids)); | |
| 610 EXPECT_TRUE(verify_ids.empty()); | |
| 611 | |
| 612 EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId1, false)); | |
| 613 EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId2, false)); | |
| 614 } | |
| 615 | |
| 445 } // namespace content | 616 } // namespace content |
| OLD | NEW |