OLD | NEW |
| (Empty) |
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/plugin_prefs.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/command_line.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/path_service.h" | |
13 #include "base/string_util.h" | |
14 #include "base/utf_string_conversions.h" | |
15 #include "base/values.h" | |
16 #include "build/build_config.h" | |
17 #include "chrome/browser/plugin_installer.h" | |
18 #include "chrome/browser/plugin_prefs_factory.h" | |
19 #include "chrome/browser/prefs/scoped_user_pref_update.h" | |
20 #include "chrome/browser/profiles/profile.h" | |
21 #include "chrome/browser/profiles/profile_keyed_service.h" | |
22 #include "chrome/common/chrome_constants.h" | |
23 #include "chrome/common/chrome_content_client.h" | |
24 #include "chrome/common/chrome_notification_types.h" | |
25 #include "chrome/common/chrome_paths.h" | |
26 #include "chrome/common/chrome_switches.h" | |
27 #include "chrome/common/pref_names.h" | |
28 #include "content/public/browser/browser_thread.h" | |
29 #include "content/public/browser/notification_service.h" | |
30 #include "content/public/browser/plugin_service.h" | |
31 #include "webkit/plugins/npapi/plugin_group.h" | |
32 #include "webkit/plugins/npapi/plugin_list.h" | |
33 #include "webkit/plugins/webplugininfo.h" | |
34 | |
35 using content::BrowserThread; | |
36 using content::PluginService; | |
37 | |
38 namespace { | |
39 | |
40 // How long to wait to save the plugin enabled information, which might need to | |
41 // go to disk. | |
42 const int64 kPluginUpdateDelayMs = 60 * 1000; | |
43 | |
44 } // namespace | |
45 | |
46 PluginPrefs::PluginState::PluginState() { | |
47 } | |
48 | |
49 PluginPrefs::PluginState::~PluginState() { | |
50 } | |
51 | |
52 bool PluginPrefs::PluginState::Get(const FilePath& plugin, | |
53 bool* enabled) const { | |
54 FilePath key = ConvertMapKey(plugin); | |
55 std::map<FilePath, bool>::const_iterator iter = state_.find(key); | |
56 if (iter != state_.end()) { | |
57 *enabled = iter->second; | |
58 return true; | |
59 } | |
60 return false; | |
61 } | |
62 | |
63 void PluginPrefs::PluginState::Set(const FilePath& plugin, bool enabled) { | |
64 state_[ConvertMapKey(plugin)] = enabled; | |
65 } | |
66 | |
67 void PluginPrefs::PluginState::SetIgnorePseudoKey(const FilePath& plugin, | |
68 bool enabled) { | |
69 FilePath key = ConvertMapKey(plugin); | |
70 if (key == plugin) | |
71 state_[key] = enabled; | |
72 } | |
73 | |
74 FilePath PluginPrefs::PluginState::ConvertMapKey(const FilePath& plugin) const { | |
75 // Keep the state of component-updated and bundled Pepper Flash in sync. | |
76 if (plugin.BaseName().value() == chrome::kPepperFlashPluginFilename) { | |
77 FilePath component_updated_pepper_flash_dir; | |
78 if (PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN, | |
79 &component_updated_pepper_flash_dir) && | |
80 component_updated_pepper_flash_dir.IsParent(plugin)) { | |
81 FilePath bundled_pepper_flash; | |
82 if (PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, | |
83 &bundled_pepper_flash)) { | |
84 return bundled_pepper_flash; | |
85 } | |
86 } | |
87 } | |
88 | |
89 return plugin; | |
90 } | |
91 | |
92 // static | |
93 scoped_refptr<PluginPrefs> PluginPrefs::GetForProfile(Profile* profile) { | |
94 return PluginPrefsFactory::GetPrefsForProfile(profile); | |
95 } | |
96 | |
97 // static | |
98 scoped_refptr<PluginPrefs> PluginPrefs::GetForTestingProfile( | |
99 Profile* profile) { | |
100 return static_cast<PluginPrefs*>( | |
101 PluginPrefsFactory::GetInstance()->SetTestingFactoryAndUse( | |
102 profile, &PluginPrefsFactory::CreateForTestingProfile).get()); | |
103 } | |
104 | |
105 void PluginPrefs::SetPluginListForTesting( | |
106 webkit::npapi::PluginList* plugin_list) { | |
107 plugin_list_ = plugin_list; | |
108 } | |
109 | |
110 void PluginPrefs::EnablePluginGroup(bool enabled, const string16& group_name) { | |
111 PluginFinder::Get( | |
112 base::Bind(&PluginPrefs::GetPluginFinderForEnablePluginGroup, | |
113 this, enabled, group_name)); | |
114 } | |
115 | |
116 void PluginPrefs::GetPluginFinderForEnablePluginGroup( | |
117 bool enabled, | |
118 const string16& group_name, | |
119 PluginFinder* finder) { | |
120 PluginService::GetInstance()->GetPlugins( | |
121 base::Bind(&PluginPrefs::EnablePluginGroupInternal, | |
122 this, enabled, group_name, finder)); | |
123 } | |
124 | |
125 void PluginPrefs::EnablePluginGroupInternal( | |
126 bool enabled, | |
127 const string16& group_name, | |
128 PluginFinder* finder, | |
129 const std::vector<webkit::WebPluginInfo>& plugins) { | |
130 base::AutoLock auto_lock(lock_); | |
131 | |
132 // Set the desired state for the group. | |
133 plugin_group_state_[group_name] = enabled; | |
134 | |
135 // Update the state for all plug-ins in the group. | |
136 for (size_t i = 0; i < plugins.size(); ++i) { | |
137 PluginInstaller* installer = finder->GetPluginInstaller(plugins[i]); | |
138 if (group_name != installer->name()) | |
139 continue; | |
140 plugin_state_.Set(plugins[i].path, enabled); | |
141 } | |
142 | |
143 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
144 base::Bind(&PluginPrefs::OnUpdatePreferences, this, plugins, finder)); | |
145 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
146 base::Bind(&PluginPrefs::NotifyPluginStatusChanged, this)); | |
147 } | |
148 | |
149 void PluginPrefs::EnablePluginIfPossibleCallback( | |
150 bool enabled, const FilePath& path, | |
151 const base::Callback<void(bool)>& callback, | |
152 PluginFinder* finder) { | |
153 webkit::WebPluginInfo plugin; | |
154 bool can_enable = true; | |
155 if (PluginService::GetInstance()->GetPluginInfoByPath(path, &plugin)) { | |
156 PluginInstaller* installer = finder->GetPluginInstaller(plugin); | |
157 PolicyStatus plugin_status = PolicyStatusForPlugin(plugin.name); | |
158 PolicyStatus group_status = PolicyStatusForPlugin(installer->name()); | |
159 if (enabled) { | |
160 if (plugin_status == POLICY_DISABLED || group_status == POLICY_DISABLED) | |
161 can_enable = false; | |
162 } else { | |
163 if (plugin_status == POLICY_ENABLED || group_status == POLICY_ENABLED) | |
164 can_enable = false; | |
165 } | |
166 } else { | |
167 NOTREACHED(); | |
168 } | |
169 | |
170 if (!can_enable) { | |
171 callback.Run(false); | |
172 return; | |
173 } | |
174 | |
175 PluginService::GetInstance()->GetPlugins( | |
176 base::Bind(&PluginPrefs::EnablePluginInternal, this, | |
177 enabled, path, finder, callback)); | |
178 } | |
179 | |
180 void PluginPrefs::EnablePlugin( | |
181 bool enabled, const FilePath& path, | |
182 const base::Callback<void(bool)>& callback) { | |
183 PluginFinder::Get(base::Bind(&PluginPrefs::EnablePluginIfPossibleCallback, | |
184 this, enabled, path, callback)); | |
185 } | |
186 | |
187 void PluginPrefs::EnablePluginInternal( | |
188 bool enabled, | |
189 const FilePath& path, | |
190 PluginFinder* plugin_finder, | |
191 const base::Callback<void(bool)>& callback, | |
192 const std::vector<webkit::WebPluginInfo>& plugins) { | |
193 { | |
194 // Set the desired state for the plug-in. | |
195 base::AutoLock auto_lock(lock_); | |
196 plugin_state_.Set(path, enabled); | |
197 } | |
198 | |
199 string16 group_name; | |
200 for (size_t i = 0; i < plugins.size(); ++i) { | |
201 if (plugins[i].path == path) { | |
202 PluginInstaller* installer = | |
203 plugin_finder->GetPluginInstaller(plugins[i]); | |
204 // set the group name for this plug-in. | |
205 group_name = installer->name(); | |
206 DCHECK_EQ(enabled, IsPluginEnabled(plugins[i])); | |
207 break; | |
208 } | |
209 } | |
210 | |
211 bool all_disabled = true; | |
212 for (size_t i = 0; i < plugins.size(); ++i) { | |
213 PluginInstaller* installer = plugin_finder->GetPluginInstaller(plugins[i]); | |
214 DCHECK(!installer->name().empty()); | |
215 if (group_name == installer->name()) { | |
216 all_disabled = all_disabled && !IsPluginEnabled(plugins[i]); | |
217 } | |
218 } | |
219 | |
220 if (!group_name.empty()) { | |
221 // Update the state for the corresponding plug-in group. | |
222 base::AutoLock auto_lock(lock_); | |
223 plugin_group_state_[group_name] = !all_disabled; | |
224 } | |
225 | |
226 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
227 base::Bind(&PluginPrefs::OnUpdatePreferences, this, | |
228 plugins, plugin_finder)); | |
229 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
230 base::Bind(&PluginPrefs::NotifyPluginStatusChanged, this)); | |
231 callback.Run(true); | |
232 } | |
233 | |
234 PluginPrefs::PolicyStatus PluginPrefs::PolicyStatusForPlugin( | |
235 const string16& name) const { | |
236 base::AutoLock auto_lock(lock_); | |
237 if (IsStringMatchedInSet(name, policy_enabled_plugin_patterns_)) { | |
238 return POLICY_ENABLED; | |
239 } else if (IsStringMatchedInSet(name, policy_disabled_plugin_patterns_) && | |
240 !IsStringMatchedInSet( | |
241 name, policy_disabled_plugin_exception_patterns_)) { | |
242 return POLICY_DISABLED; | |
243 } else { | |
244 return NO_POLICY; | |
245 } | |
246 } | |
247 | |
248 bool PluginPrefs::IsPluginEnabled(const webkit::WebPluginInfo& plugin) const { | |
249 scoped_ptr<webkit::npapi::PluginGroup> group( | |
250 GetPluginList()->GetPluginGroup(plugin)); | |
251 string16 group_name = group->GetGroupName(); | |
252 | |
253 // Check if the plug-in or its group is enabled by policy. | |
254 PolicyStatus plugin_status = PolicyStatusForPlugin(plugin.name); | |
255 PolicyStatus group_status = PolicyStatusForPlugin(group_name); | |
256 if (plugin_status == POLICY_ENABLED || group_status == POLICY_ENABLED) | |
257 return true; | |
258 | |
259 // Check if the plug-in or its group is disabled by policy. | |
260 if (plugin_status == POLICY_DISABLED || group_status == POLICY_DISABLED) | |
261 return false; | |
262 | |
263 // If enabling NaCl, make sure the plugin is also enabled. See bug | |
264 // http://code.google.com/p/chromium/issues/detail?id=81010 for more | |
265 // information. | |
266 // TODO(dspringer): When NaCl is on by default, remove this code. | |
267 if ((plugin.name == | |
268 ASCIIToUTF16(chrome::ChromeContentClient::kNaClPluginName)) && | |
269 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaCl)) { | |
270 return true; | |
271 } | |
272 | |
273 base::AutoLock auto_lock(lock_); | |
274 // Check user preferences for the plug-in. | |
275 bool plugin_enabled = false; | |
276 if (plugin_state_.Get(plugin.path, &plugin_enabled)) | |
277 return plugin_enabled; | |
278 | |
279 // Check user preferences for the plug-in group. | |
280 std::map<string16, bool>::const_iterator group_it( | |
281 plugin_group_state_.find(plugin.name)); | |
282 if (group_it != plugin_group_state_.end()) | |
283 return group_it->second; | |
284 | |
285 // Default to enabled. | |
286 return true; | |
287 } | |
288 | |
289 void PluginPrefs::Observe(int type, | |
290 const content::NotificationSource& source, | |
291 const content::NotificationDetails& details) { | |
292 DCHECK_EQ(chrome::NOTIFICATION_PREF_CHANGED, type); | |
293 const std::string* pref_name = content::Details<std::string>(details).ptr(); | |
294 if (!pref_name) { | |
295 NOTREACHED(); | |
296 return; | |
297 } | |
298 DCHECK_EQ(prefs_, content::Source<PrefService>(source).ptr()); | |
299 if (*pref_name == prefs::kPluginsDisabledPlugins) { | |
300 base::AutoLock auto_lock(lock_); | |
301 ListValueToStringSet(prefs_->GetList(prefs::kPluginsDisabledPlugins), | |
302 &policy_disabled_plugin_patterns_); | |
303 } else if (*pref_name == prefs::kPluginsDisabledPluginsExceptions) { | |
304 base::AutoLock auto_lock(lock_); | |
305 ListValueToStringSet( | |
306 prefs_->GetList(prefs::kPluginsDisabledPluginsExceptions), | |
307 &policy_disabled_plugin_exception_patterns_); | |
308 } else if (*pref_name == prefs::kPluginsEnabledPlugins) { | |
309 base::AutoLock auto_lock(lock_); | |
310 ListValueToStringSet(prefs_->GetList(prefs::kPluginsEnabledPlugins), | |
311 &policy_enabled_plugin_patterns_); | |
312 } else { | |
313 NOTREACHED(); | |
314 } | |
315 NotifyPluginStatusChanged(); | |
316 } | |
317 | |
318 /*static*/ | |
319 bool PluginPrefs::IsStringMatchedInSet(const string16& name, | |
320 const std::set<string16>& pattern_set) { | |
321 std::set<string16>::const_iterator pattern(pattern_set.begin()); | |
322 while (pattern != pattern_set.end()) { | |
323 if (MatchPattern(name, *pattern)) | |
324 return true; | |
325 ++pattern; | |
326 } | |
327 | |
328 return false; | |
329 } | |
330 | |
331 /* static */ | |
332 void PluginPrefs::ListValueToStringSet(const ListValue* src, | |
333 std::set<string16>* dest) { | |
334 DCHECK(src); | |
335 DCHECK(dest); | |
336 ListValue::const_iterator end(src->end()); | |
337 for (ListValue::const_iterator current(src->begin()); | |
338 current != end; ++current) { | |
339 string16 plugin_name; | |
340 if ((*current)->GetAsString(&plugin_name)) { | |
341 dest->insert(plugin_name); | |
342 } | |
343 } | |
344 } | |
345 | |
346 void PluginPrefs::SetPrefs(PrefService* prefs) { | |
347 prefs_ = prefs; | |
348 bool update_internal_dir = false; | |
349 FilePath last_internal_dir = | |
350 prefs_->GetFilePath(prefs::kPluginsLastInternalDirectory); | |
351 FilePath cur_internal_dir; | |
352 if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &cur_internal_dir) && | |
353 cur_internal_dir != last_internal_dir) { | |
354 update_internal_dir = true; | |
355 prefs_->SetFilePath( | |
356 prefs::kPluginsLastInternalDirectory, cur_internal_dir); | |
357 } | |
358 | |
359 bool force_enable_internal_pdf = false; | |
360 bool internal_pdf_enabled = false; | |
361 string16 pdf_group_name = | |
362 ASCIIToUTF16(chrome::ChromeContentClient::kPDFPluginName); | |
363 FilePath pdf_path; | |
364 PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path); | |
365 FilePath::StringType pdf_path_str = pdf_path.value(); | |
366 if (!prefs_->GetBoolean(prefs::kPluginsEnabledInternalPDF)) { | |
367 // We switched to the internal pdf plugin being on by default, and so we | |
368 // need to force it to be enabled. We only want to do it this once though, | |
369 // i.e. we don't want to enable it again if the user disables it afterwards. | |
370 prefs_->SetBoolean(prefs::kPluginsEnabledInternalPDF, true); | |
371 force_enable_internal_pdf = true; | |
372 } | |
373 | |
374 bool force_enable_nacl = false; | |
375 string16 nacl_group_name = | |
376 ASCIIToUTF16(chrome::ChromeContentClient::kNaClPluginName); | |
377 // Since the NaCl Plugin changed names between Chrome 13 and 14, we need to | |
378 // check for both because either could be stored as the plugin group name. | |
379 string16 old_nacl_group_name = | |
380 ASCIIToUTF16(chrome::ChromeContentClient::kNaClOldPluginName); | |
381 FilePath nacl_path; | |
382 PathService::Get(chrome::FILE_NACL_PLUGIN, &nacl_path); | |
383 FilePath::StringType nacl_path_str = nacl_path.value(); | |
384 if (!prefs_->GetBoolean(prefs::kPluginsEnabledNaCl)) { | |
385 // We switched to the nacl plugin being on by default, and so we need to | |
386 // force it to be enabled. We only want to do it this once though, i.e. | |
387 // we don't want to enable it again if the user disables it afterwards. | |
388 prefs_->SetBoolean(prefs::kPluginsEnabledNaCl, true); | |
389 force_enable_nacl = true; | |
390 } | |
391 | |
392 bool migrate_to_pepper_flash = false; | |
393 #if defined(OS_WIN) | |
394 // If bundled NPAPI Flash is enabled while Peppper Flash is disabled, we | |
395 // would like to turn Pepper Flash on. And we only want to do it once. | |
396 // TODO(yzshen): Remove all |migrate_to_pepper_flash|-related code after it | |
397 // has been run once by most users. (Maybe Chrome 24 or Chrome 25.) | |
398 if (!prefs_->GetBoolean(prefs::kPluginsMigratedToPepperFlash)) { | |
399 prefs_->SetBoolean(prefs::kPluginsMigratedToPepperFlash, true); | |
400 migrate_to_pepper_flash = true; | |
401 } | |
402 #endif | |
403 | |
404 { // Scoped update of prefs::kPluginsPluginsList. | |
405 ListPrefUpdate update(prefs_, prefs::kPluginsPluginsList); | |
406 ListValue* saved_plugins_list = update.Get(); | |
407 if (saved_plugins_list && !saved_plugins_list->empty()) { | |
408 // The following four variables are only valid when | |
409 // |migrate_to_pepper_flash| is set to true. | |
410 FilePath npapi_flash; | |
411 FilePath pepper_flash; | |
412 DictionaryValue* pepper_flash_node = NULL; | |
413 bool npapi_flash_enabled = false; | |
414 if (migrate_to_pepper_flash) { | |
415 PathService::Get(chrome::FILE_FLASH_PLUGIN, &npapi_flash); | |
416 PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &pepper_flash); | |
417 } | |
418 | |
419 for (ListValue::const_iterator it = saved_plugins_list->begin(); | |
420 it != saved_plugins_list->end(); | |
421 ++it) { | |
422 if (!(*it)->IsType(Value::TYPE_DICTIONARY)) { | |
423 LOG(WARNING) << "Invalid entry in " << prefs::kPluginsPluginsList; | |
424 continue; // Oops, don't know what to do with this item. | |
425 } | |
426 | |
427 DictionaryValue* plugin = static_cast<DictionaryValue*>(*it); | |
428 string16 group_name; | |
429 bool enabled; | |
430 if (!plugin->GetBoolean("enabled", &enabled)) | |
431 enabled = true; | |
432 | |
433 FilePath::StringType path; | |
434 // The plugin list constains all the plugin files in addition to the | |
435 // plugin groups. | |
436 if (plugin->GetString("path", &path)) { | |
437 // Files have a path attribute, groups don't. | |
438 FilePath plugin_path(path); | |
439 | |
440 // The path to the intenral plugin directory changes everytime Chrome | |
441 // is auto-updated, since it contains the current version number. For | |
442 // example, it changes from foobar\Chrome\Application\21.0.1180.83 to | |
443 // foobar\Chrome\Application\21.0.1180.89. | |
444 // However, we would like the settings of internal plugins to persist | |
445 // across Chrome updates. Therefore, we need to recognize those paths | |
446 // that are within the previous internal plugin directory, and update | |
447 // them in the prefs accordingly. | |
448 if (update_internal_dir) { | |
449 FilePath relative_path; | |
450 | |
451 // Extract the part of |plugin_path| that is relative to | |
452 // |last_internal_dir|. For example, |relative_path| will be | |
453 // foo\bar.dll if |plugin_path| is <last_internal_dir>\foo\bar.dll. | |
454 // | |
455 // Every iteration the last path component from |plugin_path| is | |
456 // removed and prepended to |relative_path| until we get up to | |
457 // |last_internal_dir|. | |
458 while (last_internal_dir.IsParent(plugin_path)) { | |
459 relative_path = plugin_path.BaseName().Append(relative_path); | |
460 | |
461 FilePath old_path = plugin_path; | |
462 plugin_path = plugin_path.DirName(); | |
463 // To be extra sure that we won't end up in an infinite loop. | |
464 if (old_path == plugin_path) { | |
465 NOTREACHED(); | |
466 break; | |
467 } | |
468 } | |
469 | |
470 // If |relative_path| is empty, |plugin_path| is not within | |
471 // |last_internal_dir|. We don't need to update it. | |
472 if (!relative_path.empty()) { | |
473 plugin_path = cur_internal_dir.Append(relative_path); | |
474 path = plugin_path.value(); | |
475 plugin->SetString("path", path); | |
476 } | |
477 } | |
478 | |
479 if (FilePath::CompareIgnoreCase(path, pdf_path_str) == 0) { | |
480 if (!enabled && force_enable_internal_pdf) { | |
481 enabled = true; | |
482 plugin->SetBoolean("enabled", true); | |
483 } | |
484 | |
485 internal_pdf_enabled = enabled; | |
486 } else if (FilePath::CompareIgnoreCase(path, nacl_path_str) == 0) { | |
487 if (!enabled && force_enable_nacl) { | |
488 enabled = true; | |
489 plugin->SetBoolean("enabled", true); | |
490 } | |
491 } else if (migrate_to_pepper_flash && | |
492 FilePath::CompareEqualIgnoreCase(path, npapi_flash.value())) { | |
493 npapi_flash_enabled = enabled; | |
494 } else if (migrate_to_pepper_flash && | |
495 FilePath::CompareEqualIgnoreCase(path, pepper_flash.value())) { | |
496 if (!enabled) | |
497 pepper_flash_node = plugin; | |
498 } | |
499 | |
500 plugin_state_.SetIgnorePseudoKey(plugin_path, enabled); | |
501 } else if (!enabled && plugin->GetString("name", &group_name)) { | |
502 // Don't disable this group if it's for the pdf or nacl plugins and | |
503 // we just forced it on. | |
504 if (force_enable_internal_pdf && pdf_group_name == group_name) | |
505 continue; | |
506 if (force_enable_nacl && (nacl_group_name == group_name || | |
507 old_nacl_group_name == group_name)) | |
508 continue; | |
509 | |
510 // Otherwise this is a list of groups. | |
511 plugin_group_state_[group_name] = false; | |
512 } | |
513 } | |
514 | |
515 if (npapi_flash_enabled && pepper_flash_node) { | |
516 DCHECK(migrate_to_pepper_flash); | |
517 pepper_flash_node->SetBoolean("enabled", true); | |
518 plugin_state_.Set(pepper_flash, true); | |
519 } | |
520 } else { | |
521 // If the saved plugin list is empty, then the call to UpdatePreferences() | |
522 // below failed in an earlier run, possibly because the user closed the | |
523 // browser too quickly. Try to force enable the internal PDF and nacl | |
524 // plugins again. | |
525 force_enable_internal_pdf = true; | |
526 force_enable_nacl = true; | |
527 } | |
528 } // Scoped update of prefs::kPluginsPluginsList. | |
529 | |
530 // Build the set of policy enabled/disabled plugin patterns once and cache it. | |
531 // Don't do this in the constructor, there's no profile available there. | |
532 ListValueToStringSet(prefs_->GetList(prefs::kPluginsDisabledPlugins), | |
533 &policy_disabled_plugin_patterns_); | |
534 ListValueToStringSet( | |
535 prefs_->GetList(prefs::kPluginsDisabledPluginsExceptions), | |
536 &policy_disabled_plugin_exception_patterns_); | |
537 ListValueToStringSet(prefs_->GetList(prefs::kPluginsEnabledPlugins), | |
538 &policy_enabled_plugin_patterns_); | |
539 | |
540 registrar_.Init(prefs_); | |
541 registrar_.Add(prefs::kPluginsDisabledPlugins, this); | |
542 registrar_.Add(prefs::kPluginsDisabledPluginsExceptions, this); | |
543 registrar_.Add(prefs::kPluginsEnabledPlugins, this); | |
544 | |
545 if (force_enable_internal_pdf || internal_pdf_enabled) { | |
546 // See http://crbug.com/50105 for background. | |
547 plugin_group_state_[ASCIIToUTF16( | |
548 webkit::npapi::PluginGroup::kAdobeReaderGroupName)] = false; | |
549 } | |
550 | |
551 if (force_enable_internal_pdf || force_enable_nacl) { | |
552 // We want to save this, but doing so requires loading the list of plugins, | |
553 // so do it after a minute as to not impact startup performance. Note that | |
554 // plugins are loaded after 30s by the metrics service. | |
555 BrowserThread::PostDelayedTask( | |
556 BrowserThread::FILE, | |
557 FROM_HERE, | |
558 base::Bind(&PluginPrefs::GetPreferencesDataOnFileThread, this), | |
559 base::TimeDelta::FromMilliseconds(kPluginUpdateDelayMs)); | |
560 } | |
561 | |
562 NotifyPluginStatusChanged(); | |
563 } | |
564 | |
565 void PluginPrefs::ShutdownOnUIThread() { | |
566 prefs_ = NULL; | |
567 registrar_.RemoveAll(); | |
568 } | |
569 | |
570 PluginPrefs::PluginPrefs() : profile_(NULL), | |
571 prefs_(NULL), | |
572 plugin_list_(NULL) { | |
573 } | |
574 | |
575 PluginPrefs::~PluginPrefs() { | |
576 } | |
577 | |
578 void PluginPrefs::SetPolicyEnforcedPluginPatterns( | |
579 const std::set<string16>& disabled_patterns, | |
580 const std::set<string16>& disabled_exception_patterns, | |
581 const std::set<string16>& enabled_patterns) { | |
582 policy_disabled_plugin_patterns_ = disabled_patterns; | |
583 policy_disabled_plugin_exception_patterns_ = disabled_exception_patterns; | |
584 policy_enabled_plugin_patterns_ = enabled_patterns; | |
585 } | |
586 | |
587 webkit::npapi::PluginList* PluginPrefs::GetPluginList() const { | |
588 if (plugin_list_) | |
589 return plugin_list_; | |
590 return PluginService::GetInstance()->GetPluginList(); | |
591 } | |
592 | |
593 void PluginPrefs::GetPreferencesDataOnFileThread() { | |
594 PluginFinder::Get( | |
595 base::Bind(&PluginPrefs::GetPluginFinderForGetPreferencesDataOnFileThread, | |
596 this)); | |
597 } | |
598 | |
599 void PluginPrefs::GetPluginFinderForGetPreferencesDataOnFileThread( | |
600 PluginFinder* finder) { | |
601 std::vector<webkit::WebPluginInfo> plugins; | |
602 webkit::npapi::PluginList* plugin_list = GetPluginList(); | |
603 plugin_list->GetPluginsNoRefresh(&plugins); | |
604 | |
605 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
606 base::Bind(&PluginPrefs::OnUpdatePreferences, this, plugins, finder)); | |
607 } | |
608 | |
609 void PluginPrefs::OnUpdatePreferences( | |
610 const std::vector<webkit::WebPluginInfo>& plugins, | |
611 PluginFinder* finder) { | |
612 if (!prefs_) | |
613 return; | |
614 | |
615 ListPrefUpdate update(prefs_, prefs::kPluginsPluginsList); | |
616 ListValue* plugins_list = update.Get(); | |
617 plugins_list->Clear(); | |
618 | |
619 FilePath internal_dir; | |
620 if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir)) | |
621 prefs_->SetFilePath(prefs::kPluginsLastInternalDirectory, internal_dir); | |
622 | |
623 base::AutoLock auto_lock(lock_); | |
624 | |
625 // Add the plugin files. | |
626 std::set<string16> group_names; | |
627 for (size_t i = 0; i < plugins.size(); ++i) { | |
628 DictionaryValue* summary = new DictionaryValue(); | |
629 summary->SetString("path", plugins[i].path.value()); | |
630 summary->SetString("name", plugins[i].name); | |
631 summary->SetString("version", plugins[i].version); | |
632 bool enabled = true; | |
633 plugin_state_.Get(plugins[i].path, &enabled); | |
634 summary->SetBoolean("enabled", enabled); | |
635 plugins_list->Append(summary); | |
636 | |
637 PluginInstaller* installer = finder->GetPluginInstaller(plugins[i]); | |
638 // Insert into a set of all group names. | |
639 group_names.insert(installer->name()); | |
640 } | |
641 | |
642 // Add the plug-in groups. | |
643 for (std::set<string16>::const_iterator it = group_names.begin(); | |
644 it != group_names.end(); ++it) { | |
645 DictionaryValue* summary = new DictionaryValue(); | |
646 summary->SetString("name", *it); | |
647 bool enabled = true; | |
648 std::map<string16, bool>::iterator gstate_it = | |
649 plugin_group_state_.find(*it); | |
650 if (gstate_it != plugin_group_state_.end()) | |
651 enabled = gstate_it->second; | |
652 summary->SetBoolean("enabled", enabled); | |
653 plugins_list->Append(summary); | |
654 } | |
655 } | |
656 | |
657 void PluginPrefs::NotifyPluginStatusChanged() { | |
658 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
659 content::NotificationService::current()->Notify( | |
660 chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, | |
661 content::Source<Profile>(profile_), | |
662 content::NotificationService::NoDetails()); | |
663 } | |
OLD | NEW |