1 // Copyright (c) 2012 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_prefs.h"
6
7 #include "base/at_exit.h"
8 #include "base/bind.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/path_service.h"
11 #include "base/run_loop.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/common/chrome_constants.h"
14 #include "chrome/common/chrome_paths.h"
15 #include "content/public/browser/plugin_service.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/common/webplugininfo.h"
18 #include "content/public/test/test_browser_thread.h"
19 #include "content/public/test/test_utils.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using content::BrowserThread;
23 using content::PluginService;
24
25 namespace {
26
CanEnablePluginCallback(const base::Closure & quit_closure,bool expected_can_change,bool did_change)27 void CanEnablePluginCallback(const base::Closure& quit_closure,
28 bool expected_can_change,
29 bool did_change) {
30 EXPECT_EQ(expected_can_change, did_change);
31 quit_closure.Run();
32 }
33
34 #if !(defined(OS_LINUX) && defined(USE_AURA))
GetComponentUpdatedPepperFlashPath(const base::FilePath::StringType & version)35 base::FilePath GetComponentUpdatedPepperFlashPath(
36 const base::FilePath::StringType& version) {
37 base::FilePath path;
38 EXPECT_TRUE(PathService::Get(
39 chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, &path));
40 path = path.Append(version);
41 path = path.Append(chrome::kPepperFlashPluginFilename);
42 return path;
43 }
44
GetBundledPepperFlashPath()45 base::FilePath GetBundledPepperFlashPath() {
46 base::FilePath path;
47 EXPECT_TRUE(PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &path));
48 return path;
49 }
50 #endif // !(defined(OS_LINUX) && defined(USE_AURA))
51
GotPlugins(const base::Closure & quit_closure,const std::vector<content::WebPluginInfo> & plugins)52 void GotPlugins(const base::Closure& quit_closure,
53 const std::vector<content::WebPluginInfo>& plugins) {
54 quit_closure.Run();
55 }
56
57 } // namespace
58
59 class PluginPrefsTest : public ::testing::Test {
60 public:
SetUp()61 virtual void SetUp() OVERRIDE {
62 plugin_prefs_ = new PluginPrefs();
63 }
64
SetPolicyEnforcedPluginPatterns(const std::set<base::string16> & disabled,const std::set<base::string16> & disabled_exceptions,const std::set<base::string16> & enabled)65 void SetPolicyEnforcedPluginPatterns(
66 const std::set<base::string16>& disabled,
67 const std::set<base::string16>& disabled_exceptions,
68 const std::set<base::string16>& enabled) {
69 plugin_prefs_->SetPolicyEnforcedPluginPatterns(
70 disabled, disabled_exceptions, enabled);
71 }
72
73 protected:
EnablePluginSynchronously(bool enabled,const base::FilePath & path,bool expected_can_change)74 void EnablePluginSynchronously(bool enabled,
75 const base::FilePath& path,
76 bool expected_can_change) {
77 base::RunLoop run_loop;
78 plugin_prefs_->EnablePlugin(
79 enabled, path,
80 base::Bind(&CanEnablePluginCallback, run_loop.QuitClosure(),
81 expected_can_change));
82 run_loop.Run();
83 }
84
RefreshPluginsSynchronously()85 void RefreshPluginsSynchronously() {
86 PluginService::GetInstance()->RefreshPlugins();
87 #if !defined(OS_WIN)
88 // Can't go out of process in unit tests.
89 content::RenderProcessHost::SetRunRendererInProcess(true);
90 #endif
91 scoped_refptr<content::MessageLoopRunner> runner =
92 new content::MessageLoopRunner;
93 PluginService::GetInstance()->GetPlugins(
94 base::Bind(&GotPlugins, runner->QuitClosure()));
95 runner->Run();
96 #if !defined(OS_WIN)
97 content::RenderProcessHost::SetRunRendererInProcess(false);
98 #endif
99 }
100
101 scoped_refptr<PluginPrefs> plugin_prefs_;
102 };
103
TEST_F(PluginPrefsTest,DisabledByPolicy)104 TEST_F(PluginPrefsTest, DisabledByPolicy) {
105 std::set<base::string16> disabled_plugins;
106 disabled_plugins.insert(ASCIIToUTF16("Disable this!"));
107 disabled_plugins.insert(ASCIIToUTF16("*Google*"));
108 SetPolicyEnforcedPluginPatterns(disabled_plugins,
109 std::set<base::string16>(),
110 std::set<base::string16>());
111
112 EXPECT_EQ(PluginPrefs::NO_POLICY,
113 plugin_prefs_->PolicyStatusForPlugin(ASCIIToUTF16("42")));
114 EXPECT_EQ(PluginPrefs::POLICY_DISABLED,
115 plugin_prefs_->PolicyStatusForPlugin(
116 ASCIIToUTF16("Disable this!")));
117 EXPECT_EQ(PluginPrefs::POLICY_DISABLED,
118 plugin_prefs_->PolicyStatusForPlugin(ASCIIToUTF16("Google Earth")));
119 }
120
TEST_F(PluginPrefsTest,EnabledByPolicy)121 TEST_F(PluginPrefsTest, EnabledByPolicy) {
122 std::set<base::string16> enabled_plugins;
123 enabled_plugins.insert(ASCIIToUTF16("Enable that!"));
124 enabled_plugins.insert(ASCIIToUTF16("PDF*"));
125 SetPolicyEnforcedPluginPatterns(std::set<base::string16>(),
126 std::set<base::string16>(),
127 enabled_plugins);
128
129 EXPECT_EQ(PluginPrefs::NO_POLICY,
130 plugin_prefs_->PolicyStatusForPlugin(ASCIIToUTF16("42")));
131 EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
132 plugin_prefs_->PolicyStatusForPlugin(ASCIIToUTF16("Enable that!")));
133 EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
134 plugin_prefs_->PolicyStatusForPlugin(ASCIIToUTF16("PDF Reader")));
135 }
136
TEST_F(PluginPrefsTest,EnabledAndDisabledByPolicy)137 TEST_F(PluginPrefsTest, EnabledAndDisabledByPolicy) {
138 const base::string16 k42(ASCIIToUTF16("42"));
139 const base::string16 kEnabled(ASCIIToUTF16("Enabled"));
140 const base::string16 kEnabled2(ASCIIToUTF16("Enabled 2"));
141 const base::string16 kEnabled3(ASCIIToUTF16("Enabled 3"));
142 const base::string16 kException(ASCIIToUTF16("Exception"));
143 const base::string16 kException2(ASCIIToUTF16("Exception 2"));
144 const base::string16 kGoogleMars(ASCIIToUTF16("Google Mars"));
145 const base::string16 kGoogleEarth(ASCIIToUTF16("Google Earth"));
146
147 std::set<base::string16> disabled_plugins;
148 std::set<base::string16> disabled_plugins_exceptions;
149 std::set<base::string16> enabled_plugins;
150
151 disabled_plugins.insert(kEnabled);
152 disabled_plugins_exceptions.insert(kEnabled);
153 enabled_plugins.insert(kEnabled);
154
155 disabled_plugins_exceptions.insert(kException);
156
157 disabled_plugins.insert(kEnabled2);
158 enabled_plugins.insert(kEnabled2);
159
160 disabled_plugins.insert(kException2);
161 disabled_plugins_exceptions.insert(kException2);
162
163 disabled_plugins_exceptions.insert(kEnabled3);
164 enabled_plugins.insert(kEnabled3);
165
166 SetPolicyEnforcedPluginPatterns(disabled_plugins,
167 disabled_plugins_exceptions,
168 enabled_plugins);
169
170 EXPECT_EQ(PluginPrefs::NO_POLICY, plugin_prefs_->PolicyStatusForPlugin(k42));
171
172 EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
173 plugin_prefs_->PolicyStatusForPlugin(kEnabled));
174 EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
175 plugin_prefs_->PolicyStatusForPlugin(kEnabled2));
176 EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
177 plugin_prefs_->PolicyStatusForPlugin(kEnabled3));
178
179 EXPECT_EQ(PluginPrefs::NO_POLICY,
180 plugin_prefs_->PolicyStatusForPlugin(kException));
181 EXPECT_EQ(PluginPrefs::NO_POLICY,
182 plugin_prefs_->PolicyStatusForPlugin(kException2));
183
184 disabled_plugins.clear();
185 disabled_plugins_exceptions.clear();
186 enabled_plugins.clear();
187
188 disabled_plugins.insert(ASCIIToUTF16("*"));
189 disabled_plugins_exceptions.insert(ASCIIToUTF16("*Google*"));
190 enabled_plugins.insert(kGoogleEarth);
191
192 SetPolicyEnforcedPluginPatterns(disabled_plugins,
193 disabled_plugins_exceptions,
194 enabled_plugins);
195
196 EXPECT_EQ(PluginPrefs::POLICY_ENABLED,
197 plugin_prefs_->PolicyStatusForPlugin(kGoogleEarth));
198 EXPECT_EQ(PluginPrefs::NO_POLICY,
199 plugin_prefs_->PolicyStatusForPlugin(kGoogleMars));
200 EXPECT_EQ(PluginPrefs::POLICY_DISABLED,
201 plugin_prefs_->PolicyStatusForPlugin(k42));
202 }
203
204 // Linux Aura doesn't support NPAPI.
205 #if !(defined(OS_LINUX) && defined(USE_AURA))
206
TEST_F(PluginPrefsTest,UnifiedPepperFlashState)207 TEST_F(PluginPrefsTest, UnifiedPepperFlashState) {
208 base::ShadowingAtExitManager at_exit_manager_; // Destroys the PluginService.
209
210 base::MessageLoop message_loop;
211 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
212 PluginService::GetInstance()->Init();
213 PluginService::GetInstance()->DisablePluginsDiscoveryForTesting();
214
215 base::string16 component_updated_plugin_name(
216 ASCIIToUTF16("Component-updated Pepper Flash"));
217 content::WebPluginInfo component_updated_plugin_1(
218 component_updated_plugin_name,
219 GetComponentUpdatedPepperFlashPath(FILE_PATH_LITERAL("11.3.31.227")),
220 ASCIIToUTF16("11.3.31.227"),
221 ASCIIToUTF16(""));
222 content::WebPluginInfo component_updated_plugin_2(
223 component_updated_plugin_name,
224 GetComponentUpdatedPepperFlashPath(FILE_PATH_LITERAL("11.3.31.228")),
225 ASCIIToUTF16("11.3.31.228"),
226 ASCIIToUTF16(""));
227 content::WebPluginInfo bundled_plugin(ASCIIToUTF16("Pepper Flash"),
228 GetBundledPepperFlashPath(),
229 ASCIIToUTF16("11.3.31.229"),
230 ASCIIToUTF16(""));
231
232 PluginService::GetInstance()->RegisterInternalPlugin(
233 component_updated_plugin_1, false);
234 PluginService::GetInstance()->RegisterInternalPlugin(
235 component_updated_plugin_2, false);
236 PluginService::GetInstance()->RegisterInternalPlugin(bundled_plugin, false);
237
238 RefreshPluginsSynchronously();
239
240 // Set the state of any of the three plugins will affect the others.
241 EnablePluginSynchronously(true, component_updated_plugin_1.path, true);
242 EXPECT_TRUE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_1));
243 EXPECT_TRUE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_2));
244 EXPECT_TRUE(plugin_prefs_->IsPluginEnabled(bundled_plugin));
245
246 EnablePluginSynchronously(false, bundled_plugin.path, true);
247 EXPECT_FALSE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_1));
248 EXPECT_FALSE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_2));
249 EXPECT_FALSE(plugin_prefs_->IsPluginEnabled(bundled_plugin));
250
251 EnablePluginSynchronously(true, component_updated_plugin_2.path, true);
252 EXPECT_TRUE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_1));
253 EXPECT_TRUE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_2));
254 EXPECT_TRUE(plugin_prefs_->IsPluginEnabled(bundled_plugin));
255
256 std::set<base::string16> disabled_plugins;
257 disabled_plugins.insert(component_updated_plugin_name);
258 SetPolicyEnforcedPluginPatterns(disabled_plugins,
259 std::set<base::string16>(),
260 std::set<base::string16>());
261
262 // Policy settings should be respected.
263 EXPECT_FALSE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_1));
264 EXPECT_FALSE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_2));
265 EXPECT_TRUE(plugin_prefs_->IsPluginEnabled(bundled_plugin));
266
267 EnablePluginSynchronously(false, bundled_plugin.path, true);
268 EXPECT_FALSE(plugin_prefs_->IsPluginEnabled(bundled_plugin));
269
270 // Trying to change the state of a policy-enforced plugin should not take
271 // effect. And it shouldn't change the state of other plugins either, even if
272 // they are not restricted by any policy.
273 EnablePluginSynchronously(true, component_updated_plugin_1.path, false);
274 EXPECT_FALSE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_1));
275 EXPECT_FALSE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_2));
276 EXPECT_FALSE(plugin_prefs_->IsPluginEnabled(bundled_plugin));
277
278 EnablePluginSynchronously(true, bundled_plugin.path, true);
279 EXPECT_FALSE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_1));
280 EXPECT_FALSE(plugin_prefs_->IsPluginEnabled(component_updated_plugin_2));
281 EXPECT_TRUE(plugin_prefs_->IsPluginEnabled(bundled_plugin));
282 }
283
284 #endif
285