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 3 // found in the LICENSE file. 4 5 #include "content/browser/appcache/appcache.h" 6 #include "content/browser/appcache/appcache_host.h" 7 #include "content/browser/appcache/mock_appcache_service.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 10 namespace content { 11 12 namespace { 13 14 class MockAppCacheFrontend : public AppCacheFrontend { 15 public: 16 virtual void OnCacheSelected(int host_id, const AppCacheInfo& info) OVERRIDE { 17 } 18 virtual void OnStatusChanged(const std::vector<int>& host_ids, 19 AppCacheStatus status) OVERRIDE {} 20 virtual void OnEventRaised(const std::vector<int>& host_ids, 21 AppCacheEventID event_id) OVERRIDE {} 22 virtual void OnProgressEventRaised( 23 const std::vector<int>& host_ids, 24 const GURL& url, 25 int num_total, int num_complete) OVERRIDE {} 26 virtual void OnErrorEventRaised( 27 const std::vector<int>& host_ids, 28 const AppCacheErrorDetails& details) OVERRIDE {} 29 virtual void OnLogMessage(int host_id, AppCacheLogLevel log_level, 30 const std::string& message) OVERRIDE {} 31 virtual void OnContentBlocked( 32 int host_id, const GURL& manifest_url) OVERRIDE {} 33 }; 34 35 } // namespace 36 37 class AppCacheTest : public testing::Test { 38 }; 39 40 TEST(AppCacheTest, CleanupUnusedCache) { 41 MockAppCacheService service; 42 MockAppCacheFrontend frontend; 43 scoped_refptr<AppCache> cache(new AppCache(service.storage(), 111)); 44 cache->set_complete(true); 45 scoped_refptr<AppCacheGroup> group( 46 new AppCacheGroup(service.storage(), GURL("http://blah/manifest"), 111)); 47 group->AddCache(cache.get()); 48 49 AppCacheHost host1(1, &frontend, &service); 50 AppCacheHost host2(2, &frontend, &service); 51 52 host1.AssociateCompleteCache(cache.get()); 53 host2.AssociateCompleteCache(cache.get()); 54 55 host1.AssociateNoCache(GURL()); 56 host2.AssociateNoCache(GURL()); 57 } 58 59 TEST(AppCacheTest, AddModifyRemoveEntry) { 60 MockAppCacheService service; 61 scoped_refptr<AppCache> cache(new AppCache(service.storage(), 111)); 62 63 EXPECT_TRUE(cache->entries().empty()); 64 EXPECT_EQ(0L, cache->cache_size()); 65 66 const GURL kFooUrl("http://foo.com"); 67 const int64 kFooResponseId = 1; 68 const int64 kFooSize = 100; 69 AppCacheEntry entry1(AppCacheEntry::MASTER, kFooResponseId, kFooSize); 70 cache->AddEntry(kFooUrl, entry1); 71 EXPECT_EQ(entry1.types(), cache->GetEntry(kFooUrl)->types()); 72 EXPECT_EQ(1UL, cache->entries().size()); 73 EXPECT_EQ(kFooSize, cache->cache_size()); 74 75 const GURL kBarUrl("http://bar.com"); 76 const int64 kBarResponseId = 2; 77 const int64 kBarSize = 200; 78 AppCacheEntry entry2(AppCacheEntry::FALLBACK, kBarResponseId, kBarSize); 79 EXPECT_TRUE(cache->AddOrModifyEntry(kBarUrl, entry2)); 80 EXPECT_EQ(entry2.types(), cache->GetEntry(kBarUrl)->types()); 81 EXPECT_EQ(2UL, cache->entries().size()); 82 EXPECT_EQ(kFooSize + kBarSize, cache->cache_size()); 83 84 // Expected to return false when an existing entry is modified. 85 AppCacheEntry entry3(AppCacheEntry::EXPLICIT); 86 EXPECT_FALSE(cache->AddOrModifyEntry(kFooUrl, entry3)); 87 EXPECT_EQ((AppCacheEntry::MASTER | AppCacheEntry::EXPLICIT), 88 cache->GetEntry(kFooUrl)->types()); 89 // Only the type should be modified. 90 EXPECT_EQ(kFooResponseId, cache->GetEntry(kFooUrl)->response_id()); 91 EXPECT_EQ(kFooSize, cache->GetEntry(kFooUrl)->response_size()); 92 EXPECT_EQ(kFooSize + kBarSize, cache->cache_size()); 93 94 EXPECT_EQ(entry2.types(), cache->GetEntry(kBarUrl)->types()); // unchanged 95 96 cache->RemoveEntry(kBarUrl); 97 EXPECT_EQ(kFooSize, cache->cache_size()); 98 cache->RemoveEntry(kFooUrl); 99 EXPECT_EQ(0L, cache->cache_size()); 100 EXPECT_TRUE(cache->entries().empty()); 101 } 102 103 TEST(AppCacheTest, InitializeWithManifest) { 104 MockAppCacheService service; 105 106 scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234)); 107 EXPECT_TRUE(cache->fallback_namespaces_.empty()); 108 EXPECT_TRUE(cache->online_whitelist_namespaces_.empty()); 109 EXPECT_FALSE(cache->online_whitelist_all_); 110 111 AppCacheManifest manifest; 112 manifest.explicit_urls.insert("http://one.com"); 113 manifest.explicit_urls.insert("http://two.com"); 114 manifest.fallback_namespaces.push_back( 115 AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, GURL("http://fb1.com"), 116 GURL("http://fbone.com"), true)); 117 manifest.online_whitelist_namespaces.push_back( 118 AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, GURL("http://w1.com"), 119 GURL(), false)); 120 manifest.online_whitelist_namespaces.push_back( 121 AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, GURL("http://w2.com"), 122 GURL(), false)); 123 manifest.online_whitelist_all = true; 124 125 cache->InitializeWithManifest(&manifest); 126 const std::vector<AppCacheNamespace>& fallbacks = 127 cache->fallback_namespaces_; 128 size_t expected = 1; 129 EXPECT_EQ(expected, fallbacks.size()); 130 EXPECT_EQ(GURL("http://fb1.com"), fallbacks[0].namespace_url); 131 EXPECT_EQ(GURL("http://fbone.com"), fallbacks[0].target_url); 132 EXPECT_TRUE(fallbacks[0].is_pattern); 133 const AppCacheNamespaceVector& whitelist = 134 cache->online_whitelist_namespaces_; 135 expected = 2; 136 EXPECT_EQ(expected, whitelist.size()); 137 EXPECT_EQ(GURL("http://w1.com"), whitelist[0].namespace_url); 138 EXPECT_EQ(GURL("http://w2.com"), whitelist[1].namespace_url); 139 EXPECT_TRUE(cache->online_whitelist_all_); 140 141 // Ensure collections in manifest were taken over by the cache rather than 142 // copied. 143 EXPECT_TRUE(manifest.fallback_namespaces.empty()); 144 EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); 145 } 146 147 TEST(AppCacheTest, FindResponseForRequest) { 148 MockAppCacheService service; 149 150 const GURL kOnlineNamespaceUrl("http://blah/online_namespace"); 151 const GURL kFallbackEntryUrl1("http://blah/fallback_entry1"); 152 const GURL kFallbackNamespaceUrl1("http://blah/fallback_namespace/"); 153 const GURL kFallbackEntryUrl2("http://blah/fallback_entry2"); 154 const GURL kFallbackNamespaceUrl2("http://blah/fallback_namespace/longer"); 155 const GURL kManifestUrl("http://blah/manifest"); 156 const GURL kForeignExplicitEntryUrl("http://blah/foreign"); 157 const GURL kInOnlineNamespaceUrl( 158 "http://blah/online_namespace/network"); 159 const GURL kExplicitInOnlineNamespaceUrl( 160 "http://blah/online_namespace/explicit"); 161 const GURL kFallbackTestUrl1("http://blah/fallback_namespace/1"); 162 const GURL kFallbackTestUrl2("http://blah/fallback_namespace/longer2"); 163 const GURL kInterceptNamespace("http://blah/intercept_namespace/"); 164 const GURL kInterceptNamespaceWithinFallback( 165 "http://blah/fallback_namespace/intercept_namespace/"); 166 const GURL kInterceptNamespaceEntry("http://blah/intercept_entry"); 167 const GURL kOnlineNamespaceWithinOtherNamespaces( 168 "http://blah/fallback_namespace/intercept_namespace/1/online"); 169 170 const int64 kFallbackResponseId1 = 1; 171 const int64 kFallbackResponseId2 = 2; 172 const int64 kManifestResponseId = 3; 173 const int64 kForeignExplicitResponseId = 4; 174 const int64 kExplicitInOnlineNamespaceResponseId = 5; 175 const int64 kInterceptResponseId = 6; 176 177 AppCacheManifest manifest; 178 manifest.online_whitelist_namespaces.push_back( 179 AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, kOnlineNamespaceUrl, 180 GURL(), false)); 181 manifest.online_whitelist_namespaces.push_back( 182 AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, 183 kOnlineNamespaceWithinOtherNamespaces, GURL(), false)); 184 manifest.fallback_namespaces.push_back( 185 AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl1, 186 kFallbackEntryUrl1, false)); 187 manifest.fallback_namespaces.push_back( 188 AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl2, 189 kFallbackEntryUrl2, false)); 190 manifest.intercept_namespaces.push_back( 191 AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespace, 192 kInterceptNamespaceEntry, false)); 193 manifest.intercept_namespaces.push_back( 194 AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE, 195 kInterceptNamespaceWithinFallback, kInterceptNamespaceEntry, false)); 196 197 // Create a cache with some namespaces and entries. 198 scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234)); 199 cache->InitializeWithManifest(&manifest); 200 cache->AddEntry( 201 kFallbackEntryUrl1, 202 AppCacheEntry(AppCacheEntry::FALLBACK, kFallbackResponseId1)); 203 cache->AddEntry( 204 kFallbackEntryUrl2, 205 AppCacheEntry(AppCacheEntry::FALLBACK, kFallbackResponseId2)); 206 cache->AddEntry( 207 kManifestUrl, 208 AppCacheEntry(AppCacheEntry::MANIFEST, kManifestResponseId)); 209 cache->AddEntry( 210 kForeignExplicitEntryUrl, 211 AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN, 212 kForeignExplicitResponseId)); 213 cache->AddEntry( 214 kExplicitInOnlineNamespaceUrl, 215 AppCacheEntry(AppCacheEntry::EXPLICIT, 216 kExplicitInOnlineNamespaceResponseId)); 217 cache->AddEntry( 218 kInterceptNamespaceEntry, 219 AppCacheEntry(AppCacheEntry::INTERCEPT, kInterceptResponseId)); 220 cache->set_complete(true); 221 222 // See that we get expected results from FindResponseForRequest 223 224 bool found = false; 225 AppCacheEntry entry; 226 AppCacheEntry fallback_entry; 227 GURL intercept_namespace; 228 GURL fallback_namespace; 229 bool network_namespace = false; 230 231 found = cache->FindResponseForRequest(GURL("http://blah/miss"), 232 &entry, &intercept_namespace, 233 &fallback_entry, &fallback_namespace, 234 &network_namespace); 235 EXPECT_FALSE(found); 236 237 found = cache->FindResponseForRequest(kForeignExplicitEntryUrl, 238 &entry, &intercept_namespace, 239 &fallback_entry, &fallback_namespace, 240 &network_namespace); 241 EXPECT_TRUE(found); 242 EXPECT_EQ(kForeignExplicitResponseId, entry.response_id()); 243 EXPECT_FALSE(fallback_entry.has_response_id()); 244 EXPECT_FALSE(network_namespace); 245 246 entry = AppCacheEntry(); // reset 247 248 found = cache->FindResponseForRequest(kManifestUrl, 249 &entry, &intercept_namespace, 250 &fallback_entry, &fallback_namespace, 251 &network_namespace); 252 EXPECT_TRUE(found); 253 EXPECT_EQ(kManifestResponseId, entry.response_id()); 254 EXPECT_FALSE(fallback_entry.has_response_id()); 255 EXPECT_FALSE(network_namespace); 256 257 entry = AppCacheEntry(); // reset 258 259 found = cache->FindResponseForRequest(kInOnlineNamespaceUrl, 260 &entry, &intercept_namespace, 261 &fallback_entry, &fallback_namespace, 262 &network_namespace); 263 EXPECT_TRUE(found); 264 EXPECT_FALSE(entry.has_response_id()); 265 EXPECT_FALSE(fallback_entry.has_response_id()); 266 EXPECT_TRUE(network_namespace); 267 268 network_namespace = false; // reset 269 270 found = cache->FindResponseForRequest(kExplicitInOnlineNamespaceUrl, 271 &entry, &intercept_namespace, 272 &fallback_entry, &fallback_namespace, 273 &network_namespace); 274 EXPECT_TRUE(found); 275 EXPECT_EQ(kExplicitInOnlineNamespaceResponseId, entry.response_id()); 276 EXPECT_FALSE(fallback_entry.has_response_id()); 277 EXPECT_FALSE(network_namespace); 278 279 entry = AppCacheEntry(); // reset 280 281 found = cache->FindResponseForRequest(kFallbackTestUrl1, 282 &entry, &intercept_namespace, 283 &fallback_entry, &fallback_namespace, 284 &network_namespace); 285 EXPECT_TRUE(found); 286 EXPECT_FALSE(entry.has_response_id()); 287 EXPECT_EQ(kFallbackResponseId1, fallback_entry.response_id()); 288 EXPECT_EQ(kFallbackEntryUrl1, 289 cache->GetFallbackEntryUrl(fallback_namespace)); 290 EXPECT_FALSE(network_namespace); 291 292 fallback_entry = AppCacheEntry(); // reset 293 294 found = cache->FindResponseForRequest(kFallbackTestUrl2, 295 &entry, &intercept_namespace, 296 &fallback_entry, &fallback_namespace, 297 &network_namespace); 298 EXPECT_TRUE(found); 299 EXPECT_FALSE(entry.has_response_id()); 300 EXPECT_EQ(kFallbackResponseId2, fallback_entry.response_id()); 301 EXPECT_EQ(kFallbackEntryUrl2, 302 cache->GetFallbackEntryUrl(fallback_namespace)); 303 EXPECT_FALSE(network_namespace); 304 305 fallback_entry = AppCacheEntry(); // reset 306 307 found = cache->FindResponseForRequest(kOnlineNamespaceWithinOtherNamespaces, 308 &entry, &intercept_namespace, 309 &fallback_entry, &fallback_namespace, 310 &network_namespace); 311 EXPECT_TRUE(found); 312 EXPECT_FALSE(entry.has_response_id()); 313 EXPECT_FALSE(fallback_entry.has_response_id()); 314 EXPECT_TRUE(network_namespace); 315 316 fallback_entry = AppCacheEntry(); // reset 317 318 found = cache->FindResponseForRequest( 319 kOnlineNamespaceWithinOtherNamespaces.Resolve("online_resource"), 320 &entry, &intercept_namespace, 321 &fallback_entry, &fallback_namespace, 322 &network_namespace); 323 EXPECT_TRUE(found); 324 EXPECT_FALSE(entry.has_response_id()); 325 EXPECT_FALSE(fallback_entry.has_response_id()); 326 EXPECT_TRUE(network_namespace); 327 328 fallback_namespace = GURL(); 329 330 found = cache->FindResponseForRequest( 331 kInterceptNamespace.Resolve("intercept_me"), 332 &entry, &intercept_namespace, 333 &fallback_entry, &fallback_namespace, 334 &network_namespace); 335 EXPECT_TRUE(found); 336 EXPECT_EQ(kInterceptResponseId, entry.response_id()); 337 EXPECT_EQ(kInterceptNamespaceEntry, 338 cache->GetInterceptEntryUrl(intercept_namespace)); 339 EXPECT_FALSE(fallback_entry.has_response_id()); 340 EXPECT_TRUE(fallback_namespace.is_empty()); 341 EXPECT_FALSE(network_namespace); 342 343 entry = AppCacheEntry(); // reset 344 345 found = cache->FindResponseForRequest( 346 kInterceptNamespaceWithinFallback.Resolve("intercept_me"), 347 &entry, &intercept_namespace, 348 &fallback_entry, &fallback_namespace, 349 &network_namespace); 350 EXPECT_TRUE(found); 351 EXPECT_EQ(kInterceptResponseId, entry.response_id()); 352 EXPECT_EQ(kInterceptNamespaceEntry, 353 cache->GetInterceptEntryUrl(intercept_namespace)); 354 EXPECT_FALSE(fallback_entry.has_response_id()); 355 EXPECT_TRUE(fallback_namespace.is_empty()); 356 EXPECT_FALSE(network_namespace); 357 } 358 359 TEST(AppCacheTest, FindInterceptPatternResponseForRequest) { 360 MockAppCacheService service; 361 362 // Setup an appcache with an intercept namespace that uses pattern matching. 363 const GURL kInterceptNamespaceBase("http://blah/intercept_namespace/"); 364 const GURL kInterceptPatternNamespace( 365 kInterceptNamespaceBase.Resolve("*.hit*")); 366 const GURL kInterceptNamespaceEntry("http://blah/intercept_resource"); 367 const int64 kInterceptResponseId = 1; 368 AppCacheManifest manifest; 369 manifest.intercept_namespaces.push_back( 370 AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE, 371 kInterceptPatternNamespace, kInterceptNamespaceEntry, true)); 372 scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234)); 373 cache->InitializeWithManifest(&manifest); 374 cache->AddEntry( 375 kInterceptNamespaceEntry, 376 AppCacheEntry(AppCacheEntry::INTERCEPT, kInterceptResponseId)); 377 cache->set_complete(true); 378 379 // See that the pattern match works. 380 bool found = false; 381 AppCacheEntry entry; 382 AppCacheEntry fallback_entry; 383 GURL intercept_namespace; 384 GURL fallback_namespace; 385 bool network_namespace = false; 386 387 found = cache->FindResponseForRequest( 388 GURL("http://blah/miss"), 389 &entry, &intercept_namespace, 390 &fallback_entry, &fallback_namespace, 391 &network_namespace); 392 EXPECT_FALSE(found); 393 394 found = cache->FindResponseForRequest( 395 GURL("http://blah/intercept_namespace/another_miss"), 396 &entry, &intercept_namespace, 397 &fallback_entry, &fallback_namespace, 398 &network_namespace); 399 EXPECT_FALSE(found); 400 401 found = cache->FindResponseForRequest( 402 GURL("http://blah/intercept_namespace/path.hit"), 403 &entry, &intercept_namespace, 404 &fallback_entry, &fallback_namespace, 405 &network_namespace); 406 EXPECT_TRUE(found); 407 EXPECT_EQ(kInterceptResponseId, entry.response_id()); 408 EXPECT_EQ(kInterceptNamespaceEntry, 409 cache->GetInterceptEntryUrl(intercept_namespace)); 410 EXPECT_FALSE(fallback_entry.has_response_id()); 411 EXPECT_TRUE(fallback_namespace.is_empty()); 412 EXPECT_FALSE(network_namespace); 413 414 entry = AppCacheEntry(); // reset 415 416 found = cache->FindResponseForRequest( 417 GURL("http://blah/intercept_namespace/longer/path.hit?arg=ok"), 418 &entry, &intercept_namespace, 419 &fallback_entry, &fallback_namespace, 420 &network_namespace); 421 EXPECT_TRUE(found); 422 EXPECT_EQ(kInterceptResponseId, entry.response_id()); 423 EXPECT_EQ(kInterceptNamespaceEntry, 424 cache->GetInterceptEntryUrl(intercept_namespace)); 425 EXPECT_FALSE(fallback_entry.has_response_id()); 426 EXPECT_TRUE(fallback_namespace.is_empty()); 427 EXPECT_FALSE(network_namespace); 428 } 429 430 TEST(AppCacheTest, FindFallbackPatternResponseForRequest) { 431 MockAppCacheService service; 432 433 // Setup an appcache with a fallback namespace that uses pattern matching. 434 const GURL kFallbackNamespaceBase("http://blah/fallback_namespace/"); 435 const GURL kFallbackPatternNamespace( 436 kFallbackNamespaceBase.Resolve("*.hit*")); 437 const GURL kFallbackNamespaceEntry("http://blah/fallback_resource"); 438 const int64 kFallbackResponseId = 1; 439 AppCacheManifest manifest; 440 manifest.fallback_namespaces.push_back( 441 AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackPatternNamespace, 442 kFallbackNamespaceEntry, true)); 443 scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234)); 444 cache->InitializeWithManifest(&manifest); 445 cache->AddEntry( 446 kFallbackNamespaceEntry, 447 AppCacheEntry(AppCacheEntry::FALLBACK, kFallbackResponseId)); 448 cache->set_complete(true); 449 450 // See that the pattern match works. 451 bool found = false; 452 AppCacheEntry entry; 453 AppCacheEntry fallback_entry; 454 GURL intercept_namespace; 455 GURL fallback_namespace; 456 bool network_namespace = false; 457 458 found = cache->FindResponseForRequest( 459 GURL("http://blah/miss"), 460 &entry, &intercept_namespace, 461 &fallback_entry, &fallback_namespace, 462 &network_namespace); 463 EXPECT_FALSE(found); 464 465 found = cache->FindResponseForRequest( 466 GURL("http://blah/fallback_namespace/another_miss"), 467 &entry, &intercept_namespace, 468 &fallback_entry, &fallback_namespace, 469 &network_namespace); 470 EXPECT_FALSE(found); 471 472 found = cache->FindResponseForRequest( 473 GURL("http://blah/fallback_namespace/path.hit"), 474 &entry, &intercept_namespace, 475 &fallback_entry, &fallback_namespace, 476 &network_namespace); 477 EXPECT_TRUE(found); 478 EXPECT_FALSE(entry.has_response_id()); 479 EXPECT_EQ(kFallbackResponseId, fallback_entry.response_id()); 480 EXPECT_EQ(kFallbackNamespaceEntry, 481 cache->GetFallbackEntryUrl(fallback_namespace)); 482 EXPECT_FALSE(network_namespace); 483 484 fallback_entry = AppCacheEntry(); 485 fallback_namespace = GURL(); 486 487 found = cache->FindResponseForRequest( 488 GURL("http://blah/fallback_namespace/longer/path.hit?arg=ok"), 489 &entry, &intercept_namespace, 490 &fallback_entry, &fallback_namespace, 491 &network_namespace); 492 EXPECT_TRUE(found); 493 EXPECT_FALSE(entry.has_response_id()); 494 EXPECT_EQ(kFallbackResponseId, fallback_entry.response_id()); 495 EXPECT_EQ(kFallbackNamespaceEntry, 496 cache->GetFallbackEntryUrl(fallback_namespace)); 497 EXPECT_TRUE(intercept_namespace.is_empty()); 498 EXPECT_FALSE(network_namespace); 499 } 500 501 502 TEST(AppCacheTest, FindNetworkNamespacePatternResponseForRequest) { 503 MockAppCacheService service; 504 505 // Setup an appcache with a network namespace that uses pattern matching. 506 const GURL kNetworkNamespaceBase("http://blah/network_namespace/"); 507 const GURL kNetworkPatternNamespace( 508 kNetworkNamespaceBase.Resolve("*.hit*")); 509 AppCacheManifest manifest; 510 manifest.online_whitelist_namespaces.push_back( 511 AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, kNetworkPatternNamespace, 512 GURL(), true)); 513 manifest.online_whitelist_all = false; 514 scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234)); 515 cache->InitializeWithManifest(&manifest); 516 cache->set_complete(true); 517 518 // See that the pattern match works. 519 bool found = false; 520 AppCacheEntry entry; 521 AppCacheEntry fallback_entry; 522 GURL intercept_namespace; 523 GURL fallback_namespace; 524 bool network_namespace = false; 525 526 found = cache->FindResponseForRequest( 527 GURL("http://blah/miss"), 528 &entry, &intercept_namespace, 529 &fallback_entry, &fallback_namespace, 530 &network_namespace); 531 EXPECT_FALSE(found); 532 533 found = cache->FindResponseForRequest( 534 GURL("http://blah/network_namespace/path.hit"), 535 &entry, &intercept_namespace, 536 &fallback_entry, &fallback_namespace, 537 &network_namespace); 538 EXPECT_TRUE(found); 539 EXPECT_TRUE(network_namespace); 540 EXPECT_FALSE(entry.has_response_id()); 541 EXPECT_FALSE(fallback_entry.has_response_id()); 542 } 543 544 TEST(AppCacheTest, ToFromDatabaseRecords) { 545 // Setup a cache with some entries. 546 const int64 kCacheId = 1234; 547 const int64 kGroupId = 4321; 548 const GURL kManifestUrl("http://foo.com/manifest"); 549 const GURL kInterceptUrl("http://foo.com/intercept.html"); 550 const GURL kFallbackUrl("http://foo.com/fallback.html"); 551 const GURL kWhitelistUrl("http://foo.com/whitelist*"); 552 const std::string kData( 553 "CACHE MANIFEST\r" 554 "CHROMIUM-INTERCEPT:\r" 555 "/intercept return /intercept.html\r" 556 "FALLBACK:\r" 557 "/ /fallback.html\r" 558 "NETWORK:\r" 559 "/whitelist* isPattern\r" 560 "*\r"); 561 MockAppCacheService service; 562 scoped_refptr<AppCacheGroup> group = 563 new AppCacheGroup(service.storage(), kManifestUrl, kGroupId); 564 scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId)); 565 AppCacheManifest manifest; 566 EXPECT_TRUE(ParseManifest(kManifestUrl, kData.c_str(), kData.length(), 567 PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); 568 cache->InitializeWithManifest(&manifest); 569 EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE, 570 cache->online_whitelist_namespaces_[0].type); 571 EXPECT_TRUE(cache->online_whitelist_namespaces_[0].is_pattern); 572 EXPECT_EQ(kWhitelistUrl, 573 cache->online_whitelist_namespaces_[0].namespace_url); 574 cache->AddEntry( 575 kManifestUrl, 576 AppCacheEntry(AppCacheEntry::MANIFEST, 1, 1)); 577 cache->AddEntry( 578 kInterceptUrl, 579 AppCacheEntry(AppCacheEntry::INTERCEPT, 3, 3)); 580 cache->AddEntry( 581 kFallbackUrl, 582 AppCacheEntry(AppCacheEntry::FALLBACK, 2, 2)); 583 584 // Get it to produce database records and verify them. 585 AppCacheDatabase::CacheRecord cache_record; 586 std::vector<AppCacheDatabase::EntryRecord> entries; 587 std::vector<AppCacheDatabase::NamespaceRecord> intercepts; 588 std::vector<AppCacheDatabase::NamespaceRecord> fallbacks; 589 std::vector<AppCacheDatabase::OnlineWhiteListRecord> whitelists; 590 cache->ToDatabaseRecords(group.get(), 591 &cache_record, 592 &entries, 593 &intercepts, 594 &fallbacks, 595 &whitelists); 596 EXPECT_EQ(kCacheId, cache_record.cache_id); 597 EXPECT_EQ(kGroupId, cache_record.group_id); 598 EXPECT_TRUE(cache_record.online_wildcard); 599 EXPECT_EQ(1 + 2 + 3, cache_record.cache_size); 600 EXPECT_EQ(3u, entries.size()); 601 EXPECT_EQ(1u, intercepts.size()); 602 EXPECT_EQ(1u, fallbacks.size()); 603 EXPECT_EQ(1u, whitelists.size()); 604 cache = NULL; 605 606 // Create a new AppCache and populate it with those records and verify. 607 cache = new AppCache(service.storage(), kCacheId); 608 cache->InitializeWithDatabaseRecords( 609 cache_record, entries, intercepts, 610 fallbacks, whitelists); 611 EXPECT_TRUE(cache->online_whitelist_all_); 612 EXPECT_EQ(3u, cache->entries().size()); 613 EXPECT_TRUE(cache->GetEntry(kManifestUrl)); 614 EXPECT_TRUE(cache->GetEntry(kInterceptUrl)); 615 EXPECT_TRUE(cache->GetEntry(kFallbackUrl)); 616 EXPECT_EQ(kInterceptUrl, 617 cache->GetInterceptEntryUrl(GURL("http://foo.com/intercept"))); 618 EXPECT_EQ(kFallbackUrl, 619 cache->GetFallbackEntryUrl(GURL("http://foo.com/"))); 620 EXPECT_EQ(1 + 2 + 3, cache->cache_size()); 621 EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE, 622 cache->online_whitelist_namespaces_[0].type); 623 EXPECT_TRUE(cache->online_whitelist_namespaces_[0].is_pattern); 624 EXPECT_EQ(kWhitelistUrl, 625 cache->online_whitelist_namespaces_[0].namespace_url); 626 } 627 628 TEST(AppCacheTest, IsNamespaceMatch) { 629 AppCacheNamespace prefix; 630 prefix.namespace_url = GURL("http://foo.com/prefix"); 631 prefix.is_pattern = false; 632 EXPECT_TRUE(prefix.IsMatch( 633 GURL("http://foo.com/prefix_and_anothing_goes"))); 634 EXPECT_FALSE(prefix.IsMatch( 635 GURL("http://foo.com/nope"))); 636 637 AppCacheNamespace bar_no_star; 638 bar_no_star.namespace_url = GURL("http://foo.com/bar"); 639 bar_no_star.is_pattern = true; 640 EXPECT_TRUE(bar_no_star.IsMatch( 641 GURL("http://foo.com/bar"))); 642 EXPECT_FALSE(bar_no_star.IsMatch( 643 GURL("http://foo.com/bar/nope"))); 644 645 AppCacheNamespace bar_star; 646 bar_star.namespace_url = GURL("http://foo.com/bar/*"); 647 bar_star.is_pattern = true; 648 EXPECT_TRUE(bar_star.IsMatch( 649 GURL("http://foo.com/bar/"))); 650 EXPECT_TRUE(bar_star.IsMatch( 651 GURL("http://foo.com/bar/should_match"))); 652 EXPECT_FALSE(bar_star.IsMatch( 653 GURL("http://foo.com/not_bar/should_not_match"))); 654 655 AppCacheNamespace star_bar_star; 656 star_bar_star.namespace_url = GURL("http://foo.com/*/bar/*"); 657 star_bar_star.is_pattern = true; 658 EXPECT_TRUE(star_bar_star.IsMatch( 659 GURL("http://foo.com/any/bar/should_match"))); 660 EXPECT_TRUE(star_bar_star.IsMatch( 661 GURL("http://foo.com/any/bar/"))); 662 EXPECT_FALSE(star_bar_star.IsMatch( 663 GURL("http://foo.com/any/not_bar/no_match"))); 664 665 AppCacheNamespace query_star_edit; 666 query_star_edit.namespace_url = GURL("http://foo.com/query?id=*&verb=edit*"); 667 query_star_edit.is_pattern = true; 668 EXPECT_TRUE(query_star_edit.IsMatch( 669 GURL("http://foo.com/query?id=1234&verb=edit&option=blue"))); 670 EXPECT_TRUE(query_star_edit.IsMatch( 671 GURL("http://foo.com/query?id=12345&option=blue&verb=edit"))); 672 EXPECT_FALSE(query_star_edit.IsMatch( 673 GURL("http://foo.com/query?id=12345&option=blue&verb=print"))); 674 EXPECT_TRUE(query_star_edit.IsMatch( 675 GURL("http://foo.com/query?id=123&verb=print&verb=edit"))); 676 677 AppCacheNamespace star_greediness; 678 star_greediness.namespace_url = GURL("http://foo.com/*/b"); 679 star_greediness.is_pattern = true; 680 EXPECT_TRUE(star_greediness.IsMatch( 681 GURL("http://foo.com/a/b"))); 682 EXPECT_TRUE(star_greediness.IsMatch( 683 GURL("http://foo.com/a/wxy/z/b"))); 684 EXPECT_TRUE(star_greediness.IsMatch( 685 GURL("http://foo.com/a/b/b"))); 686 EXPECT_TRUE(star_greediness.IsMatch( 687 GURL("http://foo.com/b/b"))); 688 EXPECT_TRUE(star_greediness.IsMatch( 689 GURL("http://foo.com/a/b/b/b/b/b"))); 690 EXPECT_TRUE(star_greediness.IsMatch( 691 GURL("http://foo.com/a/b/b/b/a/b"))); 692 EXPECT_TRUE(star_greediness.IsMatch( 693 GURL("http://foo.com/a/b/01234567890abcdef/b"))); 694 EXPECT_TRUE(star_greediness.IsMatch( 695 GURL("http://foo.com/a/b/01234567890abcdef/b01234567890abcdef/b"))); 696 EXPECT_TRUE(star_greediness.IsMatch( 697 GURL("http://foo.com/a/b/01234567890abcdef_eat_some_more_characters_" 698 "/and_even_more_for_the_heck_of_it/01234567890abcdef/b"))); 699 } 700 701 } // namespace content 702