summaryrefslogtreecommitdiffstats
path: root/chrome/browser/plugins/plugin_finder.cc
diff options
context:
space:
mode:
authoribraaaa@google.com <ibraaaa@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-20 20:53:18 +0000
committeribraaaa@google.com <ibraaaa@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-20 20:53:18 +0000
commit0f5e57f515094790fe2a8d638213c25314b8d3e8 (patch)
tree0f840c7ba459b30ba27d68929f2d7d5c6b01e41d /chrome/browser/plugins/plugin_finder.cc
parent67990d826888e15984ffe09c85ecf7796fb18a79 (diff)
downloadchromium_src-0f5e57f515094790fe2a8d638213c25314b8d3e8.zip
chromium_src-0f5e57f515094790fe2a8d638213c25314b8d3e8.tar.gz
chromium_src-0f5e57f515094790fe2a8d638213c25314b8d3e8.tar.bz2
Move chrome/browser/plugin_* to chrome/browser/plugins/
TBR=jhawkins@chromium.org BUG=124396 Review URL: https://chromiumcodereview.appspot.com/10933044 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@157834 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/plugins/plugin_finder.cc')
-rw-r--r--chrome/browser/plugins/plugin_finder.cc299
1 files changed, 299 insertions, 0 deletions
diff --git a/chrome/browser/plugins/plugin_finder.cc b/chrome/browser/plugins/plugin_finder.cc
new file mode 100644
index 0000000..91d8016
--- /dev/null
+++ b/chrome/browser/plugins/plugin_finder.cc
@@ -0,0 +1,299 @@
+// 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_finder.h"
+
+#include "base/bind.h"
+#include "base/json/json_reader.h"
+#include "base/message_loop.h"
+#include "base/stl_util.h"
+#include "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/plugins/plugin_installer.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/plugin_service.h"
+#include "googleurl/src/gurl.h"
+#include "grit/browser_resources.h"
+#include "ui/base/layout.h"
+#include "ui/base/resource/resource_bundle.h"
+
+using base::DictionaryValue;
+using content::PluginService;
+
+namespace {
+
+// Gets the base name of the file path as the identifier.
+static std::string GetIdentifier(const webkit::WebPluginInfo& plugin) {
+#if defined(OS_POSIX)
+ return plugin.path.BaseName().value();
+#elif defined(OS_WIN)
+ return base::SysWideToUTF8(plugin.path.BaseName().value());
+#endif
+}
+
+// Gets the plug-in group name as the plug-in name if it is not empty or
+// the filename without extension if the name is empty.
+static string16 GetGroupName(const webkit::WebPluginInfo& plugin) {
+ if (!plugin.name.empty())
+ return plugin.name;
+
+ FilePath::StringType path = plugin.path.BaseName().RemoveExtension().value();
+#if defined(OS_POSIX)
+ return UTF8ToUTF16(path);
+#elif defined(OS_WIN)
+ return WideToUTF16(path);
+#endif
+}
+
+// A callback barrier used to enforce the execution of a callback function
+// only when two different asynchronous callbacks are done execution.
+// The first asynchronous callback gets a PluginFinder instance and the
+// second asynchronous callback gets a list of plugins.
+class PluginFinderCallbackBarrier
+ : public base::RefCountedThreadSafe<PluginFinderCallbackBarrier> {
+ public:
+ typedef base::Callback<void(const PluginFinder::PluginVector&)>
+ PluginsCallback;
+
+ explicit PluginFinderCallbackBarrier(
+ const PluginFinder::CombinedCallback& callback)
+ : callback_(callback),
+ finder_(NULL) {
+ DCHECK(!callback_.is_null());
+ }
+
+ base::Callback<void(PluginFinder*)> CreatePluginFinderCallback() {
+ return base::Bind(&PluginFinderCallbackBarrier::GotPluginFinder, this);
+ }
+
+ PluginsCallback CreatePluginsCallback() {
+ return base::Bind(&PluginFinderCallbackBarrier::GotPlugins, this);
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<PluginFinderCallbackBarrier>;
+
+ ~PluginFinderCallbackBarrier() {
+ DCHECK(callback_.is_null());
+ }
+
+ void GotPlugins(const PluginFinder::PluginVector& plugins) {
+ plugins_.reset(new PluginFinder::PluginVector(plugins));
+ MaybeRunCallback();
+ }
+
+ void GotPluginFinder(PluginFinder* finder) {
+ finder_ = finder;
+ MaybeRunCallback();
+ }
+
+ // Executes the callback only when both asynchronous methods have finished
+ // their executions. This is identified by having non-null values in both
+ // |finder_| and |plugins_|.
+ void MaybeRunCallback() {
+ if (!finder_ || !plugins_.get())
+ return;
+
+ callback_.Run(*plugins_, finder_);
+ callback_.Reset();
+ }
+
+ PluginFinder::CombinedCallback callback_;
+ PluginFinder* finder_;
+ scoped_ptr<PluginFinder::PluginVector> plugins_;
+};
+
+} // namespace
+
+// static
+void PluginFinder::GetPluginsAndPluginFinder(
+ const PluginFinder::CombinedCallback& cb) {
+ scoped_refptr<PluginFinderCallbackBarrier> barrier =
+ new PluginFinderCallbackBarrier(cb);
+
+ PluginFinder::Get(barrier->CreatePluginFinderCallback());
+ PluginService::GetInstance()->GetPlugins(barrier->CreatePluginsCallback());
+}
+
+// static
+void PluginFinder::Get(const base::Callback<void(PluginFinder*)>& cb) {
+ // At a later point we might want to do intialization here that needs to be
+ // done asynchronously, like loading the plug-in list from disk or from a URL.
+ MessageLoop::current()->PostTask(FROM_HERE, base::Bind(cb, GetInstance()));
+}
+
+// static
+PluginFinder* PluginFinder::GetInstance() {
+ // PluginFinder::GetInstance() is the only method that's allowed to call
+ // Singleton<PluginFinder>::get().
+ return Singleton<PluginFinder>::get();
+}
+
+PluginFinder::PluginFinder() : plugin_list_(LoadPluginList()) {
+ if (!plugin_list_.get())
+ plugin_list_.reset(new DictionaryValue());
+}
+
+// static
+DictionaryValue* PluginFinder::LoadPluginList() {
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+ base::StringPiece json_resource(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_PLUGIN_DB_JSON, ui::SCALE_FACTOR_NONE));
+ std::string error_str;
+ scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
+ json_resource,
+ base::JSON_PARSE_RFC,
+ NULL,
+ &error_str));
+ if (!value.get()) {
+ DLOG(ERROR) << error_str;
+ return NULL;
+ }
+ if (value->GetType() != base::Value::TYPE_DICTIONARY)
+ return NULL;
+ return static_cast<base::DictionaryValue*>(value.release());
+#else
+ return new DictionaryValue();
+#endif
+}
+
+PluginFinder::~PluginFinder() {
+ STLDeleteValues(&installers_);
+}
+
+PluginInstaller* PluginFinder::FindPlugin(const std::string& mime_type,
+ const std::string& language) {
+ if (g_browser_process->local_state()->GetBoolean(prefs::kDisablePluginFinder))
+ return NULL;
+ for (DictionaryValue::Iterator plugin_it(*plugin_list_);
+ plugin_it.HasNext(); plugin_it.Advance()) {
+ const DictionaryValue* plugin = NULL;
+ if (!plugin_it.value().GetAsDictionary(&plugin)) {
+ NOTREACHED();
+ continue;
+ }
+ std::string language_str;
+ bool success = plugin->GetString("lang", &language_str);
+ if (language_str != language)
+ continue;
+ const ListValue* mime_types = NULL;
+ plugin->GetList("mime_types", &mime_types);
+ DCHECK(success);
+ for (ListValue::const_iterator mime_type_it = mime_types->begin();
+ mime_type_it != mime_types->end(); ++mime_type_it) {
+ std::string mime_type_str;
+ success = (*mime_type_it)->GetAsString(&mime_type_str);
+ DCHECK(success);
+ if (mime_type_str == mime_type) {
+ std::string identifier = plugin_it.key();
+ std::map<std::string, PluginInstaller*>::const_iterator installer =
+ installers_.find(identifier);
+ if (installer != installers_.end())
+ return installer->second;
+ return CreateInstaller(identifier, plugin);
+ }
+ }
+ }
+ return NULL;
+}
+
+PluginInstaller* PluginFinder::FindPluginWithIdentifier(
+ const std::string& identifier) {
+ std::map<std::string, PluginInstaller*>::const_iterator it =
+ installers_.find(identifier);
+ if (it != installers_.end())
+ return it->second;
+ DictionaryValue* plugin = NULL;
+ if (plugin_list_->GetDictionaryWithoutPathExpansion(identifier, &plugin))
+ return CreateInstaller(identifier, plugin);
+ return NULL;
+}
+
+PluginInstaller* PluginFinder::CreateInstaller(
+ const std::string& identifier,
+ const DictionaryValue* plugin_dict) {
+ DCHECK(!installers_[identifier]);
+ std::string url;
+ bool success = plugin_dict->GetString("url", &url);
+ std::string help_url;
+ plugin_dict->GetString("help_url", &help_url);
+ string16 name;
+ success = plugin_dict->GetString("name", &name);
+ DCHECK(success);
+ bool display_url = false;
+ plugin_dict->GetBoolean("displayurl", &display_url);
+ string16 group_name_matcher;
+ success = plugin_dict->GetString("group_name_matcher", &group_name_matcher);
+ DCHECK(success);
+
+ PluginInstaller* installer = new PluginInstaller(identifier,
+ name,
+ display_url,
+ GURL(url),
+ GURL(help_url),
+ group_name_matcher);
+ const ListValue* versions = NULL;
+ if (plugin_dict->GetList("versions", &versions)) {
+ for (ListValue::const_iterator it = versions->begin();
+ it != versions->end(); ++it) {
+ DictionaryValue* version_dict = NULL;
+ if (!(*it)->GetAsDictionary(&version_dict)) {
+ NOTREACHED();
+ continue;
+ }
+ std::string version;
+ success = version_dict->GetString("version", &version);
+ DCHECK(success);
+ std::string status_str;
+ success = version_dict->GetString("status", &status_str);
+ DCHECK(success);
+ PluginInstaller::SecurityStatus status =
+ PluginInstaller::SECURITY_STATUS_UP_TO_DATE;
+ success = PluginInstaller::ParseSecurityStatus(status_str, &status);
+ DCHECK(success);
+ installer->AddVersion(Version(version), status);
+ }
+ }
+
+ installers_[identifier] = installer;
+ return installer;
+}
+
+PluginInstaller* PluginFinder::GetPluginInstaller(
+ const webkit::WebPluginInfo& plugin) {
+ if (name_installers_.find(plugin.name) != name_installers_.end())
+ return name_installers_[plugin.name];
+
+ for (DictionaryValue::Iterator plugin_it(*plugin_list_);
+ plugin_it.HasNext(); plugin_it.Advance()) {
+ // This method triggers the lazy initialization for all PluginInstallers.
+ FindPluginWithIdentifier(plugin_it.key());
+ }
+
+ // Use the group name matcher to find the plug-in installer we want.
+ for (std::map<std::string, PluginInstaller*>::const_iterator it =
+ installers_.begin(); it != installers_.end(); ++it) {
+ if (!it->second->MatchesPlugin(plugin))
+ continue;
+
+ name_installers_[plugin.name] = it->second;
+ return it->second;
+ }
+
+ // The plug-in installer was not found, create a dummy one holding
+ // the name, identifier and group name only.
+ std::string identifier = GetIdentifier(plugin);
+ PluginInstaller* installer = new PluginInstaller(identifier,
+ GetGroupName(plugin),
+ false, GURL(), GURL(),
+ GetGroupName(plugin));
+ installers_[identifier] = installer;
+ name_installers_[plugin.name] = installer;
+ return installer;
+}