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 3 // found in the LICENSE file. 4 5 #include <string> 6 7 #include "base/logging.h" 8 #include "base/message_loop/message_loop.h" 9 #include "base/run_loop.h" 10 #include "content/browser/browser_thread_impl.h" 11 #include "content/browser/service_worker/service_worker_context_core.h" 12 #include "content/browser/service_worker/service_worker_disk_cache.h" 13 #include "content/browser/service_worker/service_worker_registration.h" 14 #include "content/browser/service_worker/service_worker_storage.h" 15 #include "content/browser/service_worker/service_worker_version.h" 16 #include "content/common/service_worker/service_worker_status_code.h" 17 #include "content/public/test/test_browser_thread_bundle.h" 18 #include "net/base/io_buffer.h" 19 #include "net/base/net_errors.h" 20 #include "net/http/http_response_headers.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 23 using net::IOBuffer; 24 using net::WrappedIOBuffer; 25 26 namespace content { 27 28 namespace { 29 30 typedef ServiceWorkerDatabase::RegistrationData RegistrationData; 31 typedef ServiceWorkerDatabase::ResourceRecord ResourceRecord; 32 33 void StatusCallback(bool* was_called, 34 ServiceWorkerStatusCode* result, 35 ServiceWorkerStatusCode status) { 36 *was_called = true; 37 *result = status; 38 } 39 40 ServiceWorkerStorage::StatusCallback MakeStatusCallback( 41 bool* was_called, 42 ServiceWorkerStatusCode* result) { 43 return base::Bind(&StatusCallback, was_called, result); 44 } 45 46 void FindCallback( 47 bool* was_called, 48 ServiceWorkerStatusCode* result, 49 scoped_refptr<ServiceWorkerRegistration>* found, 50 ServiceWorkerStatusCode status, 51 const scoped_refptr<ServiceWorkerRegistration>& registration) { 52 *was_called = true; 53 *result = status; 54 *found = registration; 55 } 56 57 ServiceWorkerStorage::FindRegistrationCallback MakeFindCallback( 58 bool* was_called, 59 ServiceWorkerStatusCode* result, 60 scoped_refptr<ServiceWorkerRegistration>* found) { 61 return base::Bind(&FindCallback, was_called, result, found); 62 } 63 64 void GetAllCallback( 65 bool* was_called, 66 std::vector<ServiceWorkerRegistrationInfo>* all_out, 67 const std::vector<ServiceWorkerRegistrationInfo>& all) { 68 *was_called = true; 69 *all_out = all; 70 } 71 72 ServiceWorkerStorage::GetAllRegistrationInfosCallback MakeGetAllCallback( 73 bool* was_called, 74 std::vector<ServiceWorkerRegistrationInfo>* all) { 75 return base::Bind(&GetAllCallback, was_called, all); 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)); 107 base::RunLoop().RunUntilIdle(); 108 EXPECT_EQ(static_cast<int>(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 if (rv <= 0) 124 return false; 125 126 const int kBigEnough = 512; 127 scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough); 128 rv = -1234; 129 reader->ReadData(buffer, kBigEnough, base::Bind(&OnIOComplete, &rv)); 130 base::RunLoop().RunUntilIdle(); 131 EXPECT_EQ(static_cast<int>(arraysize(kExpectedHttpBody)), rv); 132 if (rv <= 0) 133 return false; 134 135 bool status_match = 136 std::string("HONKYDORY") == 137 info_buffer->http_info->headers->GetStatusText(); 138 bool data_match = 139 std::string(kExpectedHttpBody) == std::string(buffer->data()); 140 141 EXPECT_TRUE(status_match); 142 EXPECT_TRUE(data_match); 143 return status_match && data_match; 144 } 145 146 } // namespace 147 148 class ServiceWorkerStorageTest : public testing::Test { 149 public: 150 ServiceWorkerStorageTest() 151 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) { 152 } 153 154 virtual void SetUp() OVERRIDE { 155 context_.reset( 156 new ServiceWorkerContextCore(base::FilePath(), 157 base::MessageLoopProxy::current(), 158 base::MessageLoopProxy::current(), 159 NULL, 160 NULL, 161 NULL)); 162 context_ptr_ = context_->AsWeakPtr(); 163 } 164 165 virtual void TearDown() OVERRIDE { 166 context_.reset(); 167 } 168 169 ServiceWorkerStorage* storage() { return context_->storage(); } 170 171 // A static class method for friendliness. 172 static void VerifyPurgeableListStatusCallback( 173 ServiceWorkerDatabase* database, 174 std::set<int64> *purgeable_ids, 175 bool* was_called, 176 ServiceWorkerStatusCode* result, 177 ServiceWorkerStatusCode status) { 178 *was_called = true; 179 *result = status; 180 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 181 database->GetPurgeableResourceIds(purgeable_ids)); 182 } 183 184 protected: 185 ServiceWorkerStatusCode StoreRegistration( 186 scoped_refptr<ServiceWorkerRegistration> registration, 187 scoped_refptr<ServiceWorkerVersion> version) { 188 bool was_called = false; 189 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED; 190 storage()->StoreRegistration( 191 registration, version, MakeStatusCallback(&was_called, &result)); 192 EXPECT_FALSE(was_called); // always async 193 base::RunLoop().RunUntilIdle(); 194 EXPECT_TRUE(was_called); 195 return result; 196 } 197 198 ServiceWorkerStatusCode DeleteRegistration( 199 int64 registration_id, 200 const GURL& origin) { 201 bool was_called = false; 202 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED; 203 storage()->DeleteRegistration( 204 registration_id, origin, MakeStatusCallback(&was_called, &result)); 205 EXPECT_FALSE(was_called); // always async 206 base::RunLoop().RunUntilIdle(); 207 EXPECT_TRUE(was_called); 208 return result; 209 } 210 211 void GetAllRegistrations( 212 std::vector<ServiceWorkerRegistrationInfo>* registrations) { 213 bool was_called = false; 214 storage()->GetAllRegistrations( 215 MakeGetAllCallback(&was_called, registrations)); 216 EXPECT_FALSE(was_called); // always async 217 base::RunLoop().RunUntilIdle(); 218 EXPECT_TRUE(was_called); 219 } 220 221 ServiceWorkerStatusCode UpdateToActiveState( 222 scoped_refptr<ServiceWorkerRegistration> registration) { 223 bool was_called = false; 224 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED; 225 storage()->UpdateToActiveState( 226 registration, MakeStatusCallback(&was_called, &result)); 227 EXPECT_FALSE(was_called); // always async 228 base::RunLoop().RunUntilIdle(); 229 EXPECT_TRUE(was_called); 230 return result; 231 } 232 233 ServiceWorkerStatusCode FindRegistrationForDocument( 234 const GURL& document_url, 235 scoped_refptr<ServiceWorkerRegistration>* registration) { 236 bool was_called = false; 237 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED; 238 storage()->FindRegistrationForDocument( 239 document_url, MakeFindCallback(&was_called, &result, registration)); 240 base::RunLoop().RunUntilIdle(); 241 EXPECT_TRUE(was_called); 242 return result; 243 } 244 245 ServiceWorkerStatusCode FindRegistrationForPattern( 246 const GURL& scope, 247 scoped_refptr<ServiceWorkerRegistration>* registration) { 248 bool was_called = false; 249 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED; 250 storage()->FindRegistrationForPattern( 251 scope, MakeFindCallback(&was_called, &result, registration)); 252 EXPECT_FALSE(was_called); // always async 253 base::RunLoop().RunUntilIdle(); 254 EXPECT_TRUE(was_called); 255 return result; 256 } 257 258 ServiceWorkerStatusCode FindRegistrationForId( 259 int64 registration_id, 260 const GURL& origin, 261 scoped_refptr<ServiceWorkerRegistration>* registration) { 262 bool was_called = false; 263 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED; 264 storage()->FindRegistrationForId( 265 registration_id, origin, 266 MakeFindCallback(&was_called, &result, registration)); 267 base::RunLoop().RunUntilIdle(); 268 EXPECT_TRUE(was_called); 269 return result; 270 } 271 272 scoped_ptr<ServiceWorkerContextCore> context_; 273 base::WeakPtr<ServiceWorkerContextCore> context_ptr_; 274 TestBrowserThreadBundle browser_thread_bundle_; 275 }; 276 277 TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) { 278 const GURL kScope("http://www.test.not/scope/*"); 279 const GURL kScript("http://www.test.not/script.js"); 280 const GURL kDocumentUrl("http://www.test.not/scope/document.html"); 281 const int64 kRegistrationId = 0; 282 const int64 kVersionId = 0; 283 284 scoped_refptr<ServiceWorkerRegistration> found_registration; 285 286 // We shouldn't find anything without having stored anything. 287 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, 288 FindRegistrationForDocument(kDocumentUrl, &found_registration)); 289 EXPECT_FALSE(found_registration); 290 291 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, 292 FindRegistrationForPattern(kScope, &found_registration)); 293 EXPECT_FALSE(found_registration); 294 295 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, 296 FindRegistrationForId( 297 kRegistrationId, kScope.GetOrigin(), &found_registration)); 298 EXPECT_FALSE(found_registration); 299 300 // Store something. 301 scoped_refptr<ServiceWorkerRegistration> live_registration = 302 new ServiceWorkerRegistration( 303 kScope, kScript, kRegistrationId, context_ptr_); 304 scoped_refptr<ServiceWorkerVersion> live_version = 305 new ServiceWorkerVersion( 306 live_registration, kVersionId, context_ptr_); 307 live_version->SetStatus(ServiceWorkerVersion::INSTALLED); 308 live_registration->set_waiting_version(live_version); 309 EXPECT_EQ(SERVICE_WORKER_OK, 310 StoreRegistration(live_registration, live_version)); 311 312 // Now we should find it and get the live ptr back immediately. 313 EXPECT_EQ(SERVICE_WORKER_OK, 314 FindRegistrationForDocument(kDocumentUrl, &found_registration)); 315 EXPECT_EQ(live_registration, found_registration); 316 found_registration = NULL; 317 318 // But FindRegistrationForPattern is always async. 319 EXPECT_EQ(SERVICE_WORKER_OK, 320 FindRegistrationForPattern(kScope, &found_registration)); 321 EXPECT_EQ(live_registration, found_registration); 322 found_registration = NULL; 323 324 // Can be found by id too. 325 EXPECT_EQ(SERVICE_WORKER_OK, 326 FindRegistrationForId( 327 kRegistrationId, kScope.GetOrigin(), &found_registration)); 328 ASSERT_TRUE(found_registration); 329 EXPECT_EQ(kRegistrationId, found_registration->id()); 330 EXPECT_EQ(live_registration, found_registration); 331 found_registration = NULL; 332 333 // Drop the live registration, but keep the version live. 334 live_registration = NULL; 335 336 // Now FindRegistrationForDocument should be async. 337 EXPECT_EQ(SERVICE_WORKER_OK, 338 FindRegistrationForDocument(kDocumentUrl, &found_registration)); 339 ASSERT_TRUE(found_registration); 340 EXPECT_EQ(kRegistrationId, found_registration->id()); 341 EXPECT_TRUE(found_registration->HasOneRef()); 342 EXPECT_EQ(live_version, found_registration->waiting_version()); 343 found_registration = NULL; 344 345 // Drop the live version too. 346 live_version = NULL; 347 348 // And FindRegistrationForPattern is always async. 349 EXPECT_EQ(SERVICE_WORKER_OK, 350 FindRegistrationForPattern(kScope, &found_registration)); 351 ASSERT_TRUE(found_registration); 352 EXPECT_EQ(kRegistrationId, found_registration->id()); 353 EXPECT_TRUE(found_registration->HasOneRef()); 354 EXPECT_FALSE(found_registration->active_version()); 355 ASSERT_TRUE(found_registration->waiting_version()); 356 EXPECT_EQ(ServiceWorkerVersion::INSTALLED, 357 found_registration->waiting_version()->status()); 358 359 // Update to active. 360 scoped_refptr<ServiceWorkerVersion> temp_version = 361 found_registration->waiting_version(); 362 found_registration->set_waiting_version(NULL); 363 temp_version->SetStatus(ServiceWorkerVersion::ACTIVE); 364 found_registration->set_active_version(temp_version); 365 temp_version = NULL; 366 EXPECT_EQ(SERVICE_WORKER_OK, UpdateToActiveState(found_registration)); 367 found_registration = NULL; 368 369 // Trying to update a unstored registration to active should fail. 370 scoped_refptr<ServiceWorkerRegistration> unstored_registration = 371 new ServiceWorkerRegistration( 372 kScope, kScript, kRegistrationId + 1, context_ptr_); 373 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, 374 UpdateToActiveState(unstored_registration)); 375 unstored_registration = NULL; 376 377 // The Find methods should return a registration with an active version. 378 EXPECT_EQ(SERVICE_WORKER_OK, 379 FindRegistrationForDocument(kDocumentUrl, &found_registration)); 380 ASSERT_TRUE(found_registration); 381 EXPECT_EQ(kRegistrationId, found_registration->id()); 382 EXPECT_TRUE(found_registration->HasOneRef()); 383 EXPECT_FALSE(found_registration->waiting_version()); 384 ASSERT_TRUE(found_registration->active_version()); 385 EXPECT_EQ(ServiceWorkerVersion::ACTIVE, 386 found_registration->active_version()->status()); 387 388 // Delete from storage but with a instance still live. 389 EXPECT_TRUE(context_->GetLiveVersion(kRegistrationId)); 390 EXPECT_EQ(SERVICE_WORKER_OK, 391 DeleteRegistration(kRegistrationId, kScope.GetOrigin())); 392 EXPECT_TRUE(context_->GetLiveVersion(kRegistrationId)); 393 394 // Should no longer be found. 395 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, 396 FindRegistrationForId( 397 kRegistrationId, kScope.GetOrigin(), &found_registration)); 398 EXPECT_FALSE(found_registration); 399 400 // Deleting an unstored registration should succeed. 401 EXPECT_EQ(SERVICE_WORKER_OK, 402 DeleteRegistration(kRegistrationId + 1, kScope.GetOrigin())); 403 } 404 405 TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) { 406 const GURL kScope("http://www.test.not/scope/*"); 407 const GURL kScript("http://www.test.not/script.js"); 408 const GURL kDocumentUrl("http://www.test.not/scope/document.html"); 409 const int64 kRegistrationId = 0; 410 const int64 kVersionId = 0; 411 412 scoped_refptr<ServiceWorkerRegistration> found_registration; 413 414 // Create an unstored registration. 415 scoped_refptr<ServiceWorkerRegistration> live_registration = 416 new ServiceWorkerRegistration( 417 kScope, kScript, kRegistrationId, context_ptr_); 418 scoped_refptr<ServiceWorkerVersion> live_version = 419 new ServiceWorkerVersion( 420 live_registration, kVersionId, context_ptr_); 421 live_version->SetStatus(ServiceWorkerVersion::INSTALLING); 422 live_registration->set_waiting_version(live_version); 423 424 // Should not be findable, including by GetAllRegistrations. 425 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, 426 FindRegistrationForId( 427 kRegistrationId, kScope.GetOrigin(), &found_registration)); 428 EXPECT_FALSE(found_registration); 429 430 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, 431 FindRegistrationForDocument(kDocumentUrl, &found_registration)); 432 EXPECT_FALSE(found_registration); 433 434 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, 435 FindRegistrationForPattern(kScope, &found_registration)); 436 EXPECT_FALSE(found_registration); 437 438 std::vector<ServiceWorkerRegistrationInfo> all_registrations; 439 GetAllRegistrations(&all_registrations); 440 EXPECT_TRUE(all_registrations.empty()); 441 442 // Notify storage of it being installed. 443 storage()->NotifyInstallingRegistration(live_registration); 444 445 // Now should be findable. 446 EXPECT_EQ(SERVICE_WORKER_OK, 447 FindRegistrationForId( 448 kRegistrationId, kScope.GetOrigin(), &found_registration)); 449 EXPECT_EQ(live_registration, found_registration); 450 found_registration = NULL; 451 452 EXPECT_EQ(SERVICE_WORKER_OK, 453 FindRegistrationForDocument(kDocumentUrl, &found_registration)); 454 EXPECT_EQ(live_registration, found_registration); 455 found_registration = NULL; 456 457 EXPECT_EQ(SERVICE_WORKER_OK, 458 FindRegistrationForPattern(kScope, &found_registration)); 459 EXPECT_EQ(live_registration, found_registration); 460 found_registration = NULL; 461 462 GetAllRegistrations(&all_registrations); 463 EXPECT_EQ(1u, all_registrations.size()); 464 all_registrations.clear(); 465 466 // Notify storage of installation no longer happening. 467 storage()->NotifyDoneInstallingRegistration( 468 live_registration, NULL, SERVICE_WORKER_OK); 469 470 // Once again, should not be findable. 471 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, 472 FindRegistrationForId( 473 kRegistrationId, kScope.GetOrigin(), &found_registration)); 474 EXPECT_FALSE(found_registration); 475 476 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, 477 FindRegistrationForDocument(kDocumentUrl, &found_registration)); 478 EXPECT_FALSE(found_registration); 479 480 EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, 481 FindRegistrationForPattern(kScope, &found_registration)); 482 EXPECT_FALSE(found_registration); 483 484 GetAllRegistrations(&all_registrations); 485 EXPECT_TRUE(all_registrations.empty()); 486 } 487 488 TEST_F(ServiceWorkerStorageTest, ResourceIdsAreStoredAndPurged) { 489 storage()->LazyInitialize(base::Bind(&base::DoNothing)); 490 base::RunLoop().RunUntilIdle(); 491 const GURL kScope("http://www.test.not/scope/*"); 492 const GURL kScript("http://www.test.not/script.js"); 493 const GURL kImport("http://www.test.not/import.js"); 494 const GURL kDocumentUrl("http://www.test.not/scope/document.html"); 495 const int64 kRegistrationId = storage()->NewRegistrationId(); 496 const int64 kVersionId = storage()->NewVersionId(); 497 const int64 kResourceId1 = storage()->NewResourceId(); 498 const int64 kResourceId2 = storage()->NewResourceId(); 499 500 // Cons up a new registration+version with two script resources. 501 RegistrationData data; 502 data.registration_id = kRegistrationId; 503 data.scope = kScope; 504 data.script = kScript; 505 data.version_id = kVersionId; 506 data.is_active = false; 507 std::vector<ResourceRecord> resources; 508 resources.push_back(ResourceRecord(kResourceId1, kScript)); 509 resources.push_back(ResourceRecord(kResourceId2, kImport)); 510 scoped_refptr<ServiceWorkerRegistration> registration = 511 storage()->GetOrCreateRegistration(data, resources); 512 registration->waiting_version()->SetStatus(ServiceWorkerVersion::NEW); 513 514 // Add the resources ids to the uncommitted list. 515 std::set<int64> resource_ids; 516 resource_ids.insert(kResourceId1); 517 resource_ids.insert(kResourceId2); 518 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 519 storage()->database_->WriteUncommittedResourceIds(resource_ids)); 520 521 // And dump something in the disk cache for them. 522 WriteBasicResponse(storage(), kResourceId1); 523 WriteBasicResponse(storage(), kResourceId2); 524 EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId1, true)); 525 EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId2, true)); 526 527 // Storing the registration/version should take the resources ids out 528 // of the uncommitted list. 529 EXPECT_EQ(SERVICE_WORKER_OK, 530 StoreRegistration(registration, registration->waiting_version())); 531 std::set<int64> verify_ids; 532 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 533 storage()->database_->GetUncommittedResourceIds(&verify_ids)); 534 EXPECT_TRUE(verify_ids.empty()); 535 536 // Deleting it should result in the resources being added to the 537 // purgeable list and then doomed in the disk cache and removed from 538 // that list. 539 bool was_called = false; 540 ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED; 541 verify_ids.clear(); 542 storage()->DeleteRegistration( 543 registration->id(), kScope.GetOrigin(), 544 base::Bind(&VerifyPurgeableListStatusCallback, 545 base::Unretained(storage()->database_.get()), 546 &verify_ids, &was_called, &result)); 547 base::RunLoop().RunUntilIdle(); 548 ASSERT_TRUE(was_called); 549 EXPECT_EQ(SERVICE_WORKER_OK, result); 550 EXPECT_EQ(2u, verify_ids.size()); 551 verify_ids.clear(); 552 EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, 553 storage()->database_->GetPurgeableResourceIds(&verify_ids)); 554 EXPECT_TRUE(verify_ids.empty()); 555 556 EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId1, false)); 557 EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId2, false)); 558 } 559 560 TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) { 561 const GURL kDocumentUrl("http://www.example.com/scope/foo"); 562 scoped_refptr<ServiceWorkerRegistration> found_registration; 563 564 // Registration for "/scope/*". 565 const GURL kScope1("http://www.example.com/scope/*"); 566 const GURL kScript1("http://www.example.com/script1.js"); 567 const int64 kRegistrationId1 = 1; 568 const int64 kVersionId1 = 1; 569 scoped_refptr<ServiceWorkerRegistration> live_registration1 = 570 new ServiceWorkerRegistration( 571 kScope1, kScript1, kRegistrationId1, context_ptr_); 572 scoped_refptr<ServiceWorkerVersion> live_version1 = 573 new ServiceWorkerVersion( 574 live_registration1, kVersionId1, context_ptr_); 575 live_version1->SetStatus(ServiceWorkerVersion::INSTALLED); 576 live_registration1->set_waiting_version(live_version1); 577 578 // Registration for "/scope/foo*". 579 const GURL kScope2("http://www.example.com/scope/foo*"); 580 const GURL kScript2("http://www.example.com/script2.js"); 581 const int64 kRegistrationId2 = 2; 582 const int64 kVersionId2 = 2; 583 scoped_refptr<ServiceWorkerRegistration> live_registration2 = 584 new ServiceWorkerRegistration( 585 kScope2, kScript2, kRegistrationId2, context_ptr_); 586 scoped_refptr<ServiceWorkerVersion> live_version2 = 587 new ServiceWorkerVersion( 588 live_registration2, kVersionId2, context_ptr_); 589 live_version2->SetStatus(ServiceWorkerVersion::INSTALLED); 590 live_registration2->set_waiting_version(live_version2); 591 592 // Registration for "/scope/foo". 593 const GURL kScope3("http://www.example.com/scope/foo"); 594 const GURL kScript3("http://www.example.com/script3.js"); 595 const int64 kRegistrationId3 = 3; 596 const int64 kVersionId3 = 3; 597 scoped_refptr<ServiceWorkerRegistration> live_registration3 = 598 new ServiceWorkerRegistration( 599 kScope3, kScript3, kRegistrationId3, context_ptr_); 600 scoped_refptr<ServiceWorkerVersion> live_version3 = 601 new ServiceWorkerVersion( 602 live_registration3, kVersionId3, context_ptr_); 603 live_version3->SetStatus(ServiceWorkerVersion::INSTALLED); 604 live_registration3->set_waiting_version(live_version3); 605 606 // Notify storage of they being installed. 607 storage()->NotifyInstallingRegistration(live_registration1); 608 storage()->NotifyInstallingRegistration(live_registration2); 609 storage()->NotifyInstallingRegistration(live_registration3); 610 611 // Find a registration among installing ones. 612 EXPECT_EQ(SERVICE_WORKER_OK, 613 FindRegistrationForDocument(kDocumentUrl, &found_registration)); 614 EXPECT_EQ(live_registration2, found_registration); 615 found_registration = NULL; 616 617 // Store registrations. 618 EXPECT_EQ(SERVICE_WORKER_OK, 619 StoreRegistration(live_registration1, live_version1)); 620 EXPECT_EQ(SERVICE_WORKER_OK, 621 StoreRegistration(live_registration2, live_version2)); 622 EXPECT_EQ(SERVICE_WORKER_OK, 623 StoreRegistration(live_registration3, live_version3)); 624 625 // Notify storage of installations no longer happening. 626 storage()->NotifyDoneInstallingRegistration( 627 live_registration1, NULL, SERVICE_WORKER_OK); 628 storage()->NotifyDoneInstallingRegistration( 629 live_registration2, NULL, SERVICE_WORKER_OK); 630 storage()->NotifyDoneInstallingRegistration( 631 live_registration3, NULL, SERVICE_WORKER_OK); 632 633 // Find a registration among installed ones. 634 EXPECT_EQ(SERVICE_WORKER_OK, 635 FindRegistrationForDocument(kDocumentUrl, &found_registration)); 636 EXPECT_EQ(live_registration2, found_registration); 637 } 638 639 } // namespace content 640