Home | History | Annotate | Download | only in extensions
      1 // Copyright 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_path.h"
      6 #include "chrome/common/extensions/api/plugins/plugins_handler.h"
      7 #include "chrome/common/extensions/extension.h"
      8 #include "chrome/common/extensions/extension_manifest_constants.h"
      9 #include "chrome/common/extensions/manifest.h"
     10 #include "chrome/common/extensions/sync_helper.h"
     11 #include "extensions/common/error_utils.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 #include "url/gurl.h"
     14 
     15 namespace keys = extension_manifest_keys;
     16 namespace errors = extension_manifest_errors;
     17 
     18 namespace extensions {
     19 
     20 class ExtensionSyncTypeTest : public testing::Test {
     21  protected:
     22   enum SyncTestExtensionType {
     23     EXTENSION,
     24     APP,
     25     USER_SCRIPT,
     26     THEME
     27   };
     28 
     29   static scoped_refptr<Extension> MakeSyncTestExtensionWithPluginPermission(
     30       SyncTestExtensionType type,
     31       const GURL& update_url,
     32       const GURL& launch_url,
     33       Manifest::Location location,
     34       const base::FilePath& extension_path,
     35       int creation_flags,
     36       int num_plugins,
     37       bool has_plugin_permission,
     38       const std::string& expected_error) {
     39     base::DictionaryValue source;
     40     source.SetString(keys::kName, "PossiblySyncableExtension");
     41     source.SetString(keys::kVersion, "0.0.0.0");
     42     if (type == APP)
     43       source.SetString(keys::kApp, "true");
     44     if (type == THEME)
     45       source.Set(keys::kTheme, new base::DictionaryValue());
     46     if (!update_url.is_empty()) {
     47       source.SetString(keys::kUpdateURL, update_url.spec());
     48     }
     49     if (!launch_url.is_empty()) {
     50       source.SetString(keys::kLaunchWebURL, launch_url.spec());
     51     }
     52     if (type != THEME) {
     53       source.SetBoolean(keys::kConvertedFromUserScript, type == USER_SCRIPT);
     54       if (num_plugins >= 0) {
     55         base::ListValue* plugins = new base::ListValue();
     56         for (int i = 0; i < num_plugins; ++i) {
     57           base::DictionaryValue* plugin = new base::DictionaryValue();
     58           plugin->SetString(keys::kPluginsPath, std::string());
     59           plugins->Set(i, plugin);
     60         }
     61         source.Set(keys::kPlugins, plugins);
     62       }
     63     }
     64     if (has_plugin_permission) {
     65       ListValue* plugins = new ListValue();
     66       plugins->Set(0, new StringValue("plugin"));
     67       source.Set(keys::kPermissions, plugins);
     68     }
     69 
     70     std::string error;
     71     scoped_refptr<Extension> extension = Extension::Create(
     72         extension_path, location, source, creation_flags, &error);
     73     if (expected_error == "")
     74       EXPECT_TRUE(extension.get());
     75     else
     76       EXPECT_FALSE(extension.get());
     77     EXPECT_EQ(expected_error, error);
     78     return extension;
     79   }
     80 
     81   static scoped_refptr<Extension> MakeSyncTestExtension(
     82       SyncTestExtensionType type,
     83       const GURL& update_url,
     84       const GURL& launch_url,
     85       Manifest::Location location,
     86       const base::FilePath& extension_path,
     87       int creation_flags) {
     88     return MakeSyncTestExtensionWithPluginPermission(
     89         type, update_url, launch_url, location, extension_path,
     90         creation_flags, -1, false, "");
     91   }
     92 
     93   static const char kValidUpdateUrl1[];
     94   static const char kValidUpdateUrl2[];
     95 };
     96 
     97 const char ExtensionSyncTypeTest::kValidUpdateUrl1[] =
     98     "http://clients2.google.com/service/update2/crx";
     99 const char ExtensionSyncTypeTest::kValidUpdateUrl2[] =
    100     "https://clients2.google.com/service/update2/crx";
    101 
    102 TEST_F(ExtensionSyncTypeTest, NormalExtensionNoUpdateUrl) {
    103   scoped_refptr<Extension> extension(
    104       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
    105                             Manifest::INTERNAL, base::FilePath(),
    106                             Extension::NO_FLAGS));
    107   EXPECT_TRUE(sync_helper::IsSyncableExtension(extension.get()));
    108 }
    109 
    110 TEST_F(ExtensionSyncTypeTest, UserScriptValidUpdateUrl) {
    111   scoped_refptr<Extension> extension(
    112       MakeSyncTestExtension(USER_SCRIPT, GURL(kValidUpdateUrl1), GURL(),
    113                             Manifest::INTERNAL, base::FilePath(),
    114                             Extension::NO_FLAGS));
    115   EXPECT_TRUE(sync_helper::IsSyncableExtension(extension.get()));
    116 }
    117 
    118 TEST_F(ExtensionSyncTypeTest, UserScriptNoUpdateUrl) {
    119   scoped_refptr<Extension> extension(
    120       MakeSyncTestExtension(USER_SCRIPT, GURL(), GURL(),
    121                             Manifest::INTERNAL, base::FilePath(),
    122                             Extension::NO_FLAGS));
    123   EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
    124 }
    125 
    126 TEST_F(ExtensionSyncTypeTest, ThemeNoUpdateUrl) {
    127   scoped_refptr<Extension> extension(
    128       MakeSyncTestExtension(THEME, GURL(), GURL(),
    129                             Manifest::INTERNAL, base::FilePath(),
    130                             Extension::NO_FLAGS));
    131   EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
    132   EXPECT_FALSE(sync_helper::IsSyncableApp(extension.get()));
    133 }
    134 
    135 TEST_F(ExtensionSyncTypeTest, AppWithLaunchUrl) {
    136   scoped_refptr<Extension> extension(
    137       MakeSyncTestExtension(EXTENSION, GURL(), GURL("http://www.google.com"),
    138                             Manifest::INTERNAL, base::FilePath(),
    139                             Extension::NO_FLAGS));
    140   EXPECT_TRUE(sync_helper::IsSyncableApp(extension.get()));
    141 }
    142 
    143 TEST_F(ExtensionSyncTypeTest, ExtensionExternal) {
    144   scoped_refptr<Extension> extension(
    145       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
    146                             Manifest::EXTERNAL_PREF, base::FilePath(),
    147                             Extension::NO_FLAGS));
    148   EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
    149 }
    150 
    151 TEST_F(ExtensionSyncTypeTest, UserScriptThirdPartyUpdateUrl) {
    152   scoped_refptr<Extension> extension(
    153       MakeSyncTestExtension(
    154           USER_SCRIPT, GURL("http://third-party.update_url.com"), GURL(),
    155           Manifest::INTERNAL, base::FilePath(), Extension::NO_FLAGS));
    156   EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
    157 }
    158 
    159 TEST_F(ExtensionSyncTypeTest, OnlyDisplayAppsInLauncher) {
    160   scoped_refptr<Extension> extension(
    161       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
    162                             Manifest::INTERNAL, base::FilePath(),
    163                             Extension::NO_FLAGS));
    164 
    165   EXPECT_FALSE(extension->ShouldDisplayInAppLauncher());
    166   EXPECT_FALSE(extension->ShouldDisplayInNewTabPage());
    167 
    168   scoped_refptr<Extension> app(
    169       MakeSyncTestExtension(APP, GURL(), GURL("http://www.google.com"),
    170                             Manifest::INTERNAL, base::FilePath(),
    171                             Extension::NO_FLAGS));
    172   EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
    173   EXPECT_TRUE(app->ShouldDisplayInNewTabPage());
    174 }
    175 
    176 TEST_F(ExtensionSyncTypeTest, DisplayInXManifestProperties) {
    177   base::DictionaryValue manifest;
    178   manifest.SetString(keys::kName, "TestComponentApp");
    179   manifest.SetString(keys::kVersion, "0.0.0.0");
    180   manifest.SetString(keys::kApp, "true");
    181   manifest.SetString(keys::kPlatformAppBackgroundPage, std::string());
    182 
    183   std::string error;
    184   scoped_refptr<Extension> app;
    185 
    186   // Default to true.
    187   app = Extension::Create(
    188       base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
    189   EXPECT_EQ(error, std::string());
    190   EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
    191   EXPECT_TRUE(app->ShouldDisplayInNewTabPage());
    192 
    193   // Value display_in_NTP defaults to display_in_launcher.
    194   manifest.SetBoolean(keys::kDisplayInLauncher, false);
    195   app = Extension::Create(
    196       base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
    197   EXPECT_EQ(error, std::string());
    198   EXPECT_FALSE(app->ShouldDisplayInAppLauncher());
    199   EXPECT_FALSE(app->ShouldDisplayInNewTabPage());
    200 
    201   // Value display_in_NTP = true overriding display_in_launcher = false.
    202   manifest.SetBoolean(keys::kDisplayInNewTabPage, true);
    203   app = Extension::Create(
    204       base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
    205   EXPECT_EQ(error, std::string());
    206   EXPECT_FALSE(app->ShouldDisplayInAppLauncher());
    207   EXPECT_TRUE(app->ShouldDisplayInNewTabPage());
    208 
    209   // Value display_in_NTP = false only, overrides default = true.
    210   manifest.Remove(keys::kDisplayInLauncher, NULL);
    211   manifest.SetBoolean(keys::kDisplayInNewTabPage, false);
    212   app = Extension::Create(
    213       base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
    214   EXPECT_EQ(error, std::string());
    215   EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
    216   EXPECT_FALSE(app->ShouldDisplayInNewTabPage());
    217 
    218   // Error checking.
    219   manifest.SetString(keys::kDisplayInNewTabPage, "invalid");
    220   app = Extension::Create(
    221       base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
    222   EXPECT_EQ(error, std::string(errors::kInvalidDisplayInNewTabPage));
    223 }
    224 
    225 TEST_F(ExtensionSyncTypeTest, OnlySyncInternal) {
    226   scoped_refptr<Extension> extension_internal(
    227       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
    228                             Manifest::INTERNAL, base::FilePath(),
    229                             Extension::NO_FLAGS));
    230   EXPECT_TRUE(sync_helper::IsSyncable(extension_internal.get()));
    231 
    232   scoped_refptr<Extension> extension_noninternal(
    233       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
    234                             Manifest::COMPONENT, base::FilePath(),
    235                             Extension::NO_FLAGS));
    236   EXPECT_FALSE(sync_helper::IsSyncable(extension_noninternal.get()));
    237 }
    238 
    239 TEST_F(ExtensionSyncTypeTest, DontSyncDefault) {
    240   scoped_refptr<Extension> extension_default(
    241       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
    242                             Manifest::INTERNAL, base::FilePath(),
    243                             Extension::WAS_INSTALLED_BY_DEFAULT));
    244   EXPECT_FALSE(sync_helper::IsSyncable(extension_default.get()));
    245 }
    246 
    247 // These plugin tests don't make sense on Chrome OS, where extension plugins
    248 // are not allowed.
    249 #if !defined(OS_CHROMEOS)
    250 TEST_F(ExtensionSyncTypeTest, ExtensionWithEmptyPlugins) {
    251   scoped_refptr<Extension> extension(
    252       MakeSyncTestExtensionWithPluginPermission(
    253           EXTENSION, GURL(), GURL(),
    254           Manifest::INTERNAL, base::FilePath(),
    255           Extension::NO_FLAGS, 0, false, ""));
    256   if (extension.get())
    257     EXPECT_TRUE(sync_helper::IsSyncableExtension(extension.get()));
    258 }
    259 
    260 TEST_F(ExtensionSyncTypeTest, ExtensionWithPlugin) {
    261   scoped_refptr<Extension> extension(
    262       MakeSyncTestExtensionWithPluginPermission(
    263           EXTENSION, GURL(), GURL(),
    264           Manifest::INTERNAL, base::FilePath(),
    265           Extension::NO_FLAGS, 1, false, ""));
    266   if (extension.get())
    267     EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
    268 }
    269 
    270 TEST_F(ExtensionSyncTypeTest, ExtensionWithTwoPlugins) {
    271   scoped_refptr<Extension> extension(
    272       MakeSyncTestExtensionWithPluginPermission(
    273           EXTENSION, GURL(), GURL(),
    274           Manifest::INTERNAL, base::FilePath(),
    275           Extension::NO_FLAGS, 2, false, ""));
    276   if (extension.get())
    277     EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
    278 }
    279 
    280 TEST_F(ExtensionSyncTypeTest, ExtensionWithPluginPermission) {
    281   // Specifying the "plugin" permission in the manifest is an error.
    282   scoped_refptr<Extension> extension(
    283       MakeSyncTestExtensionWithPluginPermission(
    284           EXTENSION, GURL(), GURL(),
    285           Manifest::INTERNAL, base::FilePath(),
    286           Extension::NO_FLAGS, 0, true,
    287           ErrorUtils::FormatErrorMessage(
    288               errors::kPermissionNotAllowedInManifest, "plugin")));
    289 }
    290 
    291 #endif // !defined(OS_CHROMEOS)
    292 
    293 }  // namespace extensions
    294