Home | History | Annotate | Download | only in appcache
      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 
     11 namespace appcache {
     12 
     13 class AppCacheManifestParserTest : public testing::Test {
     14 };
     15 
     16 TEST(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 
     23 TEST(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 
     61 TEST(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 
     74 TEST(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 
    111 TEST(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 
    151 TEST(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 
    214 TEST(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 
    254 TEST(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 
    295 TEST(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 
    357 TEST(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 
    370 TEST(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 
    382 TEST(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 
    409 TEST(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