// Copyright (c) 2012 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/plugins/plugin_prefs.h"

#include <string>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/plugins/plugin_installer.h"
#include "chrome/browser/plugins/plugin_metadata.h"
#include "chrome/browser/plugins/plugin_prefs_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/common/webplugininfo.h"

using content::BrowserThread;
using content::PluginService;

namespace {

bool IsComponentUpdatedPepperFlash(const base::FilePath& plugin) {
  if (plugin.BaseName().value() == chrome::kPepperFlashPluginFilename) {
    base::FilePath component_updated_pepper_flash_dir;
    if (PathService::Get(chrome::DIR_COMPONENT_UPDATED_PEPPER_FLASH_PLUGIN,
                         &component_updated_pepper_flash_dir) &&
        component_updated_pepper_flash_dir.IsParent(plugin)) {
      return true;
    }
  }

  return false;
}

}  // namespace

PluginPrefs::PluginState::PluginState() {
}

PluginPrefs::PluginState::~PluginState() {
}

bool PluginPrefs::PluginState::Get(const base::FilePath& plugin,
                                   bool* enabled) const {
  base::FilePath key = ConvertMapKey(plugin);
  std::map<base::FilePath, bool>::const_iterator iter = state_.find(key);
  if (iter != state_.end()) {
    *enabled = iter->second;
    return true;
  }
  return false;
}

void PluginPrefs::PluginState::Set(const base::FilePath& plugin, bool enabled) {
  state_[ConvertMapKey(plugin)] = enabled;
}

base::FilePath PluginPrefs::PluginState::ConvertMapKey(
    const base::FilePath& plugin) const {
  // Keep the state of component-updated and bundled Pepper Flash in sync.
  if (IsComponentUpdatedPepperFlash(plugin)) {
    base::FilePath bundled_pepper_flash;
    if (PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN,
                         &bundled_pepper_flash)) {
      return bundled_pepper_flash;
    }
  }

  return plugin;
}

// static
scoped_refptr<PluginPrefs> PluginPrefs::GetForProfile(Profile* profile) {
  return PluginPrefsFactory::GetPrefsForProfile(profile);
}

// static
scoped_refptr<PluginPrefs> PluginPrefs::GetForTestingProfile(
    Profile* profile) {
  return static_cast<PluginPrefs*>(
      PluginPrefsFactory::GetInstance()->SetTestingFactoryAndUse(
          profile, &PluginPrefsFactory::CreateForTestingProfile).get());
}

void PluginPrefs::EnablePluginGroup(bool enabled,
                                    const base::string16& group_name) {
  PluginService::GetInstance()->GetPlugins(
      base::Bind(&PluginPrefs::EnablePluginGroupInternal,
                 this, enabled, group_name));
}

void PluginPrefs::EnablePluginGroupInternal(
    bool enabled,
    const base::string16& group_name,
    const std::vector<content::WebPluginInfo>& plugins) {
  base::AutoLock auto_lock(lock_);
  PluginFinder* finder = PluginFinder::GetInstance();

  // Set the desired state for the group.
  plugin_group_state_[group_name] = enabled;

  // Update the state for all plug-ins in the group.
  for (size_t i = 0; i < plugins.size(); ++i) {
    scoped_ptr<PluginMetadata> plugin(finder->GetPluginMetadata(plugins[i]));
    if (group_name != plugin->name())
      continue;
    plugin_state_.Set(plugins[i].path, enabled);
  }

  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(&PluginPrefs::OnUpdatePreferences, this, plugins));
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(&PluginPrefs::NotifyPluginStatusChanged, this));
}

void PluginPrefs::EnablePlugin(
    bool enabled, const base::FilePath& path,
    const base::Callback<void(bool)>& callback) {
  PluginFinder* finder = PluginFinder::GetInstance();
  content::WebPluginInfo plugin;
  bool can_enable = true;
  if (PluginService::GetInstance()->GetPluginInfoByPath(path, &plugin)) {
    scoped_ptr<PluginMetadata> plugin_metadata(
        finder->GetPluginMetadata(plugin));
    PolicyStatus plugin_status = PolicyStatusForPlugin(plugin.name);
    PolicyStatus group_status = PolicyStatusForPlugin(plugin_metadata->name());
    if (enabled) {
      if (plugin_status == POLICY_DISABLED || group_status == POLICY_DISABLED)
        can_enable = false;
    } else {
      if (plugin_status == POLICY_ENABLED || group_status == POLICY_ENABLED)
        can_enable = false;
    }
  } else {
    NOTREACHED();
  }

  if (!can_enable) {
    base::MessageLoop::current()->PostTask(FROM_HERE,
                                           base::Bind(callback, false));
    return;
  }

  PluginService::GetInstance()->GetPlugins(
      base::Bind(&PluginPrefs::EnablePluginInternal, this,
                 enabled, path, finder, callback));
}

void PluginPrefs::EnablePluginInternal(
    bool enabled,
    const base::FilePath& path,
    PluginFinder* plugin_finder,
    const base::Callback<void(bool)>& callback,
    const std::vector<content::WebPluginInfo>& plugins) {
  {
    // Set the desired state for the plug-in.
    base::AutoLock auto_lock(lock_);
    plugin_state_.Set(path, enabled);
  }

  base::string16 group_name;
  for (size_t i = 0; i < plugins.size(); ++i) {
    if (plugins[i].path == path) {
      scoped_ptr<PluginMetadata> plugin_metadata(
          plugin_finder->GetPluginMetadata(plugins[i]));
      // set the group name for this plug-in.
      group_name = plugin_metadata->name();
      DCHECK_EQ(enabled, IsPluginEnabled(plugins[i]));
      break;
    }
  }

  bool all_disabled = true;
  for (size_t i = 0; i < plugins.size(); ++i) {
    scoped_ptr<PluginMetadata> plugin_metadata(
        plugin_finder->GetPluginMetadata(plugins[i]));
    DCHECK(!plugin_metadata->name().empty());
    if (group_name == plugin_metadata->name()) {
      all_disabled = all_disabled && !IsPluginEnabled(plugins[i]);
    }
  }

  if (!group_name.empty()) {
    // Update the state for the corresponding plug-in group.
    base::AutoLock auto_lock(lock_);
    plugin_group_state_[group_name] = !all_disabled;
  }

  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(&PluginPrefs::OnUpdatePreferences, this, plugins));
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(&PluginPrefs::NotifyPluginStatusChanged, this));
  callback.Run(true);
}

PluginPrefs::PolicyStatus PluginPrefs::PolicyStatusForPlugin(
    const base::string16& name) const {
  base::AutoLock auto_lock(lock_);
  if (IsStringMatchedInSet(name, policy_enabled_plugin_patterns_)) {
    return POLICY_ENABLED;
  } else if (IsStringMatchedInSet(name, policy_disabled_plugin_patterns_) &&
             !IsStringMatchedInSet(
                 name, policy_disabled_plugin_exception_patterns_)) {
    return POLICY_DISABLED;
  } else {
    return NO_POLICY;
  }
}

bool PluginPrefs::IsPluginEnabled(const content::WebPluginInfo& plugin) const {
  scoped_ptr<PluginMetadata> plugin_metadata(
      PluginFinder::GetInstance()->GetPluginMetadata(plugin));
  base::string16 group_name = plugin_metadata->name();

  // Check if the plug-in or its group is enabled by policy.
  PolicyStatus plugin_status = PolicyStatusForPlugin(plugin.name);
  PolicyStatus group_status = PolicyStatusForPlugin(group_name);
  if (plugin_status == POLICY_ENABLED || group_status == POLICY_ENABLED)
    return true;

  // Check if the plug-in or its group is disabled by policy.
  if (plugin_status == POLICY_DISABLED || group_status == POLICY_DISABLED)
    return false;

  // If enabling NaCl, make sure the plugin is also enabled. See bug
  // http://code.google.com/p/chromium/issues/detail?id=81010 for more
  // information.
  // TODO(dspringer): When NaCl is on by default, remove this code.
  if ((plugin.name ==
       ASCIIToUTF16(ChromeContentClient::kNaClPluginName)) &&
      CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaCl)) {
    return true;
  }

  base::AutoLock auto_lock(lock_);
  // Check user preferences for the plug-in.
  bool plugin_enabled = false;
  if (plugin_state_.Get(plugin.path, &plugin_enabled))
    return plugin_enabled;

  // Check user preferences for the plug-in group.
  std::map<base::string16, bool>::const_iterator group_it(
      plugin_group_state_.find(group_name));
  if (group_it != plugin_group_state_.end())
    return group_it->second;

  // Default to enabled.
  return true;
}

void PluginPrefs::UpdatePatternsAndNotify(std::set<base::string16>* patterns,
                                          const std::string& pref_name) {
  base::AutoLock auto_lock(lock_);
  ListValueToStringSet(prefs_->GetList(pref_name.c_str()), patterns);

  NotifyPluginStatusChanged();
}

/*static*/
bool PluginPrefs::IsStringMatchedInSet(
    const base::string16& name,
    const std::set<base::string16>& pattern_set) {
  std::set<base::string16>::const_iterator pattern(pattern_set.begin());
  while (pattern != pattern_set.end()) {
    if (MatchPattern(name, *pattern))
      return true;
    ++pattern;
  }

  return false;
}

/* static */
void PluginPrefs::ListValueToStringSet(const ListValue* src,
                                       std::set<base::string16>* dest) {
  DCHECK(src);
  DCHECK(dest);
  dest->clear();
  ListValue::const_iterator end(src->end());
  for (ListValue::const_iterator current(src->begin());
       current != end; ++current) {
    base::string16 plugin_name;
    if ((*current)->GetAsString(&plugin_name)) {
      dest->insert(plugin_name);
    }
  }
}

void PluginPrefs::SetPrefs(PrefService* prefs) {
  prefs_ = prefs;
  bool update_internal_dir = false;
  base::FilePath last_internal_dir =
      prefs_->GetFilePath(prefs::kPluginsLastInternalDirectory);
  base::FilePath cur_internal_dir;
  if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &cur_internal_dir) &&
      cur_internal_dir != last_internal_dir) {
    update_internal_dir = true;
    prefs_->SetFilePath(
        prefs::kPluginsLastInternalDirectory, cur_internal_dir);
  }

  bool migrate_to_pepper_flash = false;
#if defined(OS_WIN) || defined(OS_MACOSX)
  // If bundled NPAPI Flash is enabled while Pepper Flash is disabled, we
  // would like to turn Pepper Flash on. And we only want to do it once.
  // TODO(yzshen): Remove all |migrate_to_pepper_flash|-related code after it
  // has been run once by most users. (Maybe Chrome 24 or Chrome 25.)
  // NOTE(shess): Keep in mind that Mac is on a different schedule.
  if (!prefs_->GetBoolean(prefs::kPluginsMigratedToPepperFlash)) {
    prefs_->SetBoolean(prefs::kPluginsMigratedToPepperFlash, true);
    migrate_to_pepper_flash = true;
  }
#endif

  bool remove_component_pepper_flash_settings = false;
  // If component-updated Pepper Flash is disabled, we would like to remove that
  // settings item. And we only want to do it once. (Please see the comments of
  // kPluginsRemovedOldComponentPepperFlashSettings for why.)
  // TODO(yzshen): Remove all |remove_component_pepper_flash_settings|-related
  // code after it has been run once by most users.
  if (!prefs_->GetBoolean(
          prefs::kPluginsRemovedOldComponentPepperFlashSettings)) {
    prefs_->SetBoolean(prefs::kPluginsRemovedOldComponentPepperFlashSettings,
                       true);
    remove_component_pepper_flash_settings = true;
  }

  {  // Scoped update of prefs::kPluginsPluginsList.
    ListPrefUpdate update(prefs_, prefs::kPluginsPluginsList);
    ListValue* saved_plugins_list = update.Get();
    if (saved_plugins_list && !saved_plugins_list->empty()) {
      // The following four variables are only valid when
      // |migrate_to_pepper_flash| is set to true.
      base::FilePath npapi_flash;
      base::FilePath pepper_flash;
      DictionaryValue* pepper_flash_node = NULL;
      bool npapi_flash_enabled = false;
      if (migrate_to_pepper_flash) {
        PathService::Get(chrome::FILE_FLASH_PLUGIN, &npapi_flash);
        PathService::Get(chrome::FILE_PEPPER_FLASH_PLUGIN, &pepper_flash);
      }

      // Used when |remove_component_pepper_flash_settings| is set to true.
      ListValue::iterator component_pepper_flash_node =
          saved_plugins_list->end();

      for (ListValue::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);
        base::string16 group_name;
        bool enabled;
        if (!plugin->GetBoolean("enabled", &enabled))
          enabled = true;

        base::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.
          base::FilePath plugin_path(path);

          // The path to the intenral plugin directory changes everytime Chrome
          // is auto-updated, since it contains the current version number. For
          // example, it changes from foobar\Chrome\Application\21.0.1180.83 to
          // foobar\Chrome\Application\21.0.1180.89.
          // However, we would like the settings of internal plugins to persist
          // across Chrome updates. Therefore, we need to recognize those paths
          // that are within the previous internal plugin directory, and update
          // them in the prefs accordingly.
          if (update_internal_dir) {
            base::FilePath relative_path;

            // Extract the part of |plugin_path| that is relative to
            // |last_internal_dir|. For example, |relative_path| will be
            // foo\bar.dll if |plugin_path| is <last_internal_dir>\foo\bar.dll.
            //
            // Every iteration the last path component from |plugin_path| is
            // removed and prepended to |relative_path| until we get up to
            // |last_internal_dir|.
            while (last_internal_dir.IsParent(plugin_path)) {
              relative_path = plugin_path.BaseName().Append(relative_path);

              base::FilePath old_path = plugin_path;
              plugin_path = plugin_path.DirName();
              // To be extra sure that we won't end up in an infinite loop.
              if (old_path == plugin_path) {
                NOTREACHED();
                break;
              }
            }

            // If |relative_path| is empty, |plugin_path| is not within
            // |last_internal_dir|. We don't need to update it.
            if (!relative_path.empty()) {
              plugin_path = cur_internal_dir.Append(relative_path);
              path = plugin_path.value();
              plugin->SetString("path", path);
            }
          }

          if (migrate_to_pepper_flash &&
                     base::FilePath::CompareEqualIgnoreCase(
                         path, npapi_flash.value())) {
            npapi_flash_enabled = enabled;
          } else if (migrate_to_pepper_flash &&
                     base::FilePath::CompareEqualIgnoreCase(
                         path, pepper_flash.value())) {
            if (!enabled)
              pepper_flash_node = plugin;
          } else if (remove_component_pepper_flash_settings &&
                     IsComponentUpdatedPepperFlash(plugin_path)) {
            if (!enabled) {
              component_pepper_flash_node = it;
              // Skip setting |enabled| into |plugin_state_|.
              continue;
            }
          }

          plugin_state_.Set(plugin_path, enabled);
        } else if (!enabled && plugin->GetString("name", &group_name)) {
          // Otherwise this is a list of groups.
          plugin_group_state_[group_name] = false;
        }
      }

      if (npapi_flash_enabled && pepper_flash_node) {
        DCHECK(migrate_to_pepper_flash);
        pepper_flash_node->SetBoolean("enabled", true);
        plugin_state_.Set(pepper_flash, true);
      }

      if (component_pepper_flash_node != saved_plugins_list->end()) {
        DCHECK(remove_component_pepper_flash_settings);
        saved_plugins_list->Erase(component_pepper_flash_node, NULL);
      }
    } 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.

      // Only want one PDF plugin enabled at a time. See http://crbug.com/50105
      // for background.
      plugin_group_state_[ASCIIToUTF16(
          PluginMetadata::kAdobeReaderGroupName)] = false;
    }
  }  // 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.
  ListValueToStringSet(prefs_->GetList(prefs::kPluginsDisabledPlugins),
                       &policy_disabled_plugin_patterns_);
  ListValueToStringSet(
      prefs_->GetList(prefs::kPluginsDisabledPluginsExceptions),
      &policy_disabled_plugin_exception_patterns_);
  ListValueToStringSet(prefs_->GetList(prefs::kPluginsEnabledPlugins),
                       &policy_enabled_plugin_patterns_);

  registrar_.Init(prefs_);

  // Because pointers to our own members will remain unchanged for the
  // lifetime of |registrar_| (which we also own), we can bind their
  // pointer values directly in the callbacks to avoid string-based
  // lookups at notification time.
  registrar_.Add(prefs::kPluginsDisabledPlugins,
                 base::Bind(&PluginPrefs::UpdatePatternsAndNotify,
                            base::Unretained(this),
                            &policy_disabled_plugin_patterns_));
  registrar_.Add(prefs::kPluginsDisabledPluginsExceptions,
                 base::Bind(&PluginPrefs::UpdatePatternsAndNotify,
                            base::Unretained(this),
                            &policy_disabled_plugin_exception_patterns_));
  registrar_.Add(prefs::kPluginsEnabledPlugins,
                 base::Bind(&PluginPrefs::UpdatePatternsAndNotify,
                            base::Unretained(this),
                            &policy_enabled_plugin_patterns_));

  NotifyPluginStatusChanged();
}

void PluginPrefs::ShutdownOnUIThread() {
  prefs_ = NULL;
  registrar_.RemoveAll();
}

PluginPrefs::PluginPrefs() : profile_(NULL),
                             prefs_(NULL) {
}

PluginPrefs::~PluginPrefs() {
}

void PluginPrefs::SetPolicyEnforcedPluginPatterns(
    const std::set<base::string16>& disabled_patterns,
    const std::set<base::string16>& disabled_exception_patterns,
    const std::set<base::string16>& enabled_patterns) {
  policy_disabled_plugin_patterns_ = disabled_patterns;
  policy_disabled_plugin_exception_patterns_ = disabled_exception_patterns;
  policy_enabled_plugin_patterns_ = enabled_patterns;
}

void PluginPrefs::OnUpdatePreferences(
    const std::vector<content::WebPluginInfo>& plugins) {
  if (!prefs_)
    return;

  PluginFinder* finder = PluginFinder::GetInstance();
  ListPrefUpdate update(prefs_, prefs::kPluginsPluginsList);
  ListValue* plugins_list = update.Get();
  plugins_list->Clear();

  base::FilePath internal_dir;
  if (PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir))
    prefs_->SetFilePath(prefs::kPluginsLastInternalDirectory, internal_dir);

  base::AutoLock auto_lock(lock_);

  // Add the plugin files.
  std::set<base::string16> group_names;
  for (size_t i = 0; i < plugins.size(); ++i) {
    DictionaryValue* summary = new DictionaryValue();
    summary->SetString("path", plugins[i].path.value());
    summary->SetString("name", plugins[i].name);
    summary->SetString("version", plugins[i].version);
    bool enabled = true;
    plugin_state_.Get(plugins[i].path, &enabled);
    summary->SetBoolean("enabled", enabled);
    plugins_list->Append(summary);

    scoped_ptr<PluginMetadata> plugin_metadata(
        finder->GetPluginMetadata(plugins[i]));
    // Insert into a set of all group names.
    group_names.insert(plugin_metadata->name());
  }

  // Add the plug-in groups.
  for (std::set<base::string16>::const_iterator it = group_names.begin();
      it != group_names.end(); ++it) {
    DictionaryValue* summary = new DictionaryValue();
    summary->SetString("name", *it);
    bool enabled = true;
    std::map<base::string16, bool>::iterator gstate_it =
        plugin_group_state_.find(*it);
    if (gstate_it != plugin_group_state_.end())
      enabled = gstate_it->second;
    summary->SetBoolean("enabled", enabled);
    plugins_list->Append(summary);
  }
}

void PluginPrefs::NotifyPluginStatusChanged() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  content::NotificationService::current()->Notify(
      chrome::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED,
      content::Source<Profile>(profile_),
      content::NotificationService::NoDetails());
}
