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.
5 #include "chrome/browser/plugins/plugin_info_message_filter.h"
7 #include "base/at_exit.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"
25 using content::PluginService;
29 void PluginsLoaded(const base::Closure& callback,
30 const std::vector<content::WebPluginInfo>& plugins) {
34 class FakePluginServiceFilter : public content::PluginServiceFilter {
36 FakePluginServiceFilter() {}
37 virtual ~FakePluginServiceFilter() {}
39 virtual bool IsPluginAvailable(int render_process_id,
43 const GURL& policy_url,
44 content::WebPluginInfo* plugin) OVERRIDE;
46 virtual bool CanLoadPlugin(int render_process_id,
47 const base::FilePath& path) OVERRIDE;
49 void set_plugin_enabled(const base::FilePath& plugin_path, bool enabled) {
50 plugin_state_[plugin_path] = enabled;
54 std::map<base::FilePath, bool> plugin_state_;
57 bool FakePluginServiceFilter::IsPluginAvailable(
58 int render_process_id,
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() << "'";
73 bool FakePluginServiceFilter::CanLoadPlugin(int render_process_id,
74 const base::FilePath& path) {
80 class PluginInfoMessageFilterTest : public ::testing::Test {
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_) {
88 virtual void SetUp() OVERRIDE {
89 content::WebPluginInfo foo_plugin(base::ASCIIToUTF16("Foo Plug-in"),
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);
100 content::WebPluginInfo bar_plugin(base::ASCIIToUTF16("Bar Plug-in"),
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);
109 PluginService::GetInstance()->SetFilter(&filter_);
112 // Can't go out of process in unit tests.
113 content::RenderProcessHost::SetRunRendererInProcess(true);
115 base::RunLoop run_loop;
116 PluginService::GetInstance()->GetPlugins(
117 base::Bind(&PluginsLoaded, run_loop.QuitClosure()));
120 content::RenderProcessHost::SetRunRendererInProcess(false);
125 TestingProfile* profile() {
129 PluginInfoMessageFilter::Context* context() {
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);
150 base::FilePath foo_plugin_path_;
151 base::FilePath bar_plugin_path_;
152 FakePluginServiceFilter filter_;
155 base::ShadowingAtExitManager at_exit_manager_; // Destroys the PluginService.
156 content::TestBrowserThreadBundle test_thread_bundle;
157 TestingProfile profile_;
158 PluginInfoMessageFilter::Context context_;
161 TEST_F(PluginInfoMessageFilterTest, FindEnabledPlugin) {
162 filter_.set_plugin_enabled(foo_plugin_path_, true);
163 filter_.set_plugin_enabled(bar_plugin_path_, true);
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,
171 EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed, status.value);
172 EXPECT_EQ(foo_plugin_path_.value(), plugin.path.value());
175 filter_.set_plugin_enabled(foo_plugin_path_, false);
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,
183 EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed, status.value);
184 EXPECT_EQ(bar_plugin_path_.value(), plugin.path.value());
187 filter_.set_plugin_enabled(bar_plugin_path_, false);
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,
197 EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kDisabled, status.value);
198 EXPECT_EQ(foo_plugin_path_.value(), plugin.path.value());
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,
207 EXPECT_EQ(ChromeViewHostMsg_GetPluginInfo_Status::kNotFound, status.value);
208 EXPECT_EQ(FILE_PATH_LITERAL(""), plugin.path.value());
212 TEST_F(PluginInfoMessageFilterTest, GetPluginContentSetting) {
213 HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
215 // Block plugins by default.
216 map->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS,
217 CONTENT_SETTING_BLOCK);
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,
226 CONTENT_SETTING_ASK);
228 // Allow plugin "foo" on all sites.
229 map->SetContentSetting(ContentSettingsPattern::Wildcard(),
230 ContentSettingsPattern::Wildcard(),
231 CONTENT_SETTINGS_TYPE_PLUGINS,
233 CONTENT_SETTING_ALLOW);
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,
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"));
247 // "foo" is allowed everywhere.
248 VerifyPluginContentSetting(host, "foo", CONTENT_SETTING_ALLOW, false, false);
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);
254 // Otherwise, use the default.
255 VerifyPluginContentSetting(unmatched_host, "bar", CONTENT_SETTING_BLOCK,
258 // Block plugins via policy.
259 TestingPrefServiceSyncable* prefs = profile()->GetTestingPrefService();
260 prefs->SetManagedPref(prefs::kManagedDefaultPluginsSetting,
261 new base::FundamentalValue(CONTENT_SETTING_BLOCK));
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,