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