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