Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2013 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 "base/file_util.h"
      6 #include "base/format_macros.h"
      7 #include "base/path_service.h"
      8 #include "base/strings/string_number_conversions.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "chrome/common/chrome_paths.h"
     11 #include "chrome/common/extensions/command.h"
     12 #include "chrome/common/extensions/extension_file_util.h"
     13 #include "chrome/common/extensions/extension_test_util.h"
     14 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h"
     15 #include "chrome/common/url_constants.h"
     16 #include "extensions/common/extension.h"
     17 #include "extensions/common/extension_resource.h"
     18 #include "extensions/common/manifest.h"
     19 #include "extensions/common/permissions/permissions_data.h"
     20 #include "net/base/mime_sniffer.h"
     21 #include "net/dns/mock_host_resolver.h"
     22 #include "skia/ext/image_operations.h"
     23 #include "testing/gtest/include/gtest/gtest.h"
     24 #include "third_party/skia/include/core/SkBitmap.h"
     25 #include "ui/gfx/codec/png_codec.h"
     26 #include "url/gurl.h"
     27 
     28 using extension_test_util::LoadManifest;
     29 using extension_test_util::LoadManifestStrict;
     30 using base::FilePath;
     31 
     32 namespace extensions {
     33 
     34 // We persist location values in the preferences, so this is a sanity test that
     35 // someone doesn't accidentally change them.
     36 TEST(ExtensionTest, LocationValuesTest) {
     37   ASSERT_EQ(0, Manifest::INVALID_LOCATION);
     38   ASSERT_EQ(1, Manifest::INTERNAL);
     39   ASSERT_EQ(2, Manifest::EXTERNAL_PREF);
     40   ASSERT_EQ(3, Manifest::EXTERNAL_REGISTRY);
     41   ASSERT_EQ(4, Manifest::UNPACKED);
     42   ASSERT_EQ(5, Manifest::COMPONENT);
     43   ASSERT_EQ(6, Manifest::EXTERNAL_PREF_DOWNLOAD);
     44   ASSERT_EQ(7, Manifest::EXTERNAL_POLICY_DOWNLOAD);
     45   ASSERT_EQ(8, Manifest::COMMAND_LINE);
     46   ASSERT_EQ(9, Manifest::EXTERNAL_POLICY);
     47 }
     48 
     49 TEST(ExtensionTest, LocationPriorityTest) {
     50   for (int i = 0; i < Manifest::NUM_LOCATIONS; i++) {
     51     Manifest::Location loc = static_cast<Manifest::Location>(i);
     52 
     53     // INVALID is not a valid location.
     54     if (loc == Manifest::INVALID_LOCATION)
     55       continue;
     56 
     57     // Comparing a location that has no rank will hit a CHECK. Do a
     58     // compare with every valid location, to be sure each one is covered.
     59 
     60     // Check that no install source can override a componenet extension.
     61     ASSERT_EQ(Manifest::COMPONENT,
     62               Manifest::GetHigherPriorityLocation(Manifest::COMPONENT, loc));
     63     ASSERT_EQ(Manifest::COMPONENT,
     64               Manifest::GetHigherPriorityLocation(loc, Manifest::COMPONENT));
     65 
     66     // Check that any source can override a user install. This might change
     67     // in the future, in which case this test should be updated.
     68     ASSERT_EQ(loc,
     69               Manifest::GetHigherPriorityLocation(Manifest::INTERNAL, loc));
     70     ASSERT_EQ(loc,
     71               Manifest::GetHigherPriorityLocation(loc, Manifest::INTERNAL));
     72   }
     73 
     74   // Check a few interesting cases that we know can happen:
     75   ASSERT_EQ(Manifest::EXTERNAL_POLICY_DOWNLOAD,
     76             Manifest::GetHigherPriorityLocation(
     77                 Manifest::EXTERNAL_POLICY_DOWNLOAD,
     78                 Manifest::EXTERNAL_PREF));
     79 
     80   ASSERT_EQ(Manifest::EXTERNAL_PREF,
     81             Manifest::GetHigherPriorityLocation(
     82                 Manifest::INTERNAL,
     83                 Manifest::EXTERNAL_PREF));
     84 }
     85 
     86 TEST(ExtensionTest, GetResourceURLAndPath) {
     87   scoped_refptr<Extension> extension = LoadManifestStrict("empty_manifest",
     88       "empty.json");
     89   EXPECT_TRUE(extension.get());
     90 
     91   EXPECT_EQ(extension->url().spec() + "bar/baz.js",
     92             Extension::GetResourceURL(extension->url(), "bar/baz.js").spec());
     93   EXPECT_EQ(extension->url().spec() + "baz.js",
     94             Extension::GetResourceURL(extension->url(),
     95                                       "bar/../baz.js").spec());
     96   EXPECT_EQ(extension->url().spec() + "baz.js",
     97             Extension::GetResourceURL(extension->url(), "../baz.js").spec());
     98 
     99   // Test that absolute-looking paths ("/"-prefixed) are pasted correctly.
    100   EXPECT_EQ(extension->url().spec() + "test.html",
    101             extension->GetResourceURL("/test.html").spec());
    102 }
    103 
    104 TEST(ExtensionTest, GetResource) {
    105   const FilePath valid_path_test_cases[] = {
    106     FilePath(FILE_PATH_LITERAL("manifest.json")),
    107     FilePath(FILE_PATH_LITERAL("a/b/c/manifest.json")),
    108     FilePath(FILE_PATH_LITERAL("com/manifest.json")),
    109     FilePath(FILE_PATH_LITERAL("lpt/manifest.json")),
    110   };
    111   const FilePath invalid_path_test_cases[] = {
    112     // Directory name
    113     FilePath(FILE_PATH_LITERAL("src/")),
    114     // Contains a drive letter specification.
    115     FilePath(FILE_PATH_LITERAL("C:\\manifest.json")),
    116     // Use backslash '\\' as separator.
    117     FilePath(FILE_PATH_LITERAL("a\\b\\c\\manifest.json")),
    118     // Reserved Characters with extension
    119     FilePath(FILE_PATH_LITERAL("mani>fest.json")),
    120     FilePath(FILE_PATH_LITERAL("mani<fest.json")),
    121     FilePath(FILE_PATH_LITERAL("mani*fest.json")),
    122     FilePath(FILE_PATH_LITERAL("mani:fest.json")),
    123     FilePath(FILE_PATH_LITERAL("mani?fest.json")),
    124     FilePath(FILE_PATH_LITERAL("mani|fest.json")),
    125     // Reserved Characters without extension
    126     FilePath(FILE_PATH_LITERAL("mani>fest")),
    127     FilePath(FILE_PATH_LITERAL("mani<fest")),
    128     FilePath(FILE_PATH_LITERAL("mani*fest")),
    129     FilePath(FILE_PATH_LITERAL("mani:fest")),
    130     FilePath(FILE_PATH_LITERAL("mani?fest")),
    131     FilePath(FILE_PATH_LITERAL("mani|fest")),
    132     // Reserved Names with extension.
    133     FilePath(FILE_PATH_LITERAL("com1.json")),
    134     FilePath(FILE_PATH_LITERAL("com9.json")),
    135     FilePath(FILE_PATH_LITERAL("LPT1.json")),
    136     FilePath(FILE_PATH_LITERAL("LPT9.json")),
    137     FilePath(FILE_PATH_LITERAL("CON.json")),
    138     FilePath(FILE_PATH_LITERAL("PRN.json")),
    139     FilePath(FILE_PATH_LITERAL("AUX.json")),
    140     FilePath(FILE_PATH_LITERAL("NUL.json")),
    141     // Reserved Names without extension.
    142     FilePath(FILE_PATH_LITERAL("com1")),
    143     FilePath(FILE_PATH_LITERAL("com9")),
    144     FilePath(FILE_PATH_LITERAL("LPT1")),
    145     FilePath(FILE_PATH_LITERAL("LPT9")),
    146     FilePath(FILE_PATH_LITERAL("CON")),
    147     FilePath(FILE_PATH_LITERAL("PRN")),
    148     FilePath(FILE_PATH_LITERAL("AUX")),
    149     FilePath(FILE_PATH_LITERAL("NUL")),
    150     // Reserved Names as directory.
    151     FilePath(FILE_PATH_LITERAL("com1/manifest.json")),
    152     FilePath(FILE_PATH_LITERAL("com9/manifest.json")),
    153     FilePath(FILE_PATH_LITERAL("LPT1/manifest.json")),
    154     FilePath(FILE_PATH_LITERAL("LPT9/manifest.json")),
    155     FilePath(FILE_PATH_LITERAL("CON/manifest.json")),
    156     FilePath(FILE_PATH_LITERAL("PRN/manifest.json")),
    157     FilePath(FILE_PATH_LITERAL("AUX/manifest.json")),
    158     FilePath(FILE_PATH_LITERAL("NUL/manifest.json")),
    159   };
    160 
    161   scoped_refptr<Extension> extension = LoadManifestStrict("empty_manifest",
    162       "empty.json");
    163   EXPECT_TRUE(extension.get());
    164   for (size_t i = 0; i < arraysize(valid_path_test_cases); ++i)
    165     EXPECT_TRUE(!extension->GetResource(valid_path_test_cases[i]).empty());
    166   for (size_t i = 0; i < arraysize(invalid_path_test_cases); ++i)
    167     EXPECT_TRUE(extension->GetResource(invalid_path_test_cases[i]).empty());
    168 }
    169 
    170 TEST(ExtensionTest, GetAbsolutePathNoError) {
    171   scoped_refptr<Extension> extension = LoadManifestStrict("absolute_path",
    172       "absolute.json");
    173   EXPECT_TRUE(extension.get());
    174   std::string err;
    175   std::vector<InstallWarning> warnings;
    176   EXPECT_TRUE(extension_file_util::ValidateExtension(extension.get(),
    177                                                      &err, &warnings));
    178   EXPECT_EQ(0U, warnings.size());
    179 
    180   EXPECT_EQ(extension->path().AppendASCII("test.html").value(),
    181             extension->GetResource("test.html").GetFilePath().value());
    182   EXPECT_EQ(extension->path().AppendASCII("test.js").value(),
    183             extension->GetResource("test.js").GetFilePath().value());
    184 }
    185 
    186 
    187 TEST(ExtensionTest, IdIsValid) {
    188   EXPECT_TRUE(Extension::IdIsValid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
    189   EXPECT_TRUE(Extension::IdIsValid("pppppppppppppppppppppppppppppppp"));
    190   EXPECT_TRUE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmnop"));
    191   EXPECT_TRUE(Extension::IdIsValid("ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP"));
    192   EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmno"));
    193   EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmnopa"));
    194   EXPECT_FALSE(Extension::IdIsValid("0123456789abcdef0123456789abcdef"));
    195   EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmnoq"));
    196   EXPECT_FALSE(Extension::IdIsValid("abcdefghijklmnopabcdefghijklmno0"));
    197 }
    198 
    199 
    200 // This test ensures that the mimetype sniffing code stays in sync with the
    201 // actual crx files that we test other parts of the system with.
    202 TEST(ExtensionTest, MimeTypeSniffing) {
    203   base::FilePath path;
    204   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
    205   path = path.AppendASCII("extensions").AppendASCII("good.crx");
    206 
    207   std::string data;
    208   ASSERT_TRUE(base::ReadFileToString(path, &data));
    209 
    210   std::string result;
    211   EXPECT_TRUE(net::SniffMimeType(data.c_str(),
    212                                  data.size(),
    213                                  GURL("http://www.example.com/foo.crx"),
    214                                  std::string(),
    215                                  &result));
    216   EXPECT_EQ(std::string(Extension::kMimeType), result);
    217 
    218   data.clear();
    219   result.clear();
    220   path = path.DirName().AppendASCII("bad_magic.crx");
    221   ASSERT_TRUE(base::ReadFileToString(path, &data));
    222   EXPECT_TRUE(net::SniffMimeType(data.c_str(),
    223                                  data.size(),
    224                                  GURL("http://www.example.com/foo.crx"),
    225                                  std::string(),
    226                                  &result));
    227   EXPECT_EQ("application/octet-stream", result);
    228 }
    229 
    230 TEST(ExtensionTest, WantsFileAccess) {
    231   scoped_refptr<Extension> extension;
    232   GURL file_url("file:///etc/passwd");
    233 
    234   // Ignore the policy delegate for this test.
    235   PermissionsData::SetPolicyDelegate(NULL);
    236 
    237   // <all_urls> permission
    238   extension = LoadManifest("permissions", "permissions_all_urls.json");
    239   EXPECT_TRUE(extension->wants_file_access());
    240   EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
    241       extension.get(), file_url, file_url, -1, NULL, -1, NULL));
    242   extension = LoadManifest(
    243       "permissions", "permissions_all_urls.json", Extension::ALLOW_FILE_ACCESS);
    244   EXPECT_TRUE(extension->wants_file_access());
    245   EXPECT_TRUE(PermissionsData::CanExecuteScriptOnPage(
    246       extension.get(), file_url, file_url, -1, NULL, -1, NULL));
    247 
    248   // file:///* permission
    249   extension = LoadManifest("permissions", "permissions_file_scheme.json");
    250   EXPECT_TRUE(extension->wants_file_access());
    251   EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
    252       extension.get(), file_url, file_url, -1, NULL, -1, NULL));
    253   extension = LoadManifest("permissions",
    254                            "permissions_file_scheme.json",
    255                            Extension::ALLOW_FILE_ACCESS);
    256   EXPECT_TRUE(extension->wants_file_access());
    257   EXPECT_TRUE(PermissionsData::CanExecuteScriptOnPage(
    258       extension.get(), file_url, file_url, -1, NULL, -1, NULL));
    259 
    260   // http://* permission
    261   extension = LoadManifest("permissions", "permissions_http_scheme.json");
    262   EXPECT_FALSE(extension->wants_file_access());
    263   EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
    264       extension.get(), file_url, file_url, -1, NULL, -1, NULL));
    265   extension = LoadManifest("permissions",
    266                            "permissions_http_scheme.json",
    267                            Extension::ALLOW_FILE_ACCESS);
    268   EXPECT_FALSE(extension->wants_file_access());
    269   EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
    270       extension.get(), file_url, file_url, -1, NULL, -1, NULL));
    271 
    272   // <all_urls> content script match
    273   extension = LoadManifest("permissions", "content_script_all_urls.json");
    274   EXPECT_TRUE(extension->wants_file_access());
    275   EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
    276       extension.get(),
    277       file_url,
    278       file_url,
    279       -1,
    280       &ContentScriptsInfo::GetContentScripts(extension.get())[0],
    281       -1,
    282       NULL));
    283   extension = LoadManifest("permissions", "content_script_all_urls.json",
    284       Extension::ALLOW_FILE_ACCESS);
    285   EXPECT_TRUE(extension->wants_file_access());
    286   EXPECT_TRUE(PermissionsData::CanExecuteScriptOnPage(
    287       extension.get(),
    288       file_url,
    289       file_url,
    290       -1,
    291       &ContentScriptsInfo::GetContentScripts(extension.get())[0],
    292       -1,
    293       NULL));
    294 
    295   // file:///* content script match
    296   extension = LoadManifest("permissions", "content_script_file_scheme.json");
    297   EXPECT_TRUE(extension->wants_file_access());
    298   EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
    299       extension.get(),
    300       file_url,
    301       file_url,
    302       -1,
    303       &ContentScriptsInfo::GetContentScripts(extension.get())[0],
    304       -1,
    305       NULL));
    306   extension = LoadManifest("permissions", "content_script_file_scheme.json",
    307       Extension::ALLOW_FILE_ACCESS);
    308   EXPECT_TRUE(extension->wants_file_access());
    309   EXPECT_TRUE(PermissionsData::CanExecuteScriptOnPage(
    310       extension.get(),
    311       file_url,
    312       file_url,
    313       -1,
    314       &ContentScriptsInfo::GetContentScripts(extension.get())[0],
    315       -1,
    316       NULL));
    317 
    318   // http://* content script match
    319   extension = LoadManifest("permissions", "content_script_http_scheme.json");
    320   EXPECT_FALSE(extension->wants_file_access());
    321   EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
    322       extension.get(),
    323       file_url,
    324       file_url,
    325       -1,
    326       &ContentScriptsInfo::GetContentScripts(extension.get())[0],
    327       -1,
    328       NULL));
    329   extension = LoadManifest("permissions", "content_script_http_scheme.json",
    330       Extension::ALLOW_FILE_ACCESS);
    331   EXPECT_FALSE(extension->wants_file_access());
    332   EXPECT_FALSE(PermissionsData::CanExecuteScriptOnPage(
    333       extension.get(),
    334       file_url,
    335       file_url,
    336       -1,
    337       &ContentScriptsInfo::GetContentScripts(extension.get())[0],
    338       -1,
    339       NULL));
    340 }
    341 
    342 TEST(ExtensionTest, ExtraFlags) {
    343   scoped_refptr<Extension> extension;
    344   extension = LoadManifest("app", "manifest.json", Extension::FROM_WEBSTORE);
    345   EXPECT_TRUE(extension->from_webstore());
    346 
    347   extension = LoadManifest("app", "manifest.json", Extension::FROM_BOOKMARK);
    348   EXPECT_TRUE(extension->from_bookmark());
    349 
    350   extension = LoadManifest("app", "manifest.json", Extension::NO_FLAGS);
    351   EXPECT_FALSE(extension->from_bookmark());
    352   EXPECT_FALSE(extension->from_webstore());
    353 }
    354 
    355 }  // namespace extensions
    356