| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/plugin_prefs.h" | 5 #include "chrome/browser/plugin_prefs.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/lazy_instance.h" |
| 10 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 11 #include "base/memory/singleton.h" | 12 #include "base/memory/singleton.h" |
| 12 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
| 13 #include "base/path_service.h" | 14 #include "base/path_service.h" |
| 15 #include "base/string_util.h" |
| 14 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 15 #include "base/values.h" | 17 #include "base/values.h" |
| 16 #include "base/version.h" | 18 #include "base/version.h" |
| 19 #include "chrome/browser/browser_process.h" |
| 17 #include "chrome/browser/prefs/pref_service.h" | 20 #include "chrome/browser/prefs/pref_service.h" |
| 18 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 21 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| 19 #include "chrome/browser/profiles/profile.h" | 22 #include "chrome/browser/profiles/profile.h" |
| 20 #include "chrome/browser/profiles/profile_dependency_manager.h" | 23 #include "chrome/browser/profiles/profile_dependency_manager.h" |
| 21 #include "chrome/browser/profiles/profile_keyed_service.h" | 24 #include "chrome/browser/profiles/profile_keyed_service.h" |
| 22 #include "chrome/browser/profiles/profile_keyed_service_factory.h" | 25 #include "chrome/browser/profiles/profile_keyed_service_factory.h" |
| 26 #include "chrome/browser/profiles/profile_manager.h" |
| 23 #include "chrome/common/chrome_content_client.h" | 27 #include "chrome/common/chrome_content_client.h" |
| 24 #include "chrome/common/chrome_notification_types.h" | 28 #include "chrome/common/chrome_notification_types.h" |
| 25 #include "chrome/common/chrome_paths.h" | 29 #include "chrome/common/chrome_paths.h" |
| 26 #include "chrome/common/chrome_switches.h" | 30 #include "chrome/common/chrome_switches.h" |
| 27 #include "chrome/common/pref_names.h" | 31 #include "chrome/common/pref_names.h" |
| 28 #include "content/browser/browser_thread.h" | 32 #include "content/browser/browser_thread.h" |
| 29 #include "content/common/notification_service.h" | 33 #include "content/common/notification_service.h" |
| 34 #include "webkit/plugins/npapi/plugin_group.h" |
| 30 #include "webkit/plugins/npapi/plugin_list.h" | 35 #include "webkit/plugins/npapi/plugin_list.h" |
| 31 #include "webkit/plugins/webplugininfo.h" | 36 #include "webkit/plugins/webplugininfo.h" |
| 32 | 37 |
| 33 namespace { | 38 namespace { |
| 34 | 39 |
| 35 class PluginPrefsWrapper : public ProfileKeyedService { | 40 class PluginPrefsWrapper : public ProfileKeyedService { |
| 36 public: | 41 public: |
| 37 explicit PluginPrefsWrapper(scoped_refptr<PluginPrefs> plugin_prefs) | 42 explicit PluginPrefsWrapper(scoped_refptr<PluginPrefs> plugin_prefs) |
| 38 : plugin_prefs_(plugin_prefs) {} | 43 : plugin_prefs_(plugin_prefs) {} |
| 39 virtual ~PluginPrefsWrapper() {} | 44 virtual ~PluginPrefsWrapper() {} |
| 40 | 45 |
| 41 PluginPrefs* plugin_prefs() { return plugin_prefs_.get(); } | 46 PluginPrefs* plugin_prefs() { return plugin_prefs_.get(); } |
| 42 | 47 |
| 43 private: | 48 private: |
| 44 // ProfileKeyedService methods: | 49 // ProfileKeyedService methods: |
| 45 virtual void Shutdown() OVERRIDE { | 50 virtual void Shutdown() OVERRIDE { |
| 46 plugin_prefs_->ShutdownOnUIThread(); | 51 plugin_prefs_->ShutdownOnUIThread(); |
| 47 } | 52 } |
| 48 | 53 |
| 49 scoped_refptr<PluginPrefs> plugin_prefs_; | 54 scoped_refptr<PluginPrefs> plugin_prefs_; |
| 50 }; | 55 }; |
| 51 | 56 |
| 57 // Default state for a plug-in (not state of the default plug-in!). |
| 58 // Accessed only on the UI thread. |
| 59 base::LazyInstance<std::map<FilePath, bool> > g_default_plugin_state( |
| 60 base::LINKER_INITIALIZED); |
| 61 |
| 52 } | 62 } |
| 53 | 63 |
| 54 // How long to wait to save the plugin enabled information, which might need to | 64 // How long to wait to save the plugin enabled information, which might need to |
| 55 // go to disk. | 65 // go to disk. |
| 56 #define kPluginUpdateDelayMs (60 * 1000) | 66 #define kPluginUpdateDelayMs (60 * 1000) |
| 57 | 67 |
| 58 class PluginPrefs::Factory : public ProfileKeyedServiceFactory { | 68 class PluginPrefs::Factory : public ProfileKeyedServiceFactory { |
| 59 public: | 69 public: |
| 60 static Factory* GetInstance(); | 70 static Factory* GetInstance(); |
| 61 | 71 |
| 62 PluginPrefsWrapper* GetWrapperForProfile(Profile* profile); | 72 PluginPrefsWrapper* GetWrapperForProfile(Profile* profile); |
| 63 | 73 |
| 74 // Factory function for use with |
| 75 // ProfileKeyedServiceFactory::SetTestingFactory. |
| 76 static ProfileKeyedService* CreateWrapperForProfile(Profile* profile); |
| 77 |
| 64 private: | 78 private: |
| 65 friend struct DefaultSingletonTraits<Factory>; | 79 friend struct DefaultSingletonTraits<Factory>; |
| 66 | 80 |
| 67 Factory(); | 81 Factory(); |
| 68 virtual ~Factory() {} | 82 virtual ~Factory() {} |
| 69 | 83 |
| 70 // ProfileKeyedServiceFactory methods: | 84 // ProfileKeyedServiceFactory methods: |
| 71 virtual ProfileKeyedService* BuildServiceInstanceFor( | 85 virtual ProfileKeyedService* BuildServiceInstanceFor( |
| 72 Profile* profile) const OVERRIDE; | 86 Profile* profile) const OVERRIDE; |
| 73 virtual bool ServiceRedirectedInIncognito() OVERRIDE { return true; } | 87 virtual bool ServiceRedirectedInIncognito() OVERRIDE { return true; } |
| 74 virtual bool ServiceIsNULLWhileTesting() OVERRIDE { return true; } | 88 virtual bool ServiceIsNULLWhileTesting() OVERRIDE { return true; } |
| 75 virtual bool ServiceIsCreatedWithProfile() OVERRIDE { return true; } | 89 virtual bool ServiceIsCreatedWithProfile() OVERRIDE { return true; } |
| 76 }; | 90 }; |
| 77 | 91 |
| 78 // static | 92 // static |
| 79 void PluginPrefs::Initialize() { | 93 void PluginPrefs::Initialize() { |
| 80 Factory::GetInstance(); | 94 Factory::GetInstance(); |
| 81 } | 95 } |
| 82 | 96 |
| 83 // static | 97 // static |
| 84 PluginPrefs* PluginPrefs::GetForProfile(Profile* profile) { | 98 PluginPrefs* PluginPrefs::GetForProfile(Profile* profile) { |
| 85 PluginPrefsWrapper* wrapper = | 99 PluginPrefsWrapper* wrapper = |
| 86 Factory::GetInstance()->GetWrapperForProfile(profile); | 100 Factory::GetInstance()->GetWrapperForProfile(profile); |
| 87 if (!wrapper) | 101 if (!wrapper) |
| 88 return NULL; | 102 return NULL; |
| 89 return wrapper->plugin_prefs(); | 103 return wrapper->plugin_prefs(); |
| 90 } | 104 } |
| 91 | 105 |
| 92 DictionaryValue* PluginPrefs::CreatePluginFileSummary( | 106 // static |
| 93 const webkit::WebPluginInfo& plugin) { | 107 PluginPrefs* PluginPrefs::GetForTestingProfile(Profile* profile) { |
| 94 DictionaryValue* data = new DictionaryValue(); | 108 ProfileKeyedService* wrapper = |
| 95 data->SetString("path", plugin.path.value()); | 109 Factory::GetInstance()->SetTestingFactoryAndUse( |
| 96 data->SetString("name", plugin.name); | 110 profile, &Factory::CreateWrapperForProfile); |
| 97 data->SetString("version", plugin.version); | 111 return static_cast<PluginPrefsWrapper*>(wrapper)->plugin_prefs(); |
| 98 data->SetBoolean("enabled", IsPluginEnabled(plugin)); | |
| 99 return data; | |
| 100 } | 112 } |
| 101 | 113 |
| 102 void PluginPrefs::EnablePluginGroup(bool enable, const string16& group_name) { | 114 void PluginPrefs::EnablePluginGroup(bool enabled, const string16& group_name) { |
| 103 webkit::npapi::PluginList::Singleton()->EnableGroup(enable, group_name); | 115 if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { |
| 104 NotifyPluginStatusChanged(); | 116 BrowserThread::PostTask( |
| 117 BrowserThread::FILE, FROM_HERE, |
| 118 NewRunnableMethod(this, &PluginPrefs::EnablePluginGroup, |
| 119 enabled, group_name)); |
| 120 return; |
| 121 } |
| 122 |
| 123 webkit::npapi::PluginList* plugin_list = |
| 124 webkit::npapi::PluginList::Singleton(); |
| 125 std::vector<webkit::npapi::PluginGroup> groups; |
| 126 plugin_list->GetPluginGroups(true, &groups); |
| 127 |
| 128 base::AutoLock auto_lock(lock_); |
| 129 |
| 130 // Set the desired state for the group. |
| 131 plugin_group_state_[group_name] = enabled; |
| 132 |
| 133 // Update the state for all plug-ins in the group. |
| 134 for (size_t i = 0; i < groups.size(); ++i) { |
| 135 if (groups[i].GetGroupName() != group_name) |
| 136 continue; |
| 137 const std::vector<webkit::WebPluginInfo>& plugins = |
| 138 groups[i].web_plugin_infos(); |
| 139 for (size_t j = 0; j < plugins.size(); ++j) |
| 140 plugin_state_[plugins[j].path] = enabled; |
| 141 break; |
| 142 } |
| 143 |
| 144 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 145 NewRunnableMethod(this, &PluginPrefs::OnUpdatePreferences, groups)); |
| 146 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 147 NewRunnableMethod(this, &PluginPrefs::NotifyPluginStatusChanged)); |
| 105 } | 148 } |
| 106 | 149 |
| 107 void PluginPrefs::EnablePlugin(bool enable, const FilePath& path) { | 150 void PluginPrefs::EnablePlugin(bool enabled, const FilePath& path) { |
| 108 if (enable) | 151 if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { |
| 109 webkit::npapi::PluginList::Singleton()->EnablePlugin(path); | 152 BrowserThread::PostTask( |
| 110 else | 153 BrowserThread::FILE, FROM_HERE, |
| 111 webkit::npapi::PluginList::Singleton()->DisablePlugin(path); | 154 NewRunnableMethod(this, &PluginPrefs::EnablePlugin, enabled, path)); |
| 155 return; |
| 156 } |
| 112 | 157 |
| 113 NotifyPluginStatusChanged(); | 158 { |
| 159 // Set the desired state for the plug-in. |
| 160 base::AutoLock auto_lock(lock_); |
| 161 plugin_state_[path] = enabled; |
| 162 } |
| 163 |
| 164 webkit::npapi::PluginList* plugin_list = |
| 165 webkit::npapi::PluginList::Singleton(); |
| 166 std::vector<webkit::npapi::PluginGroup> groups; |
| 167 plugin_list->GetPluginGroups(true, &groups); |
| 168 |
| 169 bool found_group = false; |
| 170 for (size_t i = 0; i < groups.size(); ++i) { |
| 171 bool all_disabled = true; |
| 172 const std::vector<webkit::WebPluginInfo>& plugins = |
| 173 groups[i].web_plugin_infos(); |
| 174 for (size_t j = 0; j < plugins.size(); ++j) { |
| 175 all_disabled = all_disabled && !IsPluginEnabled(plugins[j]); |
| 176 if (plugins[j].path == path) { |
| 177 found_group = true; |
| 178 DCHECK_EQ(enabled, IsPluginEnabled(plugins[j])); |
| 179 } |
| 180 } |
| 181 if (found_group) { |
| 182 // Update the state for the corresponding plug-in group. |
| 183 base::AutoLock auto_lock(lock_); |
| 184 plugin_group_state_[groups[i].GetGroupName()] = !all_disabled; |
| 185 break; |
| 186 } |
| 187 } |
| 188 |
| 189 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 190 NewRunnableMethod(this, &PluginPrefs::OnUpdatePreferences, groups)); |
| 191 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 192 NewRunnableMethod(this, &PluginPrefs::NotifyPluginStatusChanged)); |
| 193 } |
| 194 |
| 195 // static |
| 196 void PluginPrefs::EnablePluginGlobally(bool enable, const FilePath& file_path) { |
| 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 198 g_default_plugin_state.Get()[file_path] = enable; |
| 199 std::vector<Profile*> profiles = |
| 200 g_browser_process->profile_manager()->GetLoadedProfiles(); |
| 201 for (std::vector<Profile*>::iterator it = profiles.begin(); |
| 202 it != profiles.end(); ++it) { |
| 203 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(*it); |
| 204 DCHECK(plugin_prefs); |
| 205 plugin_prefs->EnablePlugin(enable, file_path); |
| 206 } |
| 207 } |
| 208 |
| 209 PluginPrefs::PolicyStatus PluginPrefs::PolicyStatusForPlugin( |
| 210 const string16& name) { |
| 211 base::AutoLock auto_lock(lock_); |
| 212 if (IsStringMatchedInSet(name, policy_enabled_plugin_patterns_)) { |
| 213 return POLICY_ENABLED; |
| 214 } else if (IsStringMatchedInSet(name, policy_disabled_plugin_patterns_) && |
| 215 !IsStringMatchedInSet( |
| 216 name, policy_disabled_plugin_exception_patterns_)) { |
| 217 return POLICY_DISABLED; |
| 218 } else { |
| 219 return NO_POLICY; |
| 220 } |
| 114 } | 221 } |
| 115 | 222 |
| 116 bool PluginPrefs::IsPluginEnabled(const webkit::WebPluginInfo& plugin) { | 223 bool PluginPrefs::IsPluginEnabled(const webkit::WebPluginInfo& plugin) { |
| 224 scoped_ptr<webkit::npapi::PluginGroup> group( |
| 225 webkit::npapi::PluginList::Singleton()->GetPluginGroup(plugin)); |
| 226 string16 group_name = group->GetGroupName(); |
| 227 |
| 228 // Check if the plug-in or its group is enabled by policy. |
| 229 PolicyStatus plugin_status = PolicyStatusForPlugin(plugin.name); |
| 230 PolicyStatus group_status = PolicyStatusForPlugin(group_name); |
| 231 if (plugin_status == POLICY_ENABLED || group_status == POLICY_ENABLED) |
| 232 return true; |
| 233 |
| 234 // Check if the plug-in or its group is disabled by policy. |
| 235 if (plugin_status == POLICY_DISABLED || group_status == POLICY_DISABLED) |
| 236 return false; |
| 237 |
| 117 // If enabling NaCl, make sure the plugin is also enabled. See bug | 238 // If enabling NaCl, make sure the plugin is also enabled. See bug |
| 118 // http://code.google.com/p/chromium/issues/detail?id=81010 for more | 239 // http://code.google.com/p/chromium/issues/detail?id=81010 for more |
| 119 // information. | 240 // information. |
| 120 // TODO(dspringer): When NaCl is on by default, remove this code. | 241 // TODO(dspringer): When NaCl is on by default, remove this code. |
| 121 if ((plugin.name == | 242 if ((plugin.name == |
| 122 ASCIIToUTF16(chrome::ChromeContentClient::kNaClPluginName)) && | 243 ASCIIToUTF16(chrome::ChromeContentClient::kNaClPluginName)) && |
| 123 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaCl)) { | 244 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaCl)) { |
| 124 return true; | 245 return true; |
| 125 } | 246 } |
| 126 return webkit::IsPluginEnabled(plugin); | 247 |
| 248 base::AutoLock auto_lock(lock_); |
| 249 // Check user preferences for the plug-in. |
| 250 std::map<FilePath, bool>::iterator plugin_it = |
| 251 plugin_state_.find(plugin.path); |
| 252 if (plugin_it != plugin_state_.end()) |
| 253 return plugin_it->second; |
| 254 |
| 255 // Check user preferences for the plug-in group. |
| 256 std::map<string16, bool>::iterator group_it( |
| 257 plugin_group_state_.find(plugin.name)); |
| 258 if (group_it != plugin_group_state_.end()) |
| 259 return group_it->second; |
| 260 |
| 261 // Default to enabled. |
| 262 return true; |
| 127 } | 263 } |
| 128 | 264 |
| 129 void PluginPrefs::Observe(int type, | 265 void PluginPrefs::Observe(int type, |
| 130 const NotificationSource& source, | 266 const NotificationSource& source, |
| 131 const NotificationDetails& details) { | 267 const NotificationDetails& details) { |
| 132 DCHECK_EQ(chrome::NOTIFICATION_PREF_CHANGED, type); | 268 DCHECK_EQ(chrome::NOTIFICATION_PREF_CHANGED, type); |
| 133 const std::string* pref_name = Details<std::string>(details).ptr(); | 269 const std::string* pref_name = Details<std::string>(details).ptr(); |
| 134 if (!pref_name) { | 270 if (!pref_name) { |
| 135 NOTREACHED(); | 271 NOTREACHED(); |
| 136 return; | 272 return; |
| 137 } | 273 } |
| 138 DCHECK_EQ(prefs_, Source<PrefService>(source).ptr()); | 274 DCHECK_EQ(prefs_, Source<PrefService>(source).ptr()); |
| 139 if (*pref_name == prefs::kPluginsDisabledPlugins || | 275 if (*pref_name == prefs::kPluginsDisabledPlugins) { |
| 140 *pref_name == prefs::kPluginsDisabledPluginsExceptions || | 276 base::AutoLock auto_lock(lock_); |
| 141 *pref_name == prefs::kPluginsEnabledPlugins) { | 277 ListValueToStringSet(prefs_->GetList(prefs::kPluginsDisabledPlugins), |
| 142 const ListValue* disabled_list = | 278 &policy_disabled_plugin_patterns_); |
| 143 prefs_->GetList(prefs::kPluginsDisabledPlugins); | 279 } else if (*pref_name == prefs::kPluginsDisabledPluginsExceptions) { |
| 144 const ListValue* exceptions_list = | 280 base::AutoLock auto_lock(lock_); |
| 145 prefs_->GetList(prefs::kPluginsDisabledPluginsExceptions); | 281 ListValueToStringSet( |
| 146 const ListValue* enabled_list = | 282 prefs_->GetList(prefs::kPluginsDisabledPluginsExceptions), |
| 147 prefs_->GetList(prefs::kPluginsEnabledPlugins); | 283 &policy_disabled_plugin_exception_patterns_); |
| 148 UpdatePluginsStateFromPolicy(disabled_list, exceptions_list, enabled_list); | 284 } else if (*pref_name == prefs::kPluginsEnabledPlugins) { |
| 285 base::AutoLock auto_lock(lock_); |
| 286 ListValueToStringSet(prefs_->GetList(prefs::kPluginsEnabledPlugins), |
| 287 &policy_enabled_plugin_patterns_); |
| 288 } else { |
| 289 NOTREACHED(); |
| 149 } | 290 } |
| 150 } | |
| 151 | |
| 152 void PluginPrefs::UpdatePluginsStateFromPolicy( | |
| 153 const ListValue* disabled_list, | |
| 154 const ListValue* exceptions_list, | |
| 155 const ListValue* enabled_list) { | |
| 156 std::set<string16> disabled_plugin_patterns; | |
| 157 std::set<string16> disabled_plugin_exception_patterns; | |
| 158 std::set<string16> enabled_plugin_patterns; | |
| 159 | |
| 160 ListValueToStringSet(disabled_list, &disabled_plugin_patterns); | |
| 161 ListValueToStringSet(exceptions_list, &disabled_plugin_exception_patterns); | |
| 162 ListValueToStringSet(enabled_list, &enabled_plugin_patterns); | |
| 163 | |
| 164 webkit::npapi::PluginGroup::SetPolicyEnforcedPluginPatterns( | |
| 165 disabled_plugin_patterns, | |
| 166 disabled_plugin_exception_patterns, | |
| 167 enabled_plugin_patterns); | |
| 168 | |
| 169 NotifyPluginStatusChanged(); | 291 NotifyPluginStatusChanged(); |
| 170 } | 292 } |
| 171 | 293 |
| 294 /*static*/ |
| 295 bool PluginPrefs::IsStringMatchedInSet(const string16& name, |
| 296 const std::set<string16>& pattern_set) { |
| 297 std::set<string16>::const_iterator pattern(pattern_set.begin()); |
| 298 while (pattern != pattern_set.end()) { |
| 299 if (MatchPattern(name, *pattern)) |
| 300 return true; |
| 301 ++pattern; |
| 302 } |
| 303 |
| 304 return false; |
| 305 } |
| 306 |
| 307 /* static */ |
| 172 void PluginPrefs::ListValueToStringSet(const ListValue* src, | 308 void PluginPrefs::ListValueToStringSet(const ListValue* src, |
| 173 std::set<string16>* dest) { | 309 std::set<string16>* dest) { |
| 174 DCHECK(src); | 310 DCHECK(src); |
| 175 DCHECK(dest); | 311 DCHECK(dest); |
| 176 ListValue::const_iterator end(src->end()); | 312 ListValue::const_iterator end(src->end()); |
| 177 for (ListValue::const_iterator current(src->begin()); | 313 for (ListValue::const_iterator current(src->begin()); |
| 178 current != end; ++current) { | 314 current != end; ++current) { |
| 179 string16 plugin_name; | 315 string16 plugin_name; |
| 180 if ((*current)->GetAsString(&plugin_name)) { | 316 if ((*current)->GetAsString(&plugin_name)) { |
| 181 dest->insert(plugin_name); | 317 dest->insert(plugin_name); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 } | 406 } |
| 271 | 407 |
| 272 internal_pdf_enabled = enabled; | 408 internal_pdf_enabled = enabled; |
| 273 } else if (FilePath::CompareIgnoreCase(path, nacl_path_str) == 0) { | 409 } else if (FilePath::CompareIgnoreCase(path, nacl_path_str) == 0) { |
| 274 if (!enabled && force_enable_nacl) { | 410 if (!enabled && force_enable_nacl) { |
| 275 enabled = true; | 411 enabled = true; |
| 276 plugin->SetBoolean("enabled", true); | 412 plugin->SetBoolean("enabled", true); |
| 277 } | 413 } |
| 278 } | 414 } |
| 279 | 415 |
| 280 if (!enabled) | 416 plugin_state_[plugin_path] = enabled; |
| 281 webkit::npapi::PluginList::Singleton()->DisablePlugin(plugin_path); | |
| 282 } else if (!enabled && plugin->GetString("name", &group_name)) { | 417 } else if (!enabled && plugin->GetString("name", &group_name)) { |
| 283 // Don't disable this group if it's for the pdf or nacl plugins and | 418 // Don't disable this group if it's for the pdf or nacl plugins and |
| 284 // we just forced it on. | 419 // we just forced it on. |
| 285 if (force_enable_internal_pdf && pdf_group_name == group_name) | 420 if (force_enable_internal_pdf && pdf_group_name == group_name) |
| 286 continue; | 421 continue; |
| 287 if (force_enable_nacl && (nacl_group_name == group_name || | 422 if (force_enable_nacl && (nacl_group_name == group_name || |
| 288 old_nacl_group_name == group_name)) | 423 old_nacl_group_name == group_name)) |
| 289 continue; | 424 continue; |
| 290 | 425 |
| 291 // Otherwise this is a list of groups. | 426 // Otherwise this is a list of groups. |
| 292 EnablePluginGroup(false, group_name); | 427 plugin_group_state_[group_name] = false; |
| 293 } | 428 } |
| 294 } | 429 } |
| 295 } else { | 430 } else { |
| 296 // If the saved plugin list is empty, then the call to UpdatePreferences() | 431 // If the saved plugin list is empty, then the call to UpdatePreferences() |
| 297 // below failed in an earlier run, possibly because the user closed the | 432 // below failed in an earlier run, possibly because the user closed the |
| 298 // browser too quickly. Try to force enable the internal PDF and nacl | 433 // browser too quickly. Try to force enable the internal PDF and nacl |
| 299 // plugins again. | 434 // plugins again. |
| 300 force_enable_internal_pdf = true; | 435 force_enable_internal_pdf = true; |
| 301 force_enable_nacl = true; | 436 force_enable_nacl = true; |
| 302 } | 437 } |
| 303 } // Scoped update of prefs::kPluginsPluginsList. | 438 } // Scoped update of prefs::kPluginsPluginsList. |
| 304 | 439 |
| 305 // Build the set of policy enabled/disabled plugin patterns once and cache it. | 440 // Build the set of policy enabled/disabled plugin patterns once and cache it. |
| 306 // Don't do this in the constructor, there's no profile available there. | 441 // Don't do this in the constructor, there's no profile available there. |
| 307 const ListValue* disabled_plugins = | 442 ListValueToStringSet(prefs_->GetList(prefs::kPluginsDisabledPlugins), |
| 308 prefs_->GetList(prefs::kPluginsDisabledPlugins); | 443 &policy_disabled_plugin_patterns_); |
| 309 const ListValue* disabled_exception_plugins = | 444 ListValueToStringSet( |
| 310 prefs_->GetList(prefs::kPluginsDisabledPluginsExceptions); | 445 prefs_->GetList(prefs::kPluginsDisabledPluginsExceptions), |
| 311 const ListValue* enabled_plugins = | 446 &policy_disabled_plugin_exception_patterns_); |
| 312 prefs_->GetList(prefs::kPluginsEnabledPlugins); | 447 ListValueToStringSet(prefs_->GetList(prefs::kPluginsEnabledPlugins), |
| 313 UpdatePluginsStateFromPolicy(disabled_plugins, | 448 &policy_enabled_plugin_patterns_); |
| 314 disabled_exception_plugins, | |
| 315 enabled_plugins); | |
| 316 | 449 |
| 317 registrar_.RemoveAll(); | |
| 318 registrar_.Init(prefs_); | 450 registrar_.Init(prefs_); |
| 319 registrar_.Add(prefs::kPluginsDisabledPlugins, this); | 451 registrar_.Add(prefs::kPluginsDisabledPlugins, this); |
| 320 registrar_.Add(prefs::kPluginsDisabledPluginsExceptions, this); | 452 registrar_.Add(prefs::kPluginsDisabledPluginsExceptions, this); |
| 321 registrar_.Add(prefs::kPluginsEnabledPlugins, this); | 453 registrar_.Add(prefs::kPluginsEnabledPlugins, this); |
| 322 | 454 |
| 323 if (force_enable_internal_pdf || internal_pdf_enabled) { | 455 if (force_enable_internal_pdf || internal_pdf_enabled) { |
| 324 // See http://crbug.com/50105 for background. | 456 // See http://crbug.com/50105 for background. |
| 325 EnablePluginGroup(false, ASCIIToUTF16( | 457 plugin_group_state_[ASCIIToUTF16( |
| 326 webkit::npapi::PluginGroup::kAdobeReaderGroupName)); | 458 webkit::npapi::PluginGroup::kAdobeReaderGroupName)] = false; |
| 327 } | 459 } |
| 328 | 460 |
| 329 if (force_enable_internal_pdf || force_enable_nacl) { | 461 if (force_enable_internal_pdf || force_enable_nacl) { |
| 330 // We want to save this, but doing so requires loading the list of plugins, | 462 // We want to save this, but doing so requires loading the list of plugins, |
| 331 // so do it after a minute as to not impact startup performance. Note that | 463 // so do it after a minute as to not impact startup performance. Note that |
| 332 // plugins are loaded after 30s by the metrics service. | 464 // plugins are loaded after 30s by the metrics service. |
| 333 UpdatePreferences(kPluginUpdateDelayMs); | 465 BrowserThread::PostDelayedTask( |
| 466 BrowserThread::FILE, |
| 467 FROM_HERE, |
| 468 NewRunnableMethod(this, &PluginPrefs::GetPreferencesDataOnFileThread), |
| 469 kPluginUpdateDelayMs); |
| 334 } | 470 } |
| 471 |
| 472 NotifyPluginStatusChanged(); |
| 335 } | 473 } |
| 336 | 474 |
| 337 void PluginPrefs::ShutdownOnUIThread() { | 475 void PluginPrefs::ShutdownOnUIThread() { |
| 338 prefs_ = NULL; | 476 prefs_ = NULL; |
| 339 registrar_.RemoveAll(); | 477 registrar_.RemoveAll(); |
| 340 } | 478 } |
| 341 | 479 |
| 342 // static | 480 // static |
| 343 PluginPrefs::Factory* PluginPrefs::Factory::GetInstance() { | 481 PluginPrefs::Factory* PluginPrefs::Factory::GetInstance() { |
| 344 return Singleton<PluginPrefs::Factory>::get(); | 482 return Singleton<PluginPrefs::Factory>::get(); |
| 345 } | 483 } |
| 346 | 484 |
| 347 PluginPrefsWrapper* PluginPrefs::Factory::GetWrapperForProfile( | 485 PluginPrefsWrapper* PluginPrefs::Factory::GetWrapperForProfile( |
| 348 Profile* profile) { | 486 Profile* profile) { |
| 349 return static_cast<PluginPrefsWrapper*>(GetServiceForProfile(profile, true)); | 487 return static_cast<PluginPrefsWrapper*>(GetServiceForProfile(profile, true)); |
| 350 } | 488 } |
| 351 | 489 |
| 490 // static |
| 491 ProfileKeyedService* PluginPrefs::Factory::CreateWrapperForProfile( |
| 492 Profile* profile) { |
| 493 return GetInstance()->BuildServiceInstanceFor(profile); |
| 494 } |
| 495 |
| 352 PluginPrefs::Factory::Factory() | 496 PluginPrefs::Factory::Factory() |
| 353 : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) { | 497 : ProfileKeyedServiceFactory(ProfileDependencyManager::GetInstance()) { |
| 354 } | 498 } |
| 355 | 499 |
| 356 ProfileKeyedService* PluginPrefs::Factory::BuildServiceInstanceFor( | 500 ProfileKeyedService* PluginPrefs::Factory::BuildServiceInstanceFor( |
| 357 Profile* profile) const { | 501 Profile* profile) const { |
| 358 scoped_refptr<PluginPrefs> plugin_prefs(new PluginPrefs()); | 502 scoped_refptr<PluginPrefs> plugin_prefs(new PluginPrefs()); |
| 359 plugin_prefs->SetPrefs(profile->GetPrefs()); | 503 plugin_prefs->SetPrefs(profile->GetPrefs()); |
| 360 return new PluginPrefsWrapper(plugin_prefs); | 504 return new PluginPrefsWrapper(plugin_prefs); |
| 361 } | 505 } |
| 362 | 506 |
| 363 PluginPrefs::PluginPrefs() : prefs_(NULL), notify_pending_(false) { | 507 PluginPrefs::PluginPrefs() : plugin_state_(g_default_plugin_state.Get()), |
| 508 prefs_(NULL) { |
| 364 } | 509 } |
| 365 | 510 |
| 366 PluginPrefs::~PluginPrefs() { | 511 PluginPrefs::~PluginPrefs() { |
| 367 } | 512 } |
| 368 | 513 |
| 369 void PluginPrefs::UpdatePreferences(int delay_ms) { | 514 void PluginPrefs::SetPolicyEnforcedPluginPatterns( |
| 370 BrowserThread::PostDelayedTask( | 515 const std::set<string16>& disabled_patterns, |
| 371 BrowserThread::FILE, | 516 const std::set<string16>& disabled_exception_patterns, |
| 372 FROM_HERE, | 517 const std::set<string16>& enabled_patterns) { |
| 373 NewRunnableMethod(this, &PluginPrefs::GetPreferencesDataOnFileThread), | 518 policy_disabled_plugin_patterns_ = disabled_patterns; |
| 374 delay_ms); | 519 policy_disabled_plugin_exception_patterns_ = disabled_exception_patterns; |
| 520 policy_enabled_plugin_patterns_ = enabled_patterns; |
| 375 } | 521 } |
| 376 | 522 |
| 377 void PluginPrefs::GetPreferencesDataOnFileThread() { | 523 void PluginPrefs::GetPreferencesDataOnFileThread() { |
| 378 std::vector<webkit::WebPluginInfo> plugins; | |
| 379 std::vector<webkit::npapi::PluginGroup> groups; | 524 std::vector<webkit::npapi::PluginGroup> groups; |
| 380 | 525 |
| 381 webkit::npapi::PluginList* plugin_list = | 526 webkit::npapi::PluginList* plugin_list = |
| 382 webkit::npapi::PluginList::Singleton(); | 527 webkit::npapi::PluginList::Singleton(); |
| 383 plugin_list->GetPlugins(&plugins); | |
| 384 plugin_list->GetPluginGroups(false, &groups); | 528 plugin_list->GetPluginGroups(false, &groups); |
| 385 | 529 |
| 386 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 530 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 387 NewRunnableMethod(this, &PluginPrefs::OnUpdatePreferences, | 531 NewRunnableMethod(this, &PluginPrefs::OnUpdatePreferences, groups)); |
| 388 plugins, groups)); | |
| 389 } | 532 } |
| 390 | 533 |
| 391 void PluginPrefs::OnUpdatePreferences( | 534 void PluginPrefs::OnUpdatePreferences( |
| 392 std::vector<webkit::WebPluginInfo> plugins, | |
| 393 std::vector<webkit::npapi::PluginGroup> groups) { | 535 std::vector<webkit::npapi::PluginGroup> groups) { |
| 394 if (!prefs_) | 536 if (!prefs_) |
| 395 return; | 537 return; |
| 396 | 538 |
| 397 ListPrefUpdate update(prefs_, prefs::kPluginsPluginsList); | 539 ListPrefUpdate update(prefs_, prefs::kPluginsPluginsList); |
| 398 ListValue* plugins_list = update.Get(); | 540 ListValue* plugins_list = update.Get(); |
| 399 plugins_list->Clear(); | 541 plugins_list->Clear(); |
| 400 | 542 |
| 401 FilePath internal_dir; | 543 FilePath internal_dir; |
| 402 if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir)) | 544 if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir)) |
| 403 prefs_->SetFilePath(prefs::kPluginsLastInternalDirectory, internal_dir); | 545 prefs_->SetFilePath(prefs::kPluginsLastInternalDirectory, internal_dir); |
| 404 | 546 |
| 405 // Add the plugin files. | 547 base::AutoLock auto_lock(lock_); |
| 406 for (size_t i = 0; i < plugins.size(); ++i) { | 548 |
| 407 DictionaryValue* summary = CreatePluginFileSummary(plugins[i]); | 549 // Add the plug-in groups. |
| 408 // If the plugin is managed by policy, store the user preferred state | 550 for (size_t i = 0; i < groups.size(); ++i) { |
| 409 // instead. | 551 // Add the plugin files to the same list. |
| 410 if (plugins[i].enabled & webkit::WebPluginInfo::MANAGED_MASK) { | 552 const std::vector<webkit::WebPluginInfo>& plugins = |
| 411 bool user_enabled = | 553 groups[i].web_plugin_infos(); |
| 412 (plugins[i].enabled & webkit::WebPluginInfo::USER_MASK) == | 554 for (size_t j = 0; j < plugins.size(); ++j) { |
| 413 webkit::WebPluginInfo::USER_ENABLED; | 555 DictionaryValue* summary = new DictionaryValue(); |
| 414 summary->SetBoolean("enabled", user_enabled); | 556 summary->SetString("path", plugins[j].path.value()); |
| 557 summary->SetString("name", plugins[j].name); |
| 558 summary->SetString("version", plugins[j].version); |
| 559 bool enabled = true; |
| 560 std::map<FilePath, bool>::iterator it = |
| 561 plugin_state_.find(plugins[j].path); |
| 562 if (it != plugin_state_.end()) |
| 563 enabled = it->second; |
| 564 summary->SetBoolean("enabled", enabled); |
| 565 plugins_list->Append(summary); |
| 415 } | 566 } |
| 567 |
| 568 DictionaryValue* summary = new DictionaryValue(); |
| 569 string16 name = groups[i].GetGroupName(); |
| 570 summary->SetString("name", name); |
| 571 bool enabled = true; |
| 572 std::map<string16, bool>::iterator it = |
| 573 plugin_group_state_.find(name); |
| 574 if (it != plugin_group_state_.end()) |
| 575 enabled = it->second; |
| 576 summary->SetBoolean("enabled", enabled); |
| 416 plugins_list->Append(summary); | 577 plugins_list->Append(summary); |
| 417 } | 578 } |
| 418 | |
| 419 // Add the groups as well. | |
| 420 for (size_t i = 0; i < groups.size(); ++i) { | |
| 421 DictionaryValue* summary = groups[i].GetSummary(); | |
| 422 // If the plugin is disabled only by policy don't store this state in the | |
| 423 // user pref store. | |
| 424 if (!groups[i].Enabled() && | |
| 425 webkit::npapi::PluginGroup::IsPluginNameDisabledByPolicy( | |
| 426 groups[i].GetGroupName())) | |
| 427 summary->SetBoolean("enabled", true); | |
| 428 plugins_list->Append(summary); | |
| 429 } | |
| 430 } | 579 } |
| 431 | 580 |
| 432 void PluginPrefs::NotifyPluginStatusChanged() { | 581 void PluginPrefs::NotifyPluginStatusChanged() { |
| 433 if (notify_pending_) | 582 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 434 return; | |
| 435 notify_pending_ = true; | |
| 436 MessageLoop::current()->PostTask( | |
| 437 FROM_HERE, | |
| 438 NewRunnableMethod(this, &PluginPrefs::OnNotifyPluginStatusChanged)); | |
| 439 } | |
| 440 | |
| 441 void PluginPrefs::OnNotifyPluginStatusChanged() { | |
| 442 notify_pending_ = false; | |
| 443 NotificationService::current()->Notify( | 583 NotificationService::current()->Notify( |
| 444 chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, | 584 chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED, |
| 445 Source<PluginPrefs>(this), | 585 Source<PluginPrefs>(this), |
| 446 NotificationService::NoDetails()); | 586 NotificationService::NoDetails()); |
| 447 } | 587 } |
| 448 | 588 |
| 449 /*static*/ | 589 /*static*/ |
| 450 void PluginPrefs::RegisterPrefs(PrefService* prefs) { | 590 void PluginPrefs::RegisterPrefs(PrefService* prefs) { |
| 451 FilePath internal_dir; | 591 FilePath internal_dir; |
| 452 PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir); | 592 PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir); |
| 453 prefs->RegisterFilePathPref(prefs::kPluginsLastInternalDirectory, | 593 prefs->RegisterFilePathPref(prefs::kPluginsLastInternalDirectory, |
| 454 internal_dir, | 594 internal_dir, |
| 455 PrefService::UNSYNCABLE_PREF); | 595 PrefService::UNSYNCABLE_PREF); |
| 456 prefs->RegisterBooleanPref(prefs::kPluginsEnabledInternalPDF, | 596 prefs->RegisterBooleanPref(prefs::kPluginsEnabledInternalPDF, |
| 457 false, | 597 false, |
| 458 PrefService::UNSYNCABLE_PREF); | 598 PrefService::UNSYNCABLE_PREF); |
| 459 prefs->RegisterBooleanPref(prefs::kPluginsEnabledNaCl, | 599 prefs->RegisterBooleanPref(prefs::kPluginsEnabledNaCl, |
| 460 false, | 600 false, |
| 461 PrefService::UNSYNCABLE_PREF); | 601 PrefService::UNSYNCABLE_PREF); |
| 462 prefs->RegisterListPref(prefs::kPluginsPluginsList, | 602 prefs->RegisterListPref(prefs::kPluginsPluginsList, |
| 463 PrefService::UNSYNCABLE_PREF); | 603 PrefService::UNSYNCABLE_PREF); |
| 464 prefs->RegisterListPref(prefs::kPluginsDisabledPlugins, | 604 prefs->RegisterListPref(prefs::kPluginsDisabledPlugins, |
| 465 PrefService::UNSYNCABLE_PREF); | 605 PrefService::UNSYNCABLE_PREF); |
| 466 prefs->RegisterListPref(prefs::kPluginsDisabledPluginsExceptions, | 606 prefs->RegisterListPref(prefs::kPluginsDisabledPluginsExceptions, |
| 467 PrefService::UNSYNCABLE_PREF); | 607 PrefService::UNSYNCABLE_PREF); |
| 468 prefs->RegisterListPref(prefs::kPluginsEnabledPlugins, | 608 prefs->RegisterListPref(prefs::kPluginsEnabledPlugins, |
| 469 PrefService::UNSYNCABLE_PREF); | 609 PrefService::UNSYNCABLE_PREF); |
| 470 } | 610 } |
| OLD | NEW |