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