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