Home | History | Annotate | Download | only in manifest_handlers
      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 <algorithm>
      6 
      7 #include "extensions/common/error_utils.h"
      8 #include "extensions/common/manifest_constants.h"
      9 #include "extensions/common/manifest_handlers/externally_connectable.h"
     10 #include "extensions/common/manifest_test.h"
     11 #include "extensions/common/permissions/permissions_data.h"
     12 #include "testing/gmock/include/gmock/gmock.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 using testing::ElementsAre;
     16 
     17 namespace extensions {
     18 
     19 namespace errors = externally_connectable_errors;
     20 
     21 class ExternallyConnectableTest : public ManifestTest {
     22  public:
     23   ExternallyConnectableTest() {}
     24   virtual ~ExternallyConnectableTest() {}
     25 
     26  protected:
     27   ExternallyConnectableInfo* GetExternallyConnectableInfo(
     28       scoped_refptr<Extension> extension) {
     29     return static_cast<ExternallyConnectableInfo*>(
     30         extension->GetManifestData(manifest_keys::kExternallyConnectable));
     31   }
     32 };
     33 
     34 TEST_F(ExternallyConnectableTest, IDsAndMatches) {
     35   scoped_refptr<Extension> extension =
     36       LoadAndExpectSuccess("externally_connectable_ids_and_matches.json");
     37   ASSERT_TRUE(extension.get());
     38 
     39   EXPECT_TRUE(extension->permissions_data()->HasAPIPermission(
     40       APIPermission::kWebConnectable));
     41 
     42   ExternallyConnectableInfo* info =
     43       ExternallyConnectableInfo::Get(extension.get());
     44   ASSERT_TRUE(info);
     45 
     46   EXPECT_THAT(info->ids,
     47               ElementsAre("abcdefghijklmnopabcdefghijklmnop",
     48                           "ponmlkjihgfedcbaponmlkjihgfedcba"));
     49 
     50   EXPECT_FALSE(info->all_ids);
     51 
     52   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com")));
     53   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com/")));
     54   EXPECT_FALSE(info->matches.MatchesURL(GURL("http://example.com/index.html")));
     55 
     56   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com")));
     57   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com/")));
     58   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com/index.html")));
     59   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://www.google.com")));
     60   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://www.google.com/")));
     61   EXPECT_TRUE(info->matches.MatchesURL(GURL("https://google.com")));
     62   EXPECT_TRUE(info->matches.MatchesURL(GURL("https://google.com/")));
     63 
     64   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org")));
     65   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org/")));
     66   EXPECT_TRUE(
     67       info->matches.MatchesURL(GURL("http://build.chromium.org/index.html")));
     68   EXPECT_FALSE(info->matches.MatchesURL(GURL("https://build.chromium.org")));
     69   EXPECT_FALSE(info->matches.MatchesURL(GURL("https://build.chromium.org/")));
     70   EXPECT_FALSE(
     71       info->matches.MatchesURL(GURL("http://foo.chromium.org/index.html")));
     72 
     73   EXPECT_FALSE(info->matches.MatchesURL(GURL("http://yahoo.com")));
     74   EXPECT_FALSE(info->matches.MatchesURL(GURL("http://yahoo.com/")));
     75 
     76   // TLD-style patterns should match just the TLD.
     77   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://appspot.com/foo.html")));
     78   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://com")));
     79   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://go/here")));
     80 
     81   // TLD-style patterns should *not* match any subdomains of the TLD.
     82   EXPECT_FALSE(
     83       info->matches.MatchesURL(GURL("http://codereview.appspot.com/foo.html")));
     84   EXPECT_FALSE(
     85       info->matches.MatchesURL(GURL("http://chromium.com/index.html")));
     86   EXPECT_FALSE(info->matches.MatchesURL(GURL("http://here.go/somewhere")));
     87 
     88   // Paths that don't have any wildcards should match the exact domain, but
     89   // ignore the trailing slash. This is kind of a corner case, so let's test it.
     90   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://no.wildcard.path")));
     91   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://no.wildcard.path/")));
     92   EXPECT_FALSE(
     93       info->matches.MatchesURL(GURL("http://no.wildcard.path/index.html")));
     94 }
     95 
     96 TEST_F(ExternallyConnectableTest, IDs) {
     97   scoped_refptr<Extension> extension =
     98       LoadAndExpectSuccess("externally_connectable_ids.json");
     99   ASSERT_TRUE(extension.get());
    100 
    101   EXPECT_FALSE(extension->permissions_data()->HasAPIPermission(
    102       APIPermission::kWebConnectable));
    103 
    104   ExternallyConnectableInfo* info =
    105       ExternallyConnectableInfo::Get(extension.get());
    106   ASSERT_TRUE(info);
    107 
    108   EXPECT_THAT(info->ids,
    109               ElementsAre("abcdefghijklmnopabcdefghijklmnop",
    110                           "ponmlkjihgfedcbaponmlkjihgfedcba"));
    111 
    112   EXPECT_FALSE(info->all_ids);
    113 
    114   EXPECT_FALSE(info->matches.MatchesURL(GURL("http://google.com/index.html")));
    115 }
    116 
    117 TEST_F(ExternallyConnectableTest, Matches) {
    118   scoped_refptr<Extension> extension =
    119       LoadAndExpectSuccess("externally_connectable_matches.json");
    120   ASSERT_TRUE(extension.get());
    121 
    122   EXPECT_TRUE(extension->permissions_data()->HasAPIPermission(
    123       APIPermission::kWebConnectable));
    124 
    125   ExternallyConnectableInfo* info =
    126       ExternallyConnectableInfo::Get(extension.get());
    127   ASSERT_TRUE(info);
    128 
    129   EXPECT_THAT(info->ids, ElementsAre());
    130 
    131   EXPECT_FALSE(info->all_ids);
    132 
    133   EXPECT_FALSE(info->accepts_tls_channel_id);
    134 
    135   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com")));
    136   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com/")));
    137   EXPECT_FALSE(info->matches.MatchesURL(GURL("http://example.com/index.html")));
    138 
    139   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com")));
    140   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com/")));
    141   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com/index.html")));
    142   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://www.google.com")));
    143   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://www.google.com/")));
    144   EXPECT_TRUE(info->matches.MatchesURL(GURL("https://google.com")));
    145   EXPECT_TRUE(info->matches.MatchesURL(GURL("https://google.com/")));
    146 
    147   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org")));
    148   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org/")));
    149   EXPECT_TRUE(
    150       info->matches.MatchesURL(GURL("http://build.chromium.org/index.html")));
    151   EXPECT_FALSE(info->matches.MatchesURL(GURL("https://build.chromium.org")));
    152   EXPECT_FALSE(info->matches.MatchesURL(GURL("https://build.chromium.org/")));
    153   EXPECT_FALSE(
    154       info->matches.MatchesURL(GURL("http://foo.chromium.org/index.html")));
    155 
    156   EXPECT_FALSE(info->matches.MatchesURL(GURL("http://yahoo.com")));
    157   EXPECT_FALSE(info->matches.MatchesURL(GURL("http://yahoo.com/")));
    158 }
    159 
    160 TEST_F(ExternallyConnectableTest, MatchesWithTlsChannelId) {
    161   scoped_refptr<Extension> extension = LoadAndExpectSuccess(
    162       "externally_connectable_matches_tls_channel_id.json");
    163   ASSERT_TRUE(extension.get());
    164 
    165   EXPECT_TRUE(extension->permissions_data()->HasAPIPermission(
    166       APIPermission::kWebConnectable));
    167 
    168   ExternallyConnectableInfo* info =
    169       ExternallyConnectableInfo::Get(extension.get());
    170   ASSERT_TRUE(info);
    171 
    172   EXPECT_THAT(info->ids, ElementsAre());
    173 
    174   EXPECT_FALSE(info->all_ids);
    175 
    176   EXPECT_TRUE(info->accepts_tls_channel_id);
    177 
    178   // The matches portion of the manifest is identical to those in
    179   // externally_connectable_matches, so only a subset of the Matches tests is
    180   // repeated here.
    181   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com")));
    182   EXPECT_FALSE(info->matches.MatchesURL(GURL("http://example.com/index.html")));
    183 }
    184 
    185 TEST_F(ExternallyConnectableTest, AllIDs) {
    186   scoped_refptr<Extension> extension =
    187       LoadAndExpectSuccess("externally_connectable_all_ids.json");
    188   ASSERT_TRUE(extension.get());
    189 
    190   EXPECT_FALSE(extension->permissions_data()->HasAPIPermission(
    191       APIPermission::kWebConnectable));
    192 
    193   ExternallyConnectableInfo* info =
    194       ExternallyConnectableInfo::Get(extension.get());
    195   ASSERT_TRUE(info);
    196 
    197   EXPECT_THAT(info->ids,
    198               ElementsAre("abcdefghijklmnopabcdefghijklmnop",
    199                           "ponmlkjihgfedcbaponmlkjihgfedcba"));
    200 
    201   EXPECT_TRUE(info->all_ids);
    202 
    203   EXPECT_FALSE(info->matches.MatchesURL(GURL("http://google.com/index.html")));
    204 }
    205 
    206 TEST_F(ExternallyConnectableTest, IdCanConnect) {
    207   // Not in order to test that ExternallyConnectableInfo sorts it.
    208   std::string matches_ids_array[] = {"g", "h", "c", "i", "a", "z", "b"};
    209   std::vector<std::string> matches_ids(
    210       matches_ids_array, matches_ids_array + arraysize(matches_ids_array));
    211 
    212   std::string nomatches_ids_array[] = {"2", "3", "1"};
    213 
    214   // all_ids = false.
    215   {
    216     ExternallyConnectableInfo info(URLPatternSet(), matches_ids, false, false);
    217     for (size_t i = 0; i < matches_ids.size(); ++i)
    218       EXPECT_TRUE(info.IdCanConnect(matches_ids[i]));
    219     for (size_t i = 0; i < arraysize(nomatches_ids_array); ++i)
    220       EXPECT_FALSE(info.IdCanConnect(nomatches_ids_array[i]));
    221   }
    222 
    223   // all_ids = true.
    224   {
    225     ExternallyConnectableInfo info(URLPatternSet(), matches_ids, true, false);
    226     for (size_t i = 0; i < matches_ids.size(); ++i)
    227       EXPECT_TRUE(info.IdCanConnect(matches_ids[i]));
    228     for (size_t i = 0; i < arraysize(nomatches_ids_array); ++i)
    229       EXPECT_TRUE(info.IdCanConnect(nomatches_ids_array[i]));
    230   }
    231 }
    232 
    233 TEST_F(ExternallyConnectableTest, ErrorWrongFormat) {
    234   LoadAndExpectError("externally_connectable_error_wrong_format.json",
    235                      "expected dictionary, got string");
    236 }
    237 
    238 TEST_F(ExternallyConnectableTest, ErrorBadID) {
    239   LoadAndExpectError(
    240       "externally_connectable_bad_id.json",
    241       ErrorUtils::FormatErrorMessage(errors::kErrorInvalidId, "badid"));
    242 }
    243 
    244 TEST_F(ExternallyConnectableTest, ErrorBadMatches) {
    245   LoadAndExpectError("externally_connectable_error_bad_matches.json",
    246                      ErrorUtils::FormatErrorMessage(
    247                          errors::kErrorInvalidMatchPattern, "www.yahoo.com"));
    248 }
    249 
    250 TEST_F(ExternallyConnectableTest, WarningNoAllURLs) {
    251   scoped_refptr<Extension> extension = LoadAndExpectWarning(
    252       "externally_connectable_error_all_urls.json",
    253       ErrorUtils::FormatErrorMessage(errors::kErrorWildcardHostsNotAllowed,
    254                                      "<all_urls>"));
    255   ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension);
    256   EXPECT_FALSE(info->matches.MatchesAllURLs());
    257   EXPECT_FALSE(info->matches.ContainsPattern(
    258       URLPattern(URLPattern::SCHEME_ALL, "<all_urls>")));
    259   EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com")));
    260   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org")));
    261 }
    262 
    263 TEST_F(ExternallyConnectableTest, AllURLsNotWhitelisted) {
    264   scoped_refptr<Extension> extension = LoadAndExpectSuccess(
    265       "externally_connectable_all_urls_not_whitelisted.json");
    266   ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension);
    267   EXPECT_FALSE(info->matches.MatchesAllURLs());
    268 }
    269 
    270 TEST_F(ExternallyConnectableTest, AllURLsWhitelisted) {
    271   scoped_refptr<Extension> extension =
    272       LoadAndExpectSuccess("externally_connectable_all_urls_whitelisted.json");
    273   ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension);
    274   EXPECT_TRUE(info->matches.MatchesAllURLs());
    275   URLPattern pattern(URLPattern::SCHEME_ALL, "<all_urls>");
    276   EXPECT_TRUE(info->matches.ContainsPattern(pattern));
    277   EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com")));
    278   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org")));
    279 }
    280 
    281 TEST_F(ExternallyConnectableTest, WarningWildcardHost) {
    282   scoped_refptr<Extension> extension = LoadAndExpectWarning(
    283       "externally_connectable_error_wildcard_host.json",
    284       ErrorUtils::FormatErrorMessage(errors::kErrorWildcardHostsNotAllowed,
    285                                      "http://*/*"));
    286   ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension);
    287   EXPECT_FALSE(info->matches.ContainsPattern(
    288       URLPattern(URLPattern::SCHEME_ALL, "http://*/*")));
    289   EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com")));
    290   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org")));
    291 }
    292 
    293 TEST_F(ExternallyConnectableTest, WarningNoTLD) {
    294   scoped_refptr<Extension> extension = LoadAndExpectWarning(
    295       "externally_connectable_error_tld.json",
    296       ErrorUtils::FormatErrorMessage(errors::kErrorTopLevelDomainsNotAllowed,
    297                                      "co.uk",
    298                                      "http://*.co.uk/*"));
    299   ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension);
    300   EXPECT_FALSE(info->matches.ContainsPattern(
    301       URLPattern(URLPattern::SCHEME_ALL, "http://*.co.uk/*")));
    302   EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com")));
    303   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org")));
    304 }
    305 
    306 TEST_F(ExternallyConnectableTest, WarningNoEffectiveTLD) {
    307   scoped_refptr<Extension> extension = LoadAndExpectWarning(
    308       "externally_connectable_error_effective_tld.json",
    309       ErrorUtils::FormatErrorMessage(errors::kErrorTopLevelDomainsNotAllowed,
    310                                      "appspot.com",
    311                                      "http://*.appspot.com/*"));
    312   ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension);
    313   EXPECT_FALSE(info->matches.ContainsPattern(
    314       URLPattern(URLPattern::SCHEME_ALL, "http://*.appspot.com/*")));
    315   EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com")));
    316   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org")));
    317 }
    318 
    319 TEST_F(ExternallyConnectableTest, WarningUnknownTLD) {
    320   scoped_refptr<Extension> extension = LoadAndExpectWarning(
    321       "externally_connectable_error_unknown_tld.json",
    322       ErrorUtils::FormatErrorMessage(errors::kErrorTopLevelDomainsNotAllowed,
    323                                      "notatld",
    324                                      "http://*.notatld/*"));
    325   ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension);
    326   EXPECT_FALSE(info->matches.ContainsPattern(
    327       URLPattern(URLPattern::SCHEME_ALL, "http://*.notatld/*")));
    328   EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com")));
    329   EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org")));
    330 }
    331 
    332 TEST_F(ExternallyConnectableTest, WarningNothingSpecified) {
    333   LoadAndExpectWarning("externally_connectable_nothing_specified.json",
    334                        errors::kErrorNothingSpecified);
    335 }
    336 
    337 }  // namespace extensions
    338