Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / renderer / manifest / manifest_parser_unittest.cc
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/renderer/manifest/manifest_parser.h"
6
7 #include "base/strings/string_util.h"
8 #include "content/public/common/manifest.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace content {
12
13 class ManifestParserTest : public testing::Test  {
14  protected:
15   ManifestParserTest() {}
16   virtual ~ManifestParserTest() {}
17
18   Manifest ParseManifest(const base::StringPiece& json,
19                          const GURL& document_url = default_document_url,
20                          const GURL& manifest_url = default_manifest_url) {
21     return ManifestParser::Parse(json, document_url, manifest_url);
22   }
23
24   static const GURL default_document_url;
25   static const GURL default_manifest_url;
26
27  private:
28   DISALLOW_COPY_AND_ASSIGN(ManifestParserTest);
29 };
30
31 const GURL ManifestParserTest::default_document_url(
32     "http://foo.com/index.html");
33 const GURL ManifestParserTest::default_manifest_url(
34     "http://foo.com/manifest.json");
35
36 TEST_F(ManifestParserTest, EmptyStringNull) {
37   Manifest manifest = ParseManifest("");
38
39   // A parsing error is equivalent to an empty manifest.
40   ASSERT_TRUE(manifest.IsEmpty());
41   ASSERT_TRUE(manifest.name.is_null());
42   ASSERT_TRUE(manifest.short_name.is_null());
43   ASSERT_TRUE(manifest.start_url.is_empty());
44   ASSERT_EQ(manifest.display, Manifest::DISPLAY_MODE_UNSPECIFIED);
45   ASSERT_EQ(manifest.orientation, blink::WebScreenOrientationLockDefault);
46 }
47
48 TEST_F(ManifestParserTest, ValidNoContentParses) {
49   Manifest manifest = ParseManifest("{}");
50
51   // Check that all the fields are null in that case.
52   ASSERT_TRUE(manifest.IsEmpty());
53   ASSERT_TRUE(manifest.name.is_null());
54   ASSERT_TRUE(manifest.short_name.is_null());
55   ASSERT_TRUE(manifest.start_url.is_empty());
56   ASSERT_EQ(manifest.display, Manifest::DISPLAY_MODE_UNSPECIFIED);
57   ASSERT_EQ(manifest.orientation, blink::WebScreenOrientationLockDefault);
58 }
59
60 TEST_F(ManifestParserTest, NameParseRules) {
61   // Smoke test.
62   {
63     Manifest manifest = ParseManifest("{ \"name\": \"foo\" }");
64     ASSERT_TRUE(EqualsASCII(manifest.name.string(), "foo"));
65     ASSERT_FALSE(manifest.IsEmpty());
66   }
67
68   // Trim whitespaces.
69   {
70     Manifest manifest = ParseManifest("{ \"name\": \"  foo  \" }");
71     ASSERT_TRUE(EqualsASCII(manifest.name.string(), "foo"));
72   }
73
74   // Don't parse if name isn't a string.
75   {
76     Manifest manifest = ParseManifest("{ \"name\": {} }");
77     ASSERT_TRUE(manifest.name.is_null());
78   }
79
80   // Don't parse if name isn't a string.
81   {
82     Manifest manifest = ParseManifest("{ \"name\": 42 }");
83     ASSERT_TRUE(manifest.name.is_null());
84   }
85 }
86
87 TEST_F(ManifestParserTest, ShortNameParseRules) {
88   // Smoke test.
89   {
90     Manifest manifest = ParseManifest("{ \"short_name\": \"foo\" }");
91     ASSERT_TRUE(EqualsASCII(manifest.short_name.string(), "foo"));
92     ASSERT_FALSE(manifest.IsEmpty());
93   }
94
95   // Trim whitespaces.
96   {
97     Manifest manifest = ParseManifest("{ \"short_name\": \"  foo  \" }");
98     ASSERT_TRUE(EqualsASCII(manifest.short_name.string(), "foo"));
99   }
100
101   // Don't parse if name isn't a string.
102   {
103     Manifest manifest = ParseManifest("{ \"short_name\": {} }");
104     ASSERT_TRUE(manifest.short_name.is_null());
105   }
106
107   // Don't parse if name isn't a string.
108   {
109     Manifest manifest = ParseManifest("{ \"short_name\": 42 }");
110     ASSERT_TRUE(manifest.short_name.is_null());
111   }
112 }
113
114 TEST_F(ManifestParserTest, StartURLParseRules) {
115   // Smoke test.
116   {
117     Manifest manifest = ParseManifest("{ \"start_url\": \"land.html\" }");
118     ASSERT_EQ(manifest.start_url.spec(),
119               default_document_url.Resolve("land.html").spec());
120     ASSERT_FALSE(manifest.IsEmpty());
121   }
122
123   // Whitespaces.
124   {
125     Manifest manifest = ParseManifest("{ \"start_url\": \"  land.html  \" }");
126     ASSERT_EQ(manifest.start_url.spec(),
127               default_document_url.Resolve("land.html").spec());
128   }
129
130   // Don't parse if property isn't a string.
131   {
132     Manifest manifest = ParseManifest("{ \"start_url\": {} }");
133     ASSERT_TRUE(manifest.start_url.is_empty());
134   }
135
136   // Don't parse if property isn't a string.
137   {
138     Manifest manifest = ParseManifest("{ \"start_url\": 42 }");
139     ASSERT_TRUE(manifest.start_url.is_empty());
140   }
141
142   // Absolute start_url, same origin with document.
143   {
144     Manifest manifest =
145         ParseManifest("{ \"start_url\": \"http://foo.com/land.html\" }",
146                       GURL("http://foo.com/manifest.json"),
147                       GURL("http://foo.com/index.html"));
148     ASSERT_EQ(manifest.start_url.spec(), "http://foo.com/land.html");
149   }
150
151   // Absolute start_url, cross origin with document.
152   {
153     Manifest manifest =
154         ParseManifest("{ \"start_url\": \"http://bar.com/land.html\" }",
155                       GURL("http://foo.com/manifest.json"),
156                       GURL("http://foo.com/index.html"));
157     ASSERT_TRUE(manifest.start_url.is_empty());
158   }
159
160   // Resolving has to happen based on the manifest_url.
161   {
162     Manifest manifest =
163         ParseManifest("{ \"start_url\": \"land.html\" }",
164                       GURL("http://foo.com/landing/manifest.json"),
165                       GURL("http://foo.com/index.html"));
166     ASSERT_EQ(manifest.start_url.spec(), "http://foo.com/landing/land.html");
167   }
168 }
169
170 TEST_F(ManifestParserTest, DisplayParserRules) {
171   // Smoke test.
172   {
173     Manifest manifest = ParseManifest("{ \"display\": \"browser\" }");
174     EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_BROWSER);
175     EXPECT_FALSE(manifest.IsEmpty());
176   }
177
178   // Trim whitespaces.
179   {
180     Manifest manifest = ParseManifest("{ \"display\": \"  browser  \" }");
181     EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_BROWSER);
182   }
183
184   // Don't parse if name isn't a string.
185   {
186     Manifest manifest = ParseManifest("{ \"display\": {} }");
187     EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_UNSPECIFIED);
188   }
189
190   // Don't parse if name isn't a string.
191   {
192     Manifest manifest = ParseManifest("{ \"display\": 42 }");
193     EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_UNSPECIFIED);
194   }
195
196   // Parse fails if string isn't known.
197   {
198     Manifest manifest = ParseManifest("{ \"display\": \"browser_something\" }");
199     EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_UNSPECIFIED);
200   }
201
202   // Accept 'fullscreen'.
203   {
204     Manifest manifest = ParseManifest("{ \"display\": \"fullscreen\" }");
205     EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_FULLSCREEN);
206   }
207
208   // Accept 'fullscreen'.
209   {
210     Manifest manifest = ParseManifest("{ \"display\": \"standalone\" }");
211     EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_STANDALONE);
212   }
213
214   // Accept 'minimal-ui'.
215   {
216     Manifest manifest = ParseManifest("{ \"display\": \"minimal-ui\" }");
217     EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_MINIMAL_UI);
218   }
219
220   // Accept 'browser'.
221   {
222     Manifest manifest = ParseManifest("{ \"display\": \"browser\" }");
223     EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_BROWSER);
224   }
225
226   // Case insensitive.
227   {
228     Manifest manifest = ParseManifest("{ \"display\": \"BROWSER\" }");
229     EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_BROWSER);
230   }
231 }
232
233 TEST_F(ManifestParserTest, OrientationParserRules) {
234   // Smoke test.
235   {
236     Manifest manifest = ParseManifest("{ \"orientation\": \"natural\" }");
237     EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockNatural);
238     EXPECT_FALSE(manifest.IsEmpty());
239   }
240
241   // Trim whitespaces.
242   {
243     Manifest manifest = ParseManifest("{ \"orientation\": \"natural\" }");
244     EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockNatural);
245   }
246
247   // Don't parse if name isn't a string.
248   {
249     Manifest manifest = ParseManifest("{ \"orientation\": {} }");
250     EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockDefault);
251   }
252
253   // Don't parse if name isn't a string.
254   {
255     Manifest manifest = ParseManifest("{ \"orientation\": 42 }");
256     EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockDefault);
257   }
258
259   // Parse fails if string isn't known.
260   {
261     Manifest manifest = ParseManifest("{ \"orientation\": \"naturalish\" }");
262     EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockDefault);
263   }
264
265   // Accept 'any'.
266   {
267     Manifest manifest = ParseManifest("{ \"orientation\": \"any\" }");
268     EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockAny);
269   }
270
271   // Accept 'natural'.
272   {
273     Manifest manifest = ParseManifest("{ \"orientation\": \"natural\" }");
274     EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockNatural);
275   }
276
277   // Accept 'landscape'.
278   {
279     Manifest manifest = ParseManifest("{ \"orientation\": \"landscape\" }");
280     EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockLandscape);
281   }
282
283   // Accept 'landscape-primary'.
284   {
285     Manifest manifest =
286         ParseManifest("{ \"orientation\": \"landscape-primary\" }");
287     EXPECT_EQ(manifest.orientation,
288               blink::WebScreenOrientationLockLandscapePrimary);
289   }
290
291   // Accept 'landscape-secondary'.
292   {
293     Manifest manifest =
294         ParseManifest("{ \"orientation\": \"landscape-secondary\" }");
295     EXPECT_EQ(manifest.orientation,
296               blink::WebScreenOrientationLockLandscapeSecondary);
297   }
298
299   // Accept 'portrait'.
300   {
301     Manifest manifest = ParseManifest("{ \"orientation\": \"portrait\" }");
302     EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockPortrait);
303   }
304
305   // Accept 'portrait-primary'.
306   {
307     Manifest manifest =
308       ParseManifest("{ \"orientation\": \"portrait-primary\" }");
309     EXPECT_EQ(manifest.orientation,
310               blink::WebScreenOrientationLockPortraitPrimary);
311   }
312
313   // Accept 'portrait-secondary'.
314   {
315     Manifest manifest =
316         ParseManifest("{ \"orientation\": \"portrait-secondary\" }");
317     EXPECT_EQ(manifest.orientation,
318               blink::WebScreenOrientationLockPortraitSecondary);
319   }
320
321   // Case insensitive.
322   {
323     Manifest manifest = ParseManifest("{ \"orientation\": \"LANDSCAPE\" }");
324     EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockLandscape);
325   }
326 }
327
328 TEST_F(ManifestParserTest, IconsParseRules) {
329   // Smoke test: if no icon, empty list.
330   {
331     Manifest manifest = ParseManifest("{ \"icons\": [] }");
332     EXPECT_EQ(manifest.icons.size(), 0u);
333     EXPECT_TRUE(manifest.IsEmpty());
334   }
335
336   // Smoke test: if empty icon, empty list.
337   {
338     Manifest manifest = ParseManifest("{ \"icons\": [ {} ] }");
339     EXPECT_EQ(manifest.icons.size(), 0u);
340     EXPECT_TRUE(manifest.IsEmpty());
341   }
342
343   // Smoke test: icon with invalid src, empty list.
344   {
345     Manifest manifest = ParseManifest("{ \"icons\": [ { \"icons\": [] } ] }");
346     EXPECT_EQ(manifest.icons.size(), 0u);
347     EXPECT_TRUE(manifest.IsEmpty());
348   }
349
350   // Smoke test: if icon with empty src, it will be present in the list.
351   {
352     Manifest manifest = ParseManifest("{ \"icons\": [ { \"src\": \"\" } ] }");
353     EXPECT_EQ(manifest.icons.size(), 1u);
354     EXPECT_EQ(manifest.icons[0].src.spec(), "http://foo.com/index.html");
355     EXPECT_FALSE(manifest.IsEmpty());
356   }
357
358   // Smoke test: if one icons with valid src, it will be present in the list.
359   {
360     Manifest manifest =
361         ParseManifest("{ \"icons\": [{ \"src\": \"foo.jpg\" }] }");
362     EXPECT_EQ(manifest.icons.size(), 1u);
363     EXPECT_EQ(manifest.icons[0].src.spec(), "http://foo.com/foo.jpg");
364     EXPECT_FALSE(manifest.IsEmpty());
365   }
366 }
367
368 TEST_F(ManifestParserTest, IconSrcParseRules) {
369   // Smoke test.
370   {
371     Manifest manifest =
372         ParseManifest("{ \"icons\": [ {\"src\": \"foo.png\" } ] }");
373     EXPECT_EQ(manifest.icons[0].src.spec(),
374               default_document_url.Resolve("foo.png").spec());
375   }
376
377   // Whitespaces.
378   {
379     Manifest manifest =
380         ParseManifest("{ \"icons\": [ {\"src\": \"   foo.png   \" } ] }");
381     EXPECT_EQ(manifest.icons[0].src.spec(),
382               default_document_url.Resolve("foo.png").spec());
383   }
384
385   // Don't parse if property isn't a string.
386   {
387     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": {} } ] }");
388     EXPECT_TRUE(manifest.icons.empty());
389   }
390
391   // Don't parse if property isn't a string.
392   {
393     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": 42 } ] }");
394     EXPECT_TRUE(manifest.icons.empty());
395   }
396
397   // Resolving has to happen based on the document_url.
398   {
399     Manifest manifest =
400         ParseManifest("{ \"icons\": [ {\"src\": \"icons/foo.png\" } ] }",
401                       GURL("http://foo.com/landing/index.html"));
402     EXPECT_EQ(manifest.icons[0].src.spec(),
403               "http://foo.com/landing/icons/foo.png");
404   }
405 }
406
407 TEST_F(ManifestParserTest, IconTypeParseRules) {
408   // Smoke test.
409   {
410     Manifest manifest =
411         ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": \"foo\" } ] }");
412     EXPECT_TRUE(EqualsASCII(manifest.icons[0].type.string(), "foo"));
413   }
414
415   // Trim whitespaces.
416   {
417     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
418                                       " \"type\": \"  foo  \" } ] }");
419     EXPECT_TRUE(EqualsASCII(manifest.icons[0].type.string(), "foo"));
420   }
421
422   // Don't parse if property isn't a string.
423   {
424     Manifest manifest =
425         ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": {} } ] }");
426     EXPECT_TRUE(manifest.icons[0].type.is_null());
427   }
428
429   // Don't parse if property isn't a string.
430   {
431     Manifest manifest =
432         ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": 42 } ] }");
433     EXPECT_TRUE(manifest.icons[0].type.is_null());
434   }
435 }
436
437 TEST_F(ManifestParserTest, IconDensityParseRules) {
438   // Smoke test.
439   {
440     Manifest manifest =
441         ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": 42 } ] }");
442     EXPECT_EQ(manifest.icons[0].density, 42);
443   }
444
445   // Decimal value.
446   {
447     Manifest manifest =
448         ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": 2.5 } ] }");
449     EXPECT_EQ(manifest.icons[0].density, 2.5);
450   }
451
452   // Parse fail if it isn't a float.
453   {
454     Manifest manifest =
455         ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": {} } ] }");
456     EXPECT_EQ(manifest.icons[0].density, Manifest::Icon::kDefaultDensity);
457   }
458
459   // Parse fail if it isn't a float.
460   {
461     Manifest manifest =
462         ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\":\"2\" } ] }");
463     EXPECT_EQ(manifest.icons[0].density, Manifest::Icon::kDefaultDensity);
464   }
465
466   // Edge case: 1.0.
467   {
468     Manifest manifest =
469         ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": 1.00 } ] }");
470     EXPECT_EQ(manifest.icons[0].density, 1);
471   }
472
473   // Edge case: values between 0.0 and 1.0 are allowed.
474   {
475     Manifest manifest =
476         ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": 0.42 } ] }");
477     EXPECT_EQ(manifest.icons[0].density, 0.42);
478   }
479
480   // 0 is an invalid value.
481   {
482     Manifest manifest =
483         ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": 0.0 } ] }");
484     EXPECT_EQ(manifest.icons[0].density, Manifest::Icon::kDefaultDensity);
485   }
486
487   // Negative values are invalid.
488   {
489     Manifest manifest =
490         ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": -2.5 } ] }");
491     EXPECT_EQ(manifest.icons[0].density, Manifest::Icon::kDefaultDensity);
492   }
493 }
494
495 TEST_F(ManifestParserTest, IconSizesParseRules) {
496   // Smoke test.
497   {
498     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
499         "\"sizes\": \"42x42\" } ] }");
500     EXPECT_EQ(manifest.icons[0].sizes.size(), 1u);
501   }
502
503   // Trim whitespaces.
504   {
505     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
506         "\"sizes\": \"  42x42  \" } ] }");
507     EXPECT_EQ(manifest.icons[0].sizes.size(), 1u);
508   }
509
510   // Don't parse if name isn't a string.
511   {
512     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
513         "\"sizes\": {} } ] }");
514     EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
515   }
516
517   // Don't parse if name isn't a string.
518   {
519     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
520         "\"sizes\": 42 } ] }");
521     EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
522   }
523
524   // Smoke test: value correctly parsed.
525   {
526     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
527         "\"sizes\": \"42x42  48x48\" } ] }");
528     EXPECT_EQ(manifest.icons[0].sizes[0], gfx::Size(42, 42));
529     EXPECT_EQ(manifest.icons[0].sizes[1], gfx::Size(48, 48));
530   }
531
532   // <WIDTH>'x'<HEIGHT> and <WIDTH>'X'<HEIGHT> are equivalent.
533   {
534     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
535         "\"sizes\": \"42X42  48X48\" } ] }");
536     EXPECT_EQ(manifest.icons[0].sizes[0], gfx::Size(42, 42));
537     EXPECT_EQ(manifest.icons[0].sizes[1], gfx::Size(48, 48));
538   }
539
540   // Twice the same value is parsed twice.
541   {
542     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
543         "\"sizes\": \"42X42  42x42\" } ] }");
544     EXPECT_EQ(manifest.icons[0].sizes[0], gfx::Size(42, 42));
545     EXPECT_EQ(manifest.icons[0].sizes[1], gfx::Size(42, 42));
546   }
547
548   // Width or height can't start with 0.
549   {
550     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
551         "\"sizes\": \"004X007  042x00\" } ] }");
552     EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
553   }
554
555   // Width and height MUST contain digits.
556   {
557     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
558         "\"sizes\": \"e4X1.0  55ax1e10\" } ] }");
559     EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
560   }
561
562   // 'any' is correctly parsed and transformed to gfx::Size(0,0).
563   {
564     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
565         "\"sizes\": \"any AnY ANY aNy\" } ] }");
566     gfx::Size any = gfx::Size(0, 0);
567     EXPECT_EQ(manifest.icons[0].sizes.size(), 4u);
568     EXPECT_EQ(manifest.icons[0].sizes[0], any);
569     EXPECT_EQ(manifest.icons[0].sizes[1], any);
570     EXPECT_EQ(manifest.icons[0].sizes[2], any);
571     EXPECT_EQ(manifest.icons[0].sizes[3], any);
572   }
573
574   // Some invalid width/height combinations.
575   {
576     Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
577         "\"sizes\": \"x 40xx 1x2x3 x42 42xx42\" } ] }");
578     gfx::Size any = gfx::Size(0, 0);
579     EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
580   }
581 }
582
583 } // namespace content