summaryrefslogtreecommitdiffstats
path: root/chrome/browser/plugin_updater.cc
diff options
context:
space:
mode:
authormnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-11 17:06:45 +0000
committermnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-11 17:06:45 +0000
commit9cc493fe559c45258060464f7a892fae0cc9c16e (patch)
treeef07d496fe314527a37b0fe45c42c1b93b01c41e /chrome/browser/plugin_updater.cc
parent7cf127e24d03711073a98105d9ad9f0329ddb8f4 (diff)
downloadchromium_src-9cc493fe559c45258060464f7a892fae0cc9c16e.zip
chromium_src-9cc493fe559c45258060464f7a892fae0cc9c16e.tar.gz
chromium_src-9cc493fe559c45258060464f7a892fae0cc9c16e.tar.bz2
Speculatively revert r96364, it's the best bet on the NaCL breakage.
TEST= BUG= TBR=bauerb@chromium.org Review URL: http://codereview.chromium.org/7627001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96409 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/plugin_updater.cc')
-rw-r--r--chrome/browser/plugin_updater.cc355
1 files changed, 355 insertions, 0 deletions
diff --git a/chrome/browser/plugin_updater.cc b/chrome/browser/plugin_updater.cc
new file mode 100644
index 0000000..887fba8
--- /dev/null
+++ b/chrome/browser/plugin_updater.cc
@@ -0,0 +1,355 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/plugin_updater.h"
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/path_service.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "base/version.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_content_client.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/pref_names.h"
+#include "content/browser/browser_thread.h"
+#include "content/common/notification_service.h"
+#include "webkit/plugins/npapi/plugin_list.h"
+#include "webkit/plugins/npapi/webplugininfo.h"
+
+// How long to wait to save the plugin enabled information, which might need to
+// go to disk.
+#define kPluginUpdateDelayMs (60 * 1000)
+
+PluginUpdater::PluginUpdater()
+ : notify_pending_(false) {
+}
+
+DictionaryValue* PluginUpdater::CreatePluginFileSummary(
+ const webkit::npapi::WebPluginInfo& plugin) {
+ DictionaryValue* data = new DictionaryValue();
+ data->SetString("path", plugin.path.value());
+ data->SetString("name", plugin.name);
+ data->SetString("version", plugin.version);
+ data->SetBoolean("enabled", webkit::npapi::IsPluginEnabled(plugin));
+ return data;
+}
+
+// static
+ListValue* PluginUpdater::GetPluginGroupsData() {
+ std::vector<webkit::npapi::PluginGroup> plugin_groups;
+ webkit::npapi::PluginList::Singleton()->GetPluginGroups(true, &plugin_groups);
+
+ // Construct DictionaryValues to return to the UI
+ ListValue* plugin_groups_data = new ListValue();
+ for (size_t i = 0; i < plugin_groups.size(); ++i) {
+ plugin_groups_data->Append(plugin_groups[i].GetDataForUI());
+ }
+ return plugin_groups_data;
+}
+
+void PluginUpdater::EnablePluginGroup(bool enable, const string16& group_name) {
+ webkit::npapi::PluginList::Singleton()->EnableGroup(enable, group_name);
+ NotifyPluginStatusChanged();
+}
+
+void PluginUpdater::EnablePlugin(bool enable,
+ const FilePath::StringType& path) {
+ FilePath file_path(path);
+ if (enable)
+ webkit::npapi::PluginList::Singleton()->EnablePlugin(file_path);
+ else
+ webkit::npapi::PluginList::Singleton()->DisablePlugin(file_path);
+
+ NotifyPluginStatusChanged();
+}
+
+void PluginUpdater::Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK_EQ(chrome::NOTIFICATION_PREF_CHANGED, type);
+ const std::string* pref_name = Details<std::string>(details).ptr();
+ if (!pref_name) {
+ NOTREACHED();
+ return;
+ }
+ if (*pref_name == prefs::kPluginsDisabledPlugins ||
+ *pref_name == prefs::kPluginsDisabledPluginsExceptions ||
+ *pref_name == prefs::kPluginsEnabledPlugins) {
+ PrefService* pref_service = Source<PrefService>(source).ptr();
+ const ListValue* disabled_list =
+ pref_service->GetList(prefs::kPluginsDisabledPlugins);
+ const ListValue* exceptions_list =
+ pref_service->GetList(prefs::kPluginsDisabledPluginsExceptions);
+ const ListValue* enabled_list =
+ pref_service->GetList(prefs::kPluginsEnabledPlugins);
+ UpdatePluginsStateFromPolicy(disabled_list, exceptions_list, enabled_list);
+ }
+}
+
+void PluginUpdater::UpdatePluginsStateFromPolicy(
+ const ListValue* disabled_list,
+ const ListValue* exceptions_list,
+ const ListValue* enabled_list) {
+ std::set<string16> disabled_plugin_patterns;
+ std::set<string16> disabled_plugin_exception_patterns;
+ std::set<string16> enabled_plugin_patterns;
+
+ ListValueToStringSet(disabled_list, &disabled_plugin_patterns);
+ ListValueToStringSet(exceptions_list, &disabled_plugin_exception_patterns);
+ ListValueToStringSet(enabled_list, &enabled_plugin_patterns);
+
+ webkit::npapi::PluginGroup::SetPolicyEnforcedPluginPatterns(
+ disabled_plugin_patterns,
+ disabled_plugin_exception_patterns,
+ enabled_plugin_patterns);
+
+ NotifyPluginStatusChanged();
+}
+
+void PluginUpdater::ListValueToStringSet(const ListValue* src,
+ std::set<string16>* dest) {
+ DCHECK(src);
+ DCHECK(dest);
+ ListValue::const_iterator end(src->end());
+ for (ListValue::const_iterator current(src->begin());
+ current != end; ++current) {
+ string16 plugin_name;
+ if ((*current)->GetAsString(&plugin_name)) {
+ dest->insert(plugin_name);
+ }
+ }
+}
+
+void PluginUpdater::SetProfile(Profile* profile) {
+ bool update_internal_dir = false;
+ FilePath last_internal_dir =
+ profile->GetPrefs()->GetFilePath(prefs::kPluginsLastInternalDirectory);
+ FilePath cur_internal_dir;
+ if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &cur_internal_dir) &&
+ cur_internal_dir != last_internal_dir) {
+ update_internal_dir = true;
+ profile->GetPrefs()->SetFilePath(
+ prefs::kPluginsLastInternalDirectory, cur_internal_dir);
+ }
+
+ bool force_enable_internal_pdf = false;
+ bool internal_pdf_enabled = false;
+ string16 pdf_group_name =
+ ASCIIToUTF16(chrome::ChromeContentClient::kPDFPluginName);
+ FilePath pdf_path;
+ PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path);
+ FilePath::StringType pdf_path_str = pdf_path.value();
+ if (!profile->GetPrefs()->GetBoolean(prefs::kPluginsEnabledInternalPDF)) {
+ // We switched to the internal pdf plugin being on by default, and so we
+ // need to force it to be enabled. We only want to do it this once though,
+ // i.e. we don't want to enable it again if the user disables it afterwards.
+ profile->GetPrefs()->SetBoolean(prefs::kPluginsEnabledInternalPDF, true);
+ force_enable_internal_pdf = true;
+ }
+
+ { // Scoped update of prefs::kPluginsPluginsList.
+ ListPrefUpdate update(profile->GetPrefs(), prefs::kPluginsPluginsList);
+ ListValue* saved_plugins_list = update.Get();
+ if (saved_plugins_list && !saved_plugins_list->empty()) {
+ for (ListValue::const_iterator it = saved_plugins_list->begin();
+ it != saved_plugins_list->end();
+ ++it) {
+ if (!(*it)->IsType(Value::TYPE_DICTIONARY)) {
+ LOG(WARNING) << "Invalid entry in " << prefs::kPluginsPluginsList;
+ continue; // Oops, don't know what to do with this item.
+ }
+
+ DictionaryValue* plugin = static_cast<DictionaryValue*>(*it);
+ string16 group_name;
+ bool enabled;
+ if (!plugin->GetBoolean("enabled", &enabled))
+ enabled = true;
+
+ FilePath::StringType path;
+ // The plugin list constains all the plugin files in addition to the
+ // plugin groups.
+ if (plugin->GetString("path", &path)) {
+ // Files have a path attribute, groups don't.
+ FilePath plugin_path(path);
+ if (update_internal_dir &&
+ FilePath::CompareIgnoreCase(plugin_path.DirName().value(),
+ last_internal_dir.value()) == 0) {
+ // If the internal plugin directory has changed and if the plugin
+ // looks internal, update its path in the prefs.
+ plugin_path = cur_internal_dir.Append(plugin_path.BaseName());
+ path = plugin_path.value();
+ plugin->SetString("path", path);
+ }
+
+ if (FilePath::CompareIgnoreCase(path, pdf_path_str) == 0) {
+ if (!enabled && force_enable_internal_pdf) {
+ enabled = true;
+ plugin->SetBoolean("enabled", true);
+ }
+
+ internal_pdf_enabled = enabled;
+ }
+
+ if (!enabled)
+ webkit::npapi::PluginList::Singleton()->DisablePlugin(plugin_path);
+ } else if (!enabled && plugin->GetString("name", &group_name)) {
+ // Don't disable this group if it's for the pdf plugin and we just
+ // forced it on.
+ if (force_enable_internal_pdf && pdf_group_name == group_name)
+ continue;
+
+ // Otherwise this is a list of groups.
+ EnablePluginGroup(false, group_name);
+ }
+ }
+ } else {
+ // If the saved plugin list is empty, then the call to UpdatePreferences()
+ // below failed in an earlier run, possibly because the user closed the
+ // browser too quickly. Try to force enable the internal PDF plugin again.
+ force_enable_internal_pdf = true;
+ }
+ } // Scoped update of prefs::kPluginsPluginsList.
+
+ // Build the set of policy enabled/disabled plugin patterns once and cache it.
+ // Don't do this in the constructor, there's no profile available there.
+ const ListValue* disabled_plugins =
+ profile->GetPrefs()->GetList(prefs::kPluginsDisabledPlugins);
+ const ListValue* disabled_exception_plugins =
+ profile->GetPrefs()->GetList(prefs::kPluginsDisabledPluginsExceptions);
+ const ListValue* enabled_plugins =
+ profile->GetPrefs()->GetList(prefs::kPluginsEnabledPlugins);
+ UpdatePluginsStateFromPolicy(disabled_plugins,
+ disabled_exception_plugins,
+ enabled_plugins);
+
+ registrar_.RemoveAll();
+ registrar_.Init(profile->GetPrefs());
+ registrar_.Add(prefs::kPluginsDisabledPlugins, this);
+ registrar_.Add(prefs::kPluginsDisabledPluginsExceptions, this);
+ registrar_.Add(prefs::kPluginsEnabledPlugins, this);
+
+ if (force_enable_internal_pdf || internal_pdf_enabled) {
+ // See http://crbug.com/50105 for background.
+ EnablePluginGroup(false, ASCIIToUTF16(
+ webkit::npapi::PluginGroup::kAdobeReaderGroupName));
+ }
+
+ if (force_enable_internal_pdf) {
+ // We want to save this, but doing so requires loading the list of plugins,
+ // so do it after a minute as to not impact startup performance. Note that
+ // plugins are loaded after 30s by the metrics service.
+ UpdatePreferences(profile, kPluginUpdateDelayMs);
+ }
+}
+
+void PluginUpdater::Shutdown() {
+ registrar_.RemoveAll();
+}
+
+void PluginUpdater::UpdatePreferences(Profile* profile, int delay_ms) {
+ BrowserThread::PostDelayedTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ NewRunnableFunction(
+ &PluginUpdater::GetPreferencesDataOnFileThread, profile), delay_ms);
+}
+
+void PluginUpdater::GetPreferencesDataOnFileThread(void* profile) {
+ std::vector<webkit::npapi::WebPluginInfo> plugins;
+ webkit::npapi::PluginList::Singleton()->GetPlugins(&plugins);
+
+ std::vector<webkit::npapi::PluginGroup> groups;
+ webkit::npapi::PluginList::Singleton()->GetPluginGroups(false, &groups);
+
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ NewRunnableFunction(&PluginUpdater::OnUpdatePreferences,
+ static_cast<Profile*>(profile),
+ plugins, groups));
+}
+
+void PluginUpdater::OnUpdatePreferences(
+ Profile* profile,
+ const std::vector<webkit::npapi::WebPluginInfo>& plugins,
+ const std::vector<webkit::npapi::PluginGroup>& groups) {
+ ListPrefUpdate update(profile->GetPrefs(), prefs::kPluginsPluginsList);
+ ListValue* plugins_list = update.Get();
+ plugins_list->Clear();
+
+ FilePath internal_dir;
+ if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir))
+ profile->GetPrefs()->SetFilePath(prefs::kPluginsLastInternalDirectory,
+ internal_dir);
+
+ // Add the plugin files.
+ for (size_t i = 0; i < plugins.size(); ++i) {
+ DictionaryValue* summary = CreatePluginFileSummary(plugins[i]);
+ // If the plugin is managed by policy, store the user preferred state
+ // instead.
+ if (plugins[i].enabled & webkit::npapi::WebPluginInfo::MANAGED_MASK) {
+ bool user_enabled =
+ (plugins[i].enabled & webkit::npapi::WebPluginInfo::USER_MASK) ==
+ webkit::npapi::WebPluginInfo::USER_ENABLED;
+ summary->SetBoolean("enabled", user_enabled);
+ }
+ plugins_list->Append(summary);
+ }
+
+ // Add the groups as well.
+ for (size_t i = 0; i < groups.size(); ++i) {
+ DictionaryValue* summary = groups[i].GetSummary();
+ // If the plugin is disabled only by policy don't store this state in the
+ // user pref store.
+ if (!groups[i].Enabled() &&
+ webkit::npapi::PluginGroup::IsPluginNameDisabledByPolicy(
+ groups[i].GetGroupName()))
+ summary->SetBoolean("enabled", true);
+ plugins_list->Append(summary);
+ }
+}
+
+void PluginUpdater::NotifyPluginStatusChanged() {
+ if (notify_pending_)
+ return;
+ notify_pending_ = true;
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(&PluginUpdater::OnNotifyPluginStatusChanged));
+}
+
+void PluginUpdater::OnNotifyPluginStatusChanged() {
+ GetInstance()->notify_pending_ = false;
+ NotificationService::current()->Notify(
+ content::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED,
+ Source<PluginUpdater>(GetInstance()),
+ NotificationService::NoDetails());
+}
+
+/*static*/
+PluginUpdater* PluginUpdater::GetInstance() {
+ return Singleton<PluginUpdater>::get();
+}
+
+/*static*/
+void PluginUpdater::RegisterPrefs(PrefService* prefs) {
+ FilePath internal_dir;
+ PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir);
+ prefs->RegisterFilePathPref(prefs::kPluginsLastInternalDirectory,
+ internal_dir,
+ PrefService::UNSYNCABLE_PREF);
+ prefs->RegisterListPref(prefs::kPluginsDisabledPlugins,
+ PrefService::UNSYNCABLE_PREF);
+ prefs->RegisterListPref(prefs::kPluginsDisabledPluginsExceptions,
+ PrefService::UNSYNCABLE_PREF);
+ prefs->RegisterListPref(prefs::kPluginsEnabledPlugins,
+ PrefService::UNSYNCABLE_PREF);
+}