Home | History | Annotate | Download | only in common
      1 // Copyright (c) 2011 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 "chrome/common/web_apps.h"
      6 
      7 #include "base/file_path.h"
      8 #include "base/file_util.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/path_service.h"
     11 #include "base/utf_string_conversions.h"
     12 #include "base/values.h"
     13 #include "chrome/common/chrome_paths.h"
     14 #include "chrome/common/json_schema_validator.h"
     15 #include "content/common/json_value_serializer.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 namespace {
     19 
     20 DictionaryValue* LoadDefinitionFile(const std::string& name) {
     21   FilePath path;
     22   if (!PathService::Get(chrome::DIR_TEST_DATA, &path)) {
     23     ADD_FAILURE() << "Could not get test data dir.";
     24     return NULL;
     25   }
     26 
     27   path = path.AppendASCII("web_app_info").AppendASCII(name.c_str());
     28   if (!file_util::PathExists(path)) {
     29     ADD_FAILURE() << "Path does not exist: " << path.value();
     30     return NULL;
     31   }
     32 
     33   std::string error;
     34   JSONFileValueSerializer serializer(path);
     35   DictionaryValue* result = static_cast<DictionaryValue*>(
     36       serializer.Deserialize(NULL, &error));
     37   if (!result) {
     38     ADD_FAILURE() << "Error parsing " << name << ": " << error;
     39     return NULL;
     40   }
     41 
     42   return result;
     43 }
     44 
     45 WebApplicationInfo* ParseFromDefinitionAndExpectSuccess(
     46     const std::string& name) {
     47   scoped_ptr<DictionaryValue> defintion(LoadDefinitionFile(name));
     48   if (!defintion.get())
     49     return NULL;
     50 
     51   scoped_ptr<WebApplicationInfo> web_app(new WebApplicationInfo());
     52   web_app->manifest_url = GURL("http://example.com/");
     53 
     54   string16 error;
     55   if (!web_apps::ParseWebAppFromDefinitionFile(defintion.get(), web_app.get(),
     56                                                &error)) {
     57     ADD_FAILURE() << "Error parsing " << name << ": " << UTF16ToUTF8(error);
     58     return NULL;
     59   }
     60 
     61   return web_app.release();
     62 }
     63 
     64 void ParseFromDefinitionAndExpectFailure(const std::string& name,
     65                                          const string16& expected_error) {
     66   scoped_ptr<DictionaryValue> definition(LoadDefinitionFile(name));
     67   if (!definition.get())
     68     return;
     69 
     70   WebApplicationInfo web_app;
     71   web_app.manifest_url = GURL("http://example.com/");
     72 
     73   string16 error;
     74   if (web_apps::ParseWebAppFromDefinitionFile(definition.get(), &web_app,
     75                                               &error)) {
     76     ADD_FAILURE() << "Expected error parsing " << name
     77                   << " but parse succeeded.";
     78     return;
     79   }
     80 
     81   EXPECT_EQ(UTF16ToUTF8(expected_error), UTF16ToUTF8(error)) << name;
     82 }
     83 
     84 }
     85 
     86 TEST(WebAppInfo, ParseFromDefinitionFileErrors) {
     87   // Test one definition file with a JSON schema error, just to make sure we're
     88   // correctly propagating those. We don't extensively test all the properties
     89   // covered by the schema, since we assume JSON schema is working correctly.
     90   ParseFromDefinitionAndExpectFailure(
     91       "missing_name.json",
     92       UTF8ToUTF16(std::string("name: ") +
     93                       JSONSchemaValidator::kObjectPropertyIsRequired));
     94 
     95   ParseFromDefinitionAndExpectFailure(
     96       "invalid_launch_url.json",
     97       UTF8ToUTF16(WebApplicationInfo::kInvalidLaunchURL));
     98 
     99   ParseFromDefinitionAndExpectFailure(
    100       "invalid_urls.json",
    101       UTF8ToUTF16(
    102           JSONSchemaValidator::FormatErrorMessage(
    103               WebApplicationInfo::kInvalidURL, "2")));
    104 }
    105 
    106 TEST(WebAppInfo, Minimal) {
    107   scoped_ptr<WebApplicationInfo> web_app(
    108       ParseFromDefinitionAndExpectSuccess("minimal.json"));
    109 
    110   EXPECT_EQ(UTF8ToUTF16("hello"), web_app->title);
    111   EXPECT_EQ(UTF8ToUTF16(""), web_app->description);
    112   EXPECT_EQ(GURL("http://example.com/launch_url"), web_app->app_url);
    113   EXPECT_EQ(0u, web_app->icons.size());
    114   EXPECT_EQ(0u, web_app->urls.size());
    115   EXPECT_EQ(0u, web_app->permissions.size());
    116   EXPECT_EQ("", web_app->launch_container);
    117 }
    118 
    119 TEST(WebAppInfo, Full) {
    120   scoped_ptr<WebApplicationInfo> web_app(
    121       ParseFromDefinitionAndExpectSuccess("full.json"));
    122 
    123   EXPECT_EQ(UTF8ToUTF16("hello"), web_app->title);
    124   EXPECT_EQ(UTF8ToUTF16("This app is super awesome"), web_app->description);
    125   EXPECT_EQ(GURL("http://example.com/launch_url"), web_app->app_url);
    126   ASSERT_EQ(1u, web_app->icons.size());
    127   EXPECT_EQ("http://example.com/16.png", web_app->icons[0].url.spec());
    128   EXPECT_EQ(16, web_app->icons[0].width);
    129   EXPECT_EQ(16, web_app->icons[0].height);
    130   ASSERT_EQ(2u, web_app->urls.size());
    131   EXPECT_EQ("http://example.com/foobar", web_app->urls[0].spec());
    132   EXPECT_EQ("http://example.com/baz", web_app->urls[1].spec());
    133   ASSERT_EQ(2u, web_app->permissions.size());
    134   EXPECT_EQ("geolocation", web_app->permissions[0]);
    135   EXPECT_EQ("notifications", web_app->permissions[1]);
    136   EXPECT_EQ("panel", web_app->launch_container);
    137 }
    138 
    139 // Tests ParseIconSizes with various input.
    140 TEST(WebAppInfo, ParseIconSizes) {
    141   struct TestData {
    142     const char* input;
    143     const bool expected_result;
    144     const bool is_any;
    145     const size_t expected_size_count;
    146     const int width1;
    147     const int height1;
    148     const int width2;
    149     const int height2;
    150   } data[] = {
    151     // Bogus input cases.
    152     { "10",         false, false, 0, 0, 0, 0, 0 },
    153     { "10 10",      false, false, 0, 0, 0, 0, 0 },
    154     { "010",        false, false, 0, 0, 0, 0, 0 },
    155     { " 010 ",      false, false, 0, 0, 0, 0, 0 },
    156     { " 10x ",      false, false, 0, 0, 0, 0, 0 },
    157     { " x10 ",      false, false, 0, 0, 0, 0, 0 },
    158     { "any 10x10",  false, false, 0, 0, 0, 0, 0 },
    159     { "",           false, false, 0, 0, 0, 0, 0 },
    160     { "10ax11",     false, false, 0, 0, 0, 0, 0 },
    161 
    162     // Any.
    163     { "any",        true, true, 0, 0, 0, 0, 0 },
    164     { " any",       true, true, 0, 0, 0, 0, 0 },
    165     { " any ",      true, true, 0, 0, 0, 0, 0 },
    166 
    167     // Sizes.
    168     { "10x11",      true, false, 1, 10, 11, 0, 0 },
    169     { " 10x11 ",    true, false, 1, 10, 11, 0, 0 },
    170     { " 10x11 1x2", true, false, 2, 10, 11, 1, 2 },
    171   };
    172   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
    173     bool is_any;
    174     std::vector<gfx::Size> sizes;
    175     bool result = web_apps::ParseIconSizes(ASCIIToUTF16(data[i].input), &sizes,
    176                                            &is_any);
    177     ASSERT_EQ(result, data[i].expected_result);
    178     if (result) {
    179       ASSERT_EQ(data[i].is_any, is_any);
    180       ASSERT_EQ(data[i].expected_size_count, sizes.size());
    181       if (!sizes.empty()) {
    182         ASSERT_EQ(data[i].width1, sizes[0].width());
    183         ASSERT_EQ(data[i].height1, sizes[0].height());
    184       }
    185       if (sizes.size() > 1) {
    186         ASSERT_EQ(data[i].width2, sizes[1].width());
    187         ASSERT_EQ(data[i].height2, sizes[1].height());
    188       }
    189     }
    190   }
    191 }
    192