1// Copyright (c) 2010 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 "testing/gtest/include/gtest/gtest.h" 8#include "url/gurl.h" 9#include "webkit/browser/appcache/manifest_parser.h" 10 11namespace appcache { 12 13class AppCacheManifestParserTest : public testing::Test { 14}; 15 16TEST(AppCacheManifestParserTest, NoData) { 17 GURL url; 18 Manifest manifest; 19 EXPECT_FALSE(ParseManifest(url, "", 0, manifest)); 20 EXPECT_FALSE(ParseManifest(url, "CACHE MANIFEST\r", 0, manifest)); // 0 len 21} 22 23TEST(AppCacheManifestParserTest, CheckSignature) { 24 GURL url; 25 Manifest manifest; 26 27 const std::string kBadSignatures[] = { 28 "foo", 29 "CACHE MANIFEST;V2\r", // not followed by whitespace 30 "CACHE MANIFEST#bad\r", // no whitespace before comment 31 "cache manifest ", // wrong case 32 "#CACHE MANIFEST\r", // comment 33 "xCACHE MANIFEST\n", // bad first char 34 " CACHE MANIFEST\r", // begins with whitespace 35 "\xEF\xBE\xBF" "CACHE MANIFEST\r", // bad UTF-8 BOM value 36 }; 37 38 for (size_t i = 0; i < arraysize(kBadSignatures); ++i) { 39 const std::string bad = kBadSignatures[i]; 40 EXPECT_FALSE(ParseManifest(url, bad.c_str(), bad.length(), manifest)); 41 } 42 43 const std::string kGoodSignatures[] = { 44 "CACHE MANIFEST", 45 "CACHE MANIFEST ", 46 "CACHE MANIFEST\r", 47 "CACHE MANIFEST\n", 48 "CACHE MANIFEST\r\n", 49 "CACHE MANIFEST\t# ignore me\r", 50 "CACHE MANIFEST ignore\r\n", 51 "CHROMIUM CACHE MANIFEST\r\n", 52 "\xEF\xBB\xBF" "CACHE MANIFEST \r\n", // BOM present 53 }; 54 55 for (size_t i = 0; i < arraysize(kGoodSignatures); ++i) { 56 const std::string good = kGoodSignatures[i]; 57 EXPECT_TRUE(ParseManifest(url, good.c_str(), good.length(), manifest)); 58 } 59} 60 61TEST(AppCacheManifestParserTest, NoManifestUrl) { 62 Manifest manifest; 63 const std::string kData("CACHE MANIFEST\r" 64 "relative/tobase.com\r" 65 "http://absolute.com/addme.com"); 66 const GURL kUrl; 67 EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); 68 EXPECT_TRUE(manifest.explicit_urls.empty()); 69 EXPECT_TRUE(manifest.fallback_namespaces.empty()); 70 EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); 71 EXPECT_FALSE(manifest.online_whitelist_all); 72} 73 74TEST(AppCacheManifestParserTest, ExplicitUrls) { 75 Manifest manifest; 76 const GURL kUrl("http://www.foo.com"); 77 const std::string kData("CACHE MANIFEST\r" 78 "relative/one\r" 79 "# some comment\r" 80 "http://www.foo.com/two#strip\r\n" 81 "NETWORK:\r" 82 " \t CACHE:\r" 83 "HTTP://www.diff.com/three\r" 84 "FALLBACK:\r" 85 " \t # another comment with leading whitespace\n" 86 "IGNORE:\r" 87 "http://www.foo.com/ignore\r" 88 "CACHE: \r" 89 "garbage:#!@\r" 90 "https://www.foo.com/diffscheme \t \r" 91 " \t relative/four#stripme\n\r" 92 "*\r"); 93 94 EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); 95 EXPECT_TRUE(manifest.fallback_namespaces.empty()); 96 EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); 97 EXPECT_FALSE(manifest.online_whitelist_all); 98 99 base::hash_set<std::string> urls = manifest.explicit_urls; 100 const size_t kExpected = 5; 101 ASSERT_EQ(kExpected, urls.size()); 102 EXPECT_TRUE(urls.find("http://www.foo.com/relative/one") != urls.end()); 103 EXPECT_TRUE(urls.find("http://www.foo.com/two") != urls.end()); 104 EXPECT_TRUE(urls.find("http://www.diff.com/three") != urls.end()); 105 EXPECT_TRUE(urls.find("http://www.foo.com/relative/four") != urls.end()); 106 107 // Wildcard is treated as a relative URL in explicit section. 108 EXPECT_TRUE(urls.find("http://www.foo.com/*") != urls.end()); 109} 110 111TEST(AppCacheManifestParserTest, WhitelistUrls) { 112 Manifest manifest; 113 const GURL kUrl("http://www.bar.com"); 114 const std::string kData("CACHE MANIFEST\r" 115 "NETWORK:\r" 116 "relative/one\r" 117 "# a comment\r" 118 "http://www.bar.com/two\r" 119 "HTTP://www.diff.com/three#strip\n\r" 120 "FALLBACK:\r" 121 "garbage\r" 122 "UNKNOWN:\r" 123 "http://www.bar.com/ignore\r" 124 "CACHE:\r" 125 "NETWORK:\r" 126 "https://www.wrongscheme.com\n" 127 "relative/four#stripref \t \r" 128 "http://www.five.com\r\n" 129 "*foo\r"); 130 131 EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); 132 EXPECT_TRUE(manifest.explicit_urls.empty()); 133 EXPECT_TRUE(manifest.fallback_namespaces.empty()); 134 EXPECT_TRUE(manifest.intercept_namespaces.empty()); 135 EXPECT_FALSE(manifest.online_whitelist_all); 136 137 const NamespaceVector& online = manifest.online_whitelist_namespaces; 138 const size_t kExpected = 6; 139 ASSERT_EQ(kExpected, online.size()); 140 EXPECT_EQ(NETWORK_NAMESPACE, online[0].type); 141 EXPECT_FALSE(online[0].is_pattern); 142 EXPECT_TRUE(online[0].target_url.is_empty()); 143 EXPECT_EQ(GURL("http://www.bar.com/relative/one"), online[0].namespace_url); 144 EXPECT_EQ(GURL("http://www.bar.com/two"), online[1].namespace_url); 145 EXPECT_EQ(GURL("http://www.diff.com/three"), online[2].namespace_url); 146 EXPECT_EQ(GURL("http://www.bar.com/relative/four"), online[3].namespace_url); 147 EXPECT_EQ(GURL("http://www.five.com"), online[4].namespace_url); 148 EXPECT_EQ(GURL("http://www.bar.com/*foo"), online[5].namespace_url); 149} 150 151TEST(AppCacheManifestParserTest, FallbackUrls) { 152 Manifest manifest; 153 const GURL kUrl("http://glorp.com"); 154 const std::string kData("CACHE MANIFEST\r" 155 "# a comment\r" 156 "CACHE:\r" 157 "NETWORK:\r" 158 "UNKNOWN:\r" 159 "FALLBACK:\r" 160 "relative/one \t \t http://glorp.com/onefb \t \r" 161 "*\r" 162 "https://glorp.com/wrong http://glorp.com/wrongfb\r" 163 "http://glorp.com/two#strip relative/twofb\r" 164 "HTTP://glorp.com/three relative/threefb#strip\n" 165 "http://glorp.com/three http://glorp.com/three-dup\r" 166 "http://glorp.com/solo \t \r\n" 167 "http://diff.com/ignore http://glorp.com/wronghost\r" 168 "http://glorp.com/wronghost http://diff.com/ohwell\r" 169 "relative/badscheme ftp://glorp.com/ignored\r" 170 "garbage\r\n" 171 "CACHE:\r" 172 "# only fallback urls in this test\r" 173 "FALLBACK:\n" 174 "relative/four#strip relative/fourfb#strip\r" 175 "http://www.glorp.com/notsame relative/skipped\r"); 176 177 EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); 178 EXPECT_TRUE(manifest.explicit_urls.empty()); 179 EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); 180 EXPECT_FALSE(manifest.online_whitelist_all); 181 182 const NamespaceVector& fallbacks = manifest.fallback_namespaces; 183 const size_t kExpected = 5; 184 ASSERT_EQ(kExpected, fallbacks.size()); 185 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[0].type); 186 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[1].type); 187 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[2].type); 188 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[3].type); 189 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[4].type); 190 EXPECT_EQ(GURL("http://glorp.com/relative/one"), 191 fallbacks[0].namespace_url); 192 EXPECT_EQ(GURL("http://glorp.com/onefb"), 193 fallbacks[0].target_url); 194 EXPECT_EQ(GURL("http://glorp.com/two"), 195 fallbacks[1].namespace_url); 196 EXPECT_EQ(GURL("http://glorp.com/relative/twofb"), 197 fallbacks[1].target_url); 198 EXPECT_EQ(GURL("http://glorp.com/three"), 199 fallbacks[2].namespace_url); 200 EXPECT_EQ(GURL("http://glorp.com/relative/threefb"), 201 fallbacks[2].target_url); 202 EXPECT_EQ(GURL("http://glorp.com/three"), // duplicates are stored 203 fallbacks[3].namespace_url); 204 EXPECT_EQ(GURL("http://glorp.com/three-dup"), 205 fallbacks[3].target_url); 206 EXPECT_EQ(GURL("http://glorp.com/relative/four"), 207 fallbacks[4].namespace_url); 208 EXPECT_EQ(GURL("http://glorp.com/relative/fourfb"), 209 fallbacks[4].target_url); 210 211 EXPECT_TRUE(manifest.intercept_namespaces.empty()); 212} 213 214TEST(AppCacheManifestParserTest, FallbackUrlsWithPort) { 215 Manifest manifest; 216 const GURL kUrl("http://www.portme.com:1234"); 217 const std::string kData("CACHE MANIFEST\r" 218 "FALLBACK:\r" 219 "http://www.portme.com:1234/one relative/onefb\r" 220 "HTTP://www.portme.com:9876/wrong http://www.portme.com:1234/ignore\r" 221 "http://www.portme.com:1234/stillwrong http://www.portme.com:42/boo\r" 222 "relative/two relative/twofb\r" 223 "http://www.portme.com:1234/three HTTP://www.portme.com:1234/threefb\r" 224 "http://www.portme.com/noport http://www.portme.com:1234/skipped\r" 225 "http://www.portme.com:1234/skipme http://www.portme.com/noport\r"); 226 227 EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); 228 EXPECT_TRUE(manifest.explicit_urls.empty()); 229 EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); 230 EXPECT_FALSE(manifest.online_whitelist_all); 231 232 const NamespaceVector& fallbacks = manifest.fallback_namespaces; 233 const size_t kExpected = 3; 234 ASSERT_EQ(kExpected, fallbacks.size()); 235 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[0].type); 236 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[1].type); 237 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[2].type); 238 EXPECT_EQ(GURL("http://www.portme.com:1234/one"), 239 fallbacks[0].namespace_url); 240 EXPECT_EQ(GURL("http://www.portme.com:1234/relative/onefb"), 241 fallbacks[0].target_url); 242 EXPECT_EQ(GURL("http://www.portme.com:1234/relative/two"), 243 fallbacks[1].namespace_url); 244 EXPECT_EQ(GURL("http://www.portme.com:1234/relative/twofb"), 245 fallbacks[1].target_url); 246 EXPECT_EQ(GURL("http://www.portme.com:1234/three"), 247 fallbacks[2].namespace_url); 248 EXPECT_EQ(GURL("http://www.portme.com:1234/threefb"), 249 fallbacks[2].target_url); 250 251 EXPECT_TRUE(manifest.intercept_namespaces.empty()); 252} 253 254TEST(AppCacheManifestParserTest, InterceptUrls) { 255 Manifest manifest; 256 const GURL kUrl("http://www.portme.com:1234"); 257 const std::string kData("CHROMIUM CACHE MANIFEST\r" 258 "CHROMIUM-INTERCEPT:\r" 259 "http://www.portme.com:1234/one return relative/int1\r" 260 "HTTP://www.portme.com:9/wrong return http://www.portme.com:1234/ignore\r" 261 "http://www.portme.com:1234/wrong return http://www.portme.com:9/boo\r" 262 "relative/two return relative/int2\r" 263 "relative/three wrong relative/threefb\r" 264 "http://www.portme.com:1234/three return HTTP://www.portme.com:1234/int3\r" 265 "http://www.portme.com/noport return http://www.portme.com:1234/skipped\r" 266 "http://www.portme.com:1234/skipme return http://www.portme.com/noport\r" 267 "relative/wrong/again missing/intercept_type\r"); 268 269 EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); 270 EXPECT_TRUE(manifest.fallback_namespaces.empty()); 271 EXPECT_TRUE(manifest.explicit_urls.empty()); 272 EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); 273 EXPECT_FALSE(manifest.online_whitelist_all); 274 275 const NamespaceVector& intercepts = manifest.intercept_namespaces; 276 const size_t kExpected = 3; 277 ASSERT_EQ(kExpected, intercepts.size()); 278 EXPECT_EQ(INTERCEPT_NAMESPACE, intercepts[0].type); 279 EXPECT_EQ(INTERCEPT_NAMESPACE, intercepts[1].type); 280 EXPECT_EQ(INTERCEPT_NAMESPACE, intercepts[2].type); 281 EXPECT_EQ(GURL("http://www.portme.com:1234/one"), 282 intercepts[0].namespace_url); 283 EXPECT_EQ(GURL("http://www.portme.com:1234/relative/int1"), 284 intercepts[0].target_url); 285 EXPECT_EQ(GURL("http://www.portme.com:1234/relative/two"), 286 intercepts[1].namespace_url); 287 EXPECT_EQ(GURL("http://www.portme.com:1234/relative/int2"), 288 intercepts[1].target_url); 289 EXPECT_EQ(GURL("http://www.portme.com:1234/three"), 290 intercepts[2].namespace_url); 291 EXPECT_EQ(GURL("http://www.portme.com:1234/int3"), 292 intercepts[2].target_url); 293} 294 295TEST(AppCacheManifestParserTest, ComboUrls) { 296 Manifest manifest; 297 const GURL kUrl("http://combo.com:42"); 298 const std::string kData("CACHE MANIFEST\r" 299 "relative/explicit-1\r" 300 "# some comment\r" 301 "http://combo.com:99/explicit-2#strip\r" 302 "NETWORK:\r" 303 "http://combo.com/whitelist-1\r" 304 "HTTP://www.diff.com/whitelist-2#strip\r" 305 "*\r" 306 "CACHE:\n\r" 307 "http://www.diff.com/explicit-3\r" 308 "FALLBACK:\r" 309 "http://combo.com:42/fallback-1 http://combo.com:42/fallback-1b\r" 310 "relative/fallback-2 relative/fallback-2b\r" 311 "UNKNOWN:\r\n" 312 "http://combo.com/ignoreme\r" 313 "relative/still-ignored\r" 314 "NETWORK:\r\n" 315 "relative/whitelist-3#strip\r" 316 "http://combo.com:99/whitelist-4\r"); 317 EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); 318 EXPECT_TRUE(manifest.online_whitelist_all); 319 320 base::hash_set<std::string> urls = manifest.explicit_urls; 321 size_t expected = 3; 322 ASSERT_EQ(expected, urls.size()); 323 EXPECT_TRUE(urls.find("http://combo.com:42/relative/explicit-1") != 324 urls.end()); 325 EXPECT_TRUE(urls.find("http://combo.com:99/explicit-2") != urls.end()); 326 EXPECT_TRUE(urls.find("http://www.diff.com/explicit-3") != urls.end()); 327 328 const NamespaceVector& online = manifest.online_whitelist_namespaces; 329 expected = 4; 330 ASSERT_EQ(expected, online.size()); 331 EXPECT_EQ(GURL("http://combo.com/whitelist-1"), 332 online[0].namespace_url); 333 EXPECT_EQ(GURL("http://www.diff.com/whitelist-2"), 334 online[1].namespace_url); 335 EXPECT_EQ(GURL("http://combo.com:42/relative/whitelist-3"), 336 online[2].namespace_url); 337 EXPECT_EQ(GURL("http://combo.com:99/whitelist-4"), 338 online[3].namespace_url); 339 340 const NamespaceVector& fallbacks = manifest.fallback_namespaces; 341 expected = 2; 342 ASSERT_EQ(expected, fallbacks.size()); 343 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[0].type); 344 EXPECT_EQ(FALLBACK_NAMESPACE, fallbacks[1].type); 345 EXPECT_EQ(GURL("http://combo.com:42/fallback-1"), 346 fallbacks[0].namespace_url); 347 EXPECT_EQ(GURL("http://combo.com:42/fallback-1b"), 348 fallbacks[0].target_url); 349 EXPECT_EQ(GURL("http://combo.com:42/relative/fallback-2"), 350 fallbacks[1].namespace_url); 351 EXPECT_EQ(GURL("http://combo.com:42/relative/fallback-2b"), 352 fallbacks[1].target_url); 353 354 EXPECT_TRUE(manifest.intercept_namespaces.empty()); 355} 356 357TEST(AppCacheManifestParserTest, UnusualUtf8) { 358 Manifest manifest; 359 const GURL kUrl("http://bad.com"); 360 const std::string kData("CACHE MANIFEST\r" 361 "\xC0" "invalidutf8\r" 362 "nonbmp" "\xF1\x84\xAB\xBC\r"); 363 EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); 364 365 base::hash_set<std::string> urls = manifest.explicit_urls; 366 EXPECT_TRUE(urls.find("http://bad.com/%EF%BF%BDinvalidutf8") != urls.end()); 367 EXPECT_TRUE(urls.find("http://bad.com/nonbmp%F1%84%AB%BC") != urls.end()); 368} 369 370TEST(AppCacheManifestParserTest, IgnoreAfterSpace) { 371 Manifest manifest; 372 const GURL kUrl("http://smorg.borg"); 373 const std::string kData( 374 "CACHE MANIFEST\r" 375 "resource.txt this stuff after the white space should be ignored\r"); 376 EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); 377 378 base::hash_set<std::string> urls = manifest.explicit_urls; 379 EXPECT_TRUE(urls.find("http://smorg.borg/resource.txt") != urls.end()); 380} 381 382TEST(AppCacheManifestParserTest, DifferentOriginUrlWithSecureScheme) { 383 Manifest manifest; 384 const GURL kUrl("https://www.foo.com"); 385 const std::string kData("CACHE MANIFEST\r" 386 "CACHE: \r" 387 "relative/secureschemesameorigin\r" 388 "https://www.foo.com/secureschemesameorigin\r" 389 "http://www.xyz.com/secureschemedifforigin\r" 390 "https://www.xyz.com/secureschemedifforigin\r"); 391 392 EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), manifest)); 393 EXPECT_TRUE(manifest.fallback_namespaces.empty()); 394 EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); 395 396 base::hash_set<std::string> urls = manifest.explicit_urls; 397 const size_t kExpected = 3; 398 ASSERT_EQ(kExpected, urls.size()); 399 EXPECT_TRUE(urls.find("https://www.foo.com/relative/secureschemesameorigin") 400 != urls.end()); 401 EXPECT_TRUE(urls.find("https://www.foo.com/secureschemesameorigin") != 402 urls.end()); 403 EXPECT_FALSE(urls.find("http://www.xyz.com/secureschemedifforigin") != 404 urls.end()); 405 EXPECT_TRUE(urls.find("https://www.xyz.com/secureschemedifforigin") != 406 urls.end()); 407} 408 409TEST(AppCacheManifestParserTest, PatternMatching) { 410 const GURL kUrl("http://foo.com/manifest"); 411 const std::string kManifestBody( 412 "CACHE MANIFEST\r" 413 "CACHE: \r" 414 "http://foo.com/page.html\r" 415 "CHROMIUM-INTERCEPT:\r" 416 "http://foo.com/intercept_prefix return /prefix\r" 417 "http://foo.com/intercept_pattern return /pattern isPattern\r" 418 "http://foo.com/*/intercept_pattern?query return /pattern isPattern\r" 419 "FALLBACK:\r" 420 "http://foo.com/fallback_prefix /prefix wrongAnnotation\r" 421 "http://foo.com/fallback_pattern* /pattern\tisPattern \r" 422 "NETWORK:\r" 423 "*\r" 424 "isPattern\r" // should not be interpretted as a pattern 425 "http://foo.com/network_pattern* isPattern\r"); 426 427 428 Manifest manifest; 429 EXPECT_TRUE(ParseManifest(kUrl, kManifestBody.c_str(), 430 kManifestBody.length(), manifest)); 431 EXPECT_TRUE(manifest.online_whitelist_all); 432 EXPECT_EQ(1u, manifest.explicit_urls.size()); 433 EXPECT_EQ(3u, manifest.intercept_namespaces.size()); 434 EXPECT_EQ(2u, manifest.fallback_namespaces.size()); 435 EXPECT_EQ(2u, manifest.online_whitelist_namespaces.size()); 436 EXPECT_EQ(INTERCEPT_NAMESPACE, manifest.intercept_namespaces[0].type); 437 EXPECT_EQ(FALLBACK_NAMESPACE, manifest.fallback_namespaces[0].type); 438 EXPECT_EQ(NETWORK_NAMESPACE, manifest.online_whitelist_namespaces[0].type); 439 EXPECT_FALSE(manifest.intercept_namespaces[0].is_pattern); 440 EXPECT_TRUE(manifest.intercept_namespaces[1].is_pattern); 441 EXPECT_TRUE(manifest.intercept_namespaces[2].is_pattern); 442 EXPECT_FALSE(manifest.fallback_namespaces[0].is_pattern); 443 EXPECT_TRUE(manifest.fallback_namespaces[1].is_pattern); 444 EXPECT_FALSE(manifest.online_whitelist_namespaces[0].is_pattern); 445 EXPECT_TRUE(manifest.online_whitelist_namespaces[1].is_pattern); 446 EXPECT_EQ( 447 GURL("http://foo.com/*/intercept_pattern?query"), 448 manifest.intercept_namespaces[2].namespace_url); 449 EXPECT_EQ( 450 GURL("http://foo.com/pattern"), 451 manifest.intercept_namespaces[2].target_url); 452 EXPECT_EQ( 453 GURL("http://foo.com/fallback_pattern*"), 454 manifest.fallback_namespaces[1].namespace_url); 455 EXPECT_EQ( 456 GURL("http://foo.com/pattern"), 457 manifest.fallback_namespaces[1].target_url); 458 EXPECT_EQ( 459 GURL("http://foo.com/isPattern"), 460 manifest.online_whitelist_namespaces[0].namespace_url); 461 EXPECT_EQ( 462 GURL(), 463 manifest.online_whitelist_namespaces[0].target_url); 464 EXPECT_EQ( 465 GURL("http://foo.com/network_pattern*"), 466 manifest.online_whitelist_namespaces[1].namespace_url); 467 EXPECT_EQ( 468 GURL(), 469 manifest.online_whitelist_namespaces[1].target_url); 470} 471 472} // namespace appcache 473