Home | History | Annotate | Download | only in plugins
      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 "chrome/browser/plugins/plugin_info_message_filter.h"
      6 
      7 #include "base/at_exit.h"
      8 #include "base/bind.h"
      9 #include "base/bind_helpers.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/run_loop.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "chrome/browser/content_settings/host_content_settings_map.h"
     14 #include "chrome/common/pref_names.h"
     15 #include "chrome/common/render_messages.h"
     16 #include "chrome/test/base/testing_pref_service_syncable.h"
     17 #include "chrome/test/base/testing_profile.h"
     18 #include "content/public/browser/plugin_service.h"
     19 #include "content/public/browser/plugin_service_filter.h"
     20 #include "content/public/browser/render_process_host.h"
     21 #include "content/public/test/test_browser_thread_bundle.h"
     22 #include "testing/gmock/include/gmock/gmock.h"
     23 #include "testing/gtest/include/gtest/gtest.h"
     24 
     25 using content::PluginService;
     26 
     27 namespace {
     28 
     29 void PluginsLoaded(const base::Closure& callback,
     30                    const std::vector<content::WebPluginInfo>& plugins) {
     31   callback.Run();
     32 }
     33 
     34 class FakePluginServiceFilter : public content::PluginServiceFilter {
     35  public:
     36   FakePluginServiceFilter() {}
     37   virtual ~FakePluginServiceFilter() {}
     38 
     39   virtual bool IsPluginAvailable(int render_process_id,
     40                                  int render_view_id,
     41                                  const void* context,
     42                                  const GURL& url,
     43                                  const GURL& policy_url,
     44                                  content::WebPluginInfo* plugin) OVERRIDE;
     45 
     46   virtual bool CanLoadPlugin(int render_process_id,
     47                              const base::FilePath& path) OVERRIDE;
     48 
     49   void set_plugin_enabled(const base::FilePath& plugin_path, bool enabled) {
     50     plugin_state_[plugin_path] = enabled;
     51   }
     52 
     53  private:
     54   std::map<base::FilePath, bool> plugin_state_;
     55 };
     56 
     57 bool FakePluginServiceFilter::IsPluginAvailable(
     58     int render_process_id,
     59     int render_view_id,
     60     const void* context,
     61     const GURL& url,
     62     const GURL& policy_url,
     63     content::WebPluginInfo* plugin) {
     64   std::map<base::FilePath, bool>::iterator it =
     65       plugin_state_.find(plugin->path);
     66   if (it == plugin_state_.end()) {
     67     ADD_FAILURE() << "No plug-in state for '" << plugin->path.value() << "'";
     68     return false;
     69   }
     70   return it->second;
     71 }
     72 
     73 bool FakePluginServiceFilter::CanLoadPlugin(int render_process_id,
     74                                             const base::FilePath& path) {
     75   return true;
     76 }
     77 
     78 }  // namespace
     79 
     80 class PluginInfoMessageFilterTest : public ::testing::Test {
     81  public:
     82   PluginInfoMessageFilterTest() :
     83       foo_plugin_path_(FILE_PATH_LITERAL("/path/to/foo")),
     84       bar_plugin_path_(FILE_PATH_LITERAL("/path/to/bar")),
     85       context_(0, &profile_) {
     86   }
     87 
     88   virtual void SetUp() OVERRIDE {
     89     content::WebPluginInfo foo_plugin(base::ASCIIToUTF16("Foo Plug-in"),
     90                                       foo_plugin_path_,
     91                                       base::ASCIIToUTF16("1"),
     92                                       base::ASCIIToUTF16("The Foo plug-in."));
     93     content::WebPluginMimeType mime_type;
     94     mime_type.mime_type = "foo/bar";
     95     foo_plugin.mime_types.push_back(mime_type);
     96     foo_plugin.type = content::WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS;
     97     PluginService::GetInstance()->Init();
     98     PluginService::GetInstance()->RegisterInternalPlugin(foo_plugin, false);
     99 
    100     content::WebPluginInfo bar_plugin(base::ASCIIToUTF16("Bar Plug-in"),
    101                                       bar_plugin_path_,
    102                                       base::ASCIIToUTF16("1"),
    103                                       base::ASCIIToUTF16("The Bar plug-in."));
    104     mime_type.mime_type = "foo/bar";
    105     bar_plugin.mime_types.push_back(mime_type);
    106     bar_plugin.type = content::WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS;
    107     PluginService::GetInstance()->RegisterInternalPlugin(bar_plugin, false);
    108 
    109     PluginService::GetInstance()->SetFilter(&filter_);
    110 
    111 #if !defined(OS_WIN)
    112     // Can't go out of process in unit tests.
    113     content::RenderProcessHost::SetRunRendererInProcess(true);
    114 #endif
    115     base::RunLoop run_loop;
    116     PluginService::GetInstance()->GetPlugins(
    117         base::Bind(&PluginsLoaded, run_loop.QuitClosure()));
    118     run_loop.Run();
    119 #if !defined(OS_WIN)
    120     content::RenderProcessHost::SetRunRendererInProcess(false);
    121 #endif
    122   }
    123 
    124  protected:
    125   TestingProfile* profile() {
    126     return &profile_;
    127   }
    128 
    129   PluginInfoMessageFilter::Context* context() {
    130     return &context_;
    131   }
    132 
    133   void VerifyPluginContentSetting(const GURL& url,
    134                                   const std::string& plugin,
    135                                   ContentSetting expected_setting,
    136                                   bool expected_is_default,
    137                                   bool expected_is_managed) {
    138     ContentSetting setting = expected_setting == CONTENT_SETTING_DEFAULT ?
    139         CONTENT_SETTING_BLOCK : CONTENT_SETTING_DEFAULT;
    140     bool is_default = !expected_is_default;
    141     bool is_managed = !expected_is_managed;
    142     context()->GetPluginContentSetting(
    143         content::WebPluginInfo(), url, url, plugin,
    144         &setting, &is_default, &is_managed);
    145     EXPECT_EQ(expected_setting, setting);
    146     EXPECT_EQ(expected_is_default, is_default);
    147     EXPECT_EQ(expected_is_managed, is_managed);
    148   }
    149 
    150   base::FilePath foo_plugin_path_;
    151   base::FilePath bar_plugin_path_;
    152   FakePluginServiceFilter filter_;
    153 
    154  private:
    155   base::ShadowingAtExitManager at_exit_manager_;  // Destroys the PluginService.
    156   content::TestBrowserThreadBundle test_thread_bundle;
    157   TestingProfile profile_;
    158   PluginInfoMessageFilter::Context context_;
    159 };
    160 
    161 TEST_F(PluginInfoMessageFilterTest, FindEnabledPlugin) {
    162   filter_.set_plugin_enabled(foo_plugin_path_, true);
    163   filter_.set_plugin_enabled(bar_plugin_path_, true);
    164   {
    165     ChromeViewHostMsg_GetPluginInfo_Status status;
    166     content::WebPluginInfo plugin;
    167     std::string actual_mime_type;
    168     EXPECT_TRUE(context()->FindEnabledPlugin(
    169         0, GURL(), GURL(), "foo/bar", &status, &plugin, &actual_mime_type,
    170         NULL));
    171     EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed, status.value);
    172     EXPECT_EQ(foo_plugin_path_.value(), plugin.path.value());
    173   }
    174 
    175   filter_.set_plugin_enabled(foo_plugin_path_, false);
    176   {
    177     ChromeViewHostMsg_GetPluginInfo_Status status;
    178     content::WebPluginInfo plugin;
    179     std::string actual_mime_type;
    180     EXPECT_TRUE(context()->FindEnabledPlugin(
    181         0, GURL(), GURL(), "foo/bar", &status, &plugin, &actual_mime_type,
    182         NULL));
    183     EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed, status.value);
    184     EXPECT_EQ(bar_plugin_path_.value(), plugin.path.value());
    185   }
    186 
    187   filter_.set_plugin_enabled(bar_plugin_path_, false);
    188   {
    189     ChromeViewHostMsg_GetPluginInfo_Status status;
    190     content::WebPluginInfo plugin;
    191     std::string actual_mime_type;
    192     std::string identifier;
    193     base::string16 plugin_name;
    194     EXPECT_FALSE(context()->FindEnabledPlugin(
    195         0, GURL(), GURL(), "foo/bar", &status, &plugin, &actual_mime_type,
    196         NULL));
    197     EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kDisabled, status.value);
    198     EXPECT_EQ(foo_plugin_path_.value(), plugin.path.value());
    199   }
    200   {
    201     ChromeViewHostMsg_GetPluginInfo_Status status;
    202     content::WebPluginInfo plugin;
    203     std::string actual_mime_type;
    204     EXPECT_FALSE(context()->FindEnabledPlugin(
    205         0, GURL(), GURL(), "baz/blurp", &status, &plugin, &actual_mime_type,
    206         NULL));
    207     EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kNotFound, status.value);
    208     EXPECT_EQ(FILE_PATH_LITERAL(""), plugin.path.value());
    209   }
    210 }
    211 
    212 TEST_F(PluginInfoMessageFilterTest, GetPluginContentSetting) {
    213   HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
    214 
    215   // Block plugins by default.
    216   map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
    217                                 CONTENT_SETTING_BLOCK);
    218 
    219   // Set plugins to click-to-play on example.com and subdomains.
    220   ContentSettingsPattern pattern =
    221        ContentSettingsPattern::FromString("[*.]example.com");
    222   map->SetContentSetting(pattern,
    223                          ContentSettingsPattern::Wildcard(),
    224                          CONTENT_SETTINGS_TYPE_PLUGINS,
    225                          std::string(),
    226                          CONTENT_SETTING_ASK);
    227 
    228   // Allow plugin "foo" on all sites.
    229   map->SetContentSetting(ContentSettingsPattern::Wildcard(),
    230                          ContentSettingsPattern::Wildcard(),
    231                          CONTENT_SETTINGS_TYPE_PLUGINS,
    232                          "foo",
    233                          CONTENT_SETTING_ALLOW);
    234 
    235   GURL unmatched_host("https://www.google.com");
    236   GURL host("http://example.com/");
    237   ASSERT_EQ(CONTENT_SETTING_BLOCK, map->GetContentSetting(
    238       unmatched_host, unmatched_host, CONTENT_SETTINGS_TYPE_PLUGINS,
    239       std::string()));
    240   ASSERT_EQ(CONTENT_SETTING_ASK, map->GetContentSetting(
    241       host, host, CONTENT_SETTINGS_TYPE_PLUGINS, std::string()));
    242   ASSERT_EQ(CONTENT_SETTING_ALLOW, map->GetContentSetting(
    243       host, host, CONTENT_SETTINGS_TYPE_PLUGINS, "foo"));
    244   ASSERT_EQ(CONTENT_SETTING_DEFAULT, map->GetContentSetting(
    245       host, host, CONTENT_SETTINGS_TYPE_PLUGINS, "bar"));
    246 
    247   // "foo" is allowed everywhere.
    248   VerifyPluginContentSetting(host, "foo", CONTENT_SETTING_ALLOW, false, false);
    249 
    250   // There is no specific content setting for "bar", so the general setting
    251   // for example.com applies.
    252   VerifyPluginContentSetting(host, "bar", CONTENT_SETTING_ASK, false, false);
    253 
    254   // Otherwise, use the default.
    255   VerifyPluginContentSetting(unmatched_host, "bar", CONTENT_SETTING_BLOCK,
    256                              true, false);
    257 
    258   // Block plugins via policy.
    259   TestingPrefServiceSyncable* prefs = profile()->GetTestingPrefService();
    260   prefs->SetManagedPref(prefs::kManagedDefaultPluginsSetting,
    261                         new base::FundamentalValue(CONTENT_SETTING_BLOCK));
    262 
    263   // All plugins should be blocked now.
    264   VerifyPluginContentSetting(host, "foo", CONTENT_SETTING_BLOCK, true, true);
    265   VerifyPluginContentSetting(host, "bar", CONTENT_SETTING_BLOCK, true, true);
    266   VerifyPluginContentSetting(unmatched_host, "bar", CONTENT_SETTING_BLOCK,
    267                              true, true);
    268 }
    269