summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorgspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-14 23:59:26 +0000
committergspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-14 23:59:26 +0000
commit6fdd418b9a50f24f7788e229bd3ae4acaf6ec1d4 (patch)
treed55a82a8551a7df61d6c84f13835e7b8e17507f3 /chrome/browser
parent6f7582fd31ff06faa0298ab6d530369256e9f20a (diff)
downloadchromium_src-6fdd418b9a50f24f7788e229bd3ae4acaf6ec1d4.zip
chromium_src-6fdd418b9a50f24f7788e229bd3ae4acaf6ec1d4.tar.gz
chromium_src-6fdd418b9a50f24f7788e229bd3ae4acaf6ec1d4.tar.bz2
This adds a plugin selection policy for selecting which plugin is
allowed for a particular domain. It is only used on ChromeOS. It reads from a file that is installed in a known location on ChromeOS, and uses that as it's policy. When there are multiple plugins supporting the same mime-type, the appropriate plugin file to load is now selected based on policy. BUG=http://crosbug.com/7403 TEST=ran new unit test, tested on device. Review URL: http://codereview.chromium.org/3717005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62679 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/chromeos/plugin_selection_policy.cc166
-rw-r--r--chrome/browser/chromeos/plugin_selection_policy.h79
-rw-r--r--chrome/browser/chromeos/plugin_selection_policy_unittest.cc270
-rw-r--r--chrome/browser/plugin_service.cc80
-rw-r--r--chrome/browser/plugin_service.h38
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc76
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h19
7 files changed, 670 insertions, 58 deletions
diff --git a/chrome/browser/chromeos/plugin_selection_policy.cc b/chrome/browser/chromeos/plugin_selection_policy.cc
new file mode 100644
index 0000000..b27bc42
--- /dev/null
+++ b/chrome/browser/chromeos/plugin_selection_policy.cc
@@ -0,0 +1,166 @@
+// Copyright (c) 2010 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/chromeos/plugin_selection_policy.h"
+
+#include <algorithm>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "base/auto_reset.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "chrome/browser/browser_thread.h"
+#include "googleurl/src/gurl.h"
+
+#if !defined(OS_CHROMEOS)
+#error This file is meant to be compiled on ChromeOS only.
+#endif
+
+using std::vector;
+using std::string;
+using std::pair;
+using std::map;
+
+namespace chromeos {
+
+static const char kPluginSelectionPolicyFile[] =
+ "/usr/share/chromeos-assets/flash/plugin_policy";
+
+PluginSelectionPolicy::PluginSelectionPolicy() : initialized_(false) {
+}
+
+void PluginSelectionPolicy::StartInit() {
+ // Initialize the policy on the FILE thread, since it reads from a
+ // policy file.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &chromeos::PluginSelectionPolicy::Init));
+}
+
+bool PluginSelectionPolicy::Init() {
+ return InitFromFile(FilePath(kPluginSelectionPolicyFile));
+}
+
+bool PluginSelectionPolicy::InitFromFile(const FilePath& policy_file) {
+ // This must always be called from the FILE thread.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ // Note: We're "initialized" even if loading the file fails.
+ initialized_ = true;
+
+ string data;
+ // This should be a really small file, so we're OK with just
+ // slurping it.
+ if (!file_util::ReadFileToString(policy_file, &data)) {
+ LOG(ERROR) << "Unable to read plugin policy file \""
+ << policy_file.value() << "\".";
+ return false;
+ }
+
+ std::istringstream input_stream(data);
+ string line;
+ map<string, Policy> policies;
+ Policy policy;
+ string last_plugin;
+
+ while (std::getline(input_stream, line)) {
+ // Strip comments.
+ string::size_type pos = line.find("#");
+ if (pos != string::npos) {
+ line = line.substr(0, pos);
+ }
+ TrimWhitespaceASCII(line, TRIM_ALL, &line);
+ if (line.find("allow") == 0) {
+ // Has to be preceeded by a "plugin" statement.
+ if (last_plugin.empty()) {
+ LOG(ERROR) << "Plugin policy file error: 'allow' out of context.";
+ return false;
+ }
+ line = line.substr(6);
+ TrimWhitespaceASCII(line, TRIM_ALL, &line);
+ line = StringToLowerASCII(line);
+ policy.push_back(make_pair(true, line));
+ }
+ if (line.find("deny") == 0) {
+ // Has to be preceeded by a "plugin" statement.
+ if (last_plugin.empty()) {
+ LOG(ERROR) << "Plugin policy file error: 'deny' out of context.";
+ return false;
+ }
+ line = line.substr(5);
+ TrimWhitespaceASCII(line, TRIM_ALL, &line);
+ line = StringToLowerASCII(line);
+ policy.push_back(make_pair(false, line));
+ }
+ if (line.find("plugin") == 0) {
+ line = line.substr(7);
+ TrimWhitespaceASCII(line, TRIM_ALL, &line);
+ if (!policy.empty() && !last_plugin.empty())
+ policies.insert(make_pair(last_plugin, policy));
+ last_plugin = line;
+ policy.clear();
+ }
+ }
+
+ if (!last_plugin.empty())
+ policies.insert(make_pair(last_plugin, policy));
+
+ policies_.swap(policies);
+ return true;
+}
+
+int PluginSelectionPolicy::FindFirstAllowed(
+ const GURL& url,
+ const std::vector<WebPluginInfo>& info) {
+ for (std::vector<WebPluginInfo>::size_type i = 0; i < info.size(); ++i) {
+ if (IsAllowed(url, info[i].path))
+ return i;
+ }
+ return -1;
+}
+
+bool PluginSelectionPolicy::IsAllowed(const GURL& url,
+ const FilePath& path) {
+ // This must always be called from the FILE thread, to be sure
+ // initialization doesn't happen at the same time.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ // Make sure that we notice if this starts being called before
+ // initialization is complete. Right now it is guaranteed only by
+ // the startup order and the fact that InitFromFile runs on the FILE
+ // thread too.
+ DCHECK(initialized_) << "Tried to check policy before policy is initialized.";
+
+ string name = path.BaseName().value();
+
+ PolicyMap::iterator policy_iter = policies_.find(name);
+ if (policy_iter != policies_.end()) {
+ Policy& policy(policy_iter->second);
+
+ // We deny by default. (equivalent to "deny" at the top of the section)
+ bool allow = false;
+
+ for (Policy::iterator iter = policy.begin(); iter != policy.end(); ++iter) {
+ bool policy_allow = iter->first;
+ string& policy_domain = iter->second;
+ if (policy_domain.empty() || url.DomainIs(policy_domain.c_str(),
+ policy_domain.size())) {
+ allow = policy_allow;
+ }
+ }
+ return allow;
+ }
+
+ // If it's not in the policy file, then we assume it's OK to allow
+ // it.
+ return true;
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/plugin_selection_policy.h b/chrome/browser/chromeos/plugin_selection_policy.h
new file mode 100644
index 0000000..4786e3c
--- /dev/null
+++ b/chrome/browser/chromeos/plugin_selection_policy.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_BROWSER_CHROMEOS_PLUGIN_SELECTION_POLICY_H_
+#define CHROME_BROWSER_CHROMEOS_PLUGIN_SELECTION_POLICY_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "base/ref_counted.h"
+#include "webkit/glue/plugins/webplugininfo.h"
+
+class GURL;
+class FilePath;
+
+namespace chromeos {
+
+#if !defined(OS_CHROMEOS)
+#error This file is meant to be compiled on ChromeOS only.
+#endif
+
+// This class is used to provide logic for selection of a plugin
+// executable path in the browser. It loads a policy file for
+// selection of particular plugins based on the domain they are be
+// instantiated for. It is used by the PluginService. It is (and
+// should be) only used for ChromeOS.
+
+// The functions in this class must only be called on the FILE thread
+// (and will DCHECK if they aren't).
+
+class PluginSelectionPolicy
+ : public base::RefCountedThreadSafe<PluginSelectionPolicy> {
+ public:
+ PluginSelectionPolicy();
+
+ // This should be called before any other method. This starts the
+ // process of initialization on the FILE thread.
+ void StartInit();
+
+ // Returns the first allowed plugin in the given vector of plugin
+ // information. Returns -1 if no plugins in the info vector are
+ // allowed (or if the info vector is empty). InitFromFile must
+ // complete before any calls to FindFirstAllowed happen or it will
+ // assert.
+ int FindFirstAllowed(const GURL& url, const std::vector<WebPluginInfo>& info);
+
+ // Applies the current policy to the given path using the url to
+ // look up what the policy for that domain is. Returns true if the
+ // given plugin is allowed for that domain. InitFromFile must
+ // complete before any calls to IsAllowed happen or it will assert.
+ bool IsAllowed(const GURL& url, const FilePath& path);
+
+ private:
+ // To allow access to InitFromFile
+ FRIEND_TEST_ALL_PREFIXES(PluginSelectionPolicyTest, Basic);
+ FRIEND_TEST_ALL_PREFIXES(PluginSelectionPolicyTest, InitFromFile);
+ FRIEND_TEST_ALL_PREFIXES(PluginSelectionPolicyTest, IsAllowed);
+ FRIEND_TEST_ALL_PREFIXES(PluginSelectionPolicyTest, FindFirstAllowed);
+
+ // Initializes from the default policy file.
+ bool Init();
+
+ // Initializes from the given file.
+ bool InitFromFile(const FilePath& policy_file);
+
+ typedef std::vector<std::pair<bool, std::string> > Policy;
+ typedef std::map<std::string, Policy> PolicyMap;
+
+ PolicyMap policies_;
+ bool initialized_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginSelectionPolicy);
+};
+
+} // namespace chromeos
+#endif // CHROME_BROWSER_CHROMEOS_PLUGIN_SELECTION_POLICY_H_
diff --git a/chrome/browser/chromeos/plugin_selection_policy_unittest.cc b/chrome/browser/chromeos/plugin_selection_policy_unittest.cc
new file mode 100644
index 0000000..455ed37
--- /dev/null
+++ b/chrome/browser/chromeos/plugin_selection_policy_unittest.cc
@@ -0,0 +1,270 @@
+// Copyright (c) 2010 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/chromeos/plugin_selection_policy.h"
+
+#include <string>
+#include <vector>
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/ref_counted.h"
+#include "base/scoped_temp_dir.h"
+#include "chrome/browser/browser_thread.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+using std::string;
+using std::vector;
+
+#if !defined(OS_CHROMEOS)
+#error This file is meant to be compiled on ChromeOS only.
+#endif
+
+namespace chromeos {
+
+const char kBasicPolicy[] = "# This is a basic policy\n"
+ "plugin test.so\n"
+ "allow foo.com\n"
+ "deny bar.com\n";
+
+const char kNoPluginPolicy[] = "# This is a policy with missing plugin.\n"
+ "# Missing plugin test.so\n"
+ "allow foo.com\n"
+ "deny bar.com\n";
+const char kNoRulesPolicy[] = "# This is a policy with no rules\n"
+ "plugin test.so\n";
+
+const char kEmptyPolicy[] = "# This is an empty policy\n";
+
+const char kCommentTestPolicy[] = "# This is a policy with inline comments.\n"
+ "plugin test.so# like this\n"
+ "allow foo.com # and this\n"
+ "deny bar.com # and this\n";
+
+const char kMultiPluginTestPolicy[] =
+ "# This is a policy with multiple plugins.\n"
+ "plugin allow_foo.so\n"
+ "allow foo.com\n"
+ "deny bar.com\n"
+ "plugin allow_baz_bim1.so\n"
+ "deny google.com\n"
+ "allow baz.com\n"
+ "allow bim.com\n"
+ "plugin allow_baz_bim2.so\n"
+ "deny google.com\n"
+ "allow baz.com\n"
+ "allow bim.com\n";
+
+const char kWhitespaceTestPolicy[] = "# This is a policy with odd whitespace.\n"
+ " plugin\ttest.so# like this\n"
+ "\n\n \n allow\t\tfoo.com # and this\n"
+ "\tdeny bar.com\t\t\t# and this \n";
+
+class PluginSelectionPolicyTest : public PlatformTest {
+ public:
+ PluginSelectionPolicyTest()
+ : loop_(MessageLoop::TYPE_DEFAULT),
+ file_thread_(BrowserThread::FILE, &loop_) {}
+
+ virtual void SetUp() {
+ PlatformTest::SetUp();
+ // Create a policy file to test with.
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ }
+
+ protected:
+ bool CreatePolicy(const std::string& name,
+ const std::string& contents,
+ FilePath* path) {
+ FilePath policy_file(temp_dir_.path());
+ policy_file = policy_file.Append(FilePath(name));
+ int bytes_written = file_util::WriteFile(policy_file,
+ contents.c_str(),
+ contents.size());
+ if (path)
+ *path = policy_file;
+ return bytes_written >= 0;
+ }
+
+ private:
+ ScopedTempDir temp_dir_;
+ MessageLoop loop_;
+ BrowserThread file_thread_;
+};
+
+TEST_F(PluginSelectionPolicyTest, Basic) {
+ FilePath path;
+ ASSERT_TRUE(CreatePolicy("basic", kBasicPolicy, &path));
+ scoped_refptr<PluginSelectionPolicy> policy = new PluginSelectionPolicy;
+ EXPECT_TRUE(policy->InitFromFile(path));
+}
+
+TEST_F(PluginSelectionPolicyTest, InitFromFile) {
+ {
+ FilePath path;
+ ASSERT_TRUE(CreatePolicy("basic", kBasicPolicy, &path));
+ scoped_refptr<PluginSelectionPolicy> policy = new PluginSelectionPolicy;
+ EXPECT_TRUE(policy->InitFromFile(path));
+ }
+
+ {
+ FilePath path;
+ ASSERT_TRUE(CreatePolicy("no_plugin", kNoPluginPolicy, &path));
+ scoped_refptr<PluginSelectionPolicy> policy = new PluginSelectionPolicy;
+ EXPECT_FALSE(policy->InitFromFile(path));
+ }
+
+ {
+ FilePath path;
+ ASSERT_TRUE(CreatePolicy("no_rules", kNoRulesPolicy, &path));
+ scoped_refptr<PluginSelectionPolicy> policy = new PluginSelectionPolicy;
+ EXPECT_TRUE(policy->InitFromFile(path));
+ }
+
+ {
+ FilePath path;
+ ASSERT_TRUE(CreatePolicy("empty", kEmptyPolicy, &path));
+ scoped_refptr<PluginSelectionPolicy> policy = new PluginSelectionPolicy;
+ EXPECT_TRUE(policy->InitFromFile(path));
+ }
+
+ {
+ FilePath path;
+ ASSERT_TRUE(CreatePolicy("comment", kCommentTestPolicy, &path));
+ scoped_refptr<PluginSelectionPolicy> policy = new PluginSelectionPolicy;
+ EXPECT_TRUE(policy->InitFromFile(path));
+ }
+
+ {
+ FilePath path;
+ ASSERT_TRUE(CreatePolicy("comment", kMultiPluginTestPolicy, &path));
+ scoped_refptr<PluginSelectionPolicy> policy = new PluginSelectionPolicy;
+ EXPECT_TRUE(policy->InitFromFile(path));
+ }
+
+ {
+ FilePath path;
+ ASSERT_TRUE(CreatePolicy("whitespace", kWhitespaceTestPolicy, &path));
+ scoped_refptr<PluginSelectionPolicy> policy = new PluginSelectionPolicy;
+ EXPECT_TRUE(policy->InitFromFile(path));
+ }
+}
+
+TEST_F(PluginSelectionPolicyTest, IsAllowed) {
+ FilePath path;
+ ASSERT_TRUE(CreatePolicy("basic", kBasicPolicy, &path));
+
+ scoped_refptr<PluginSelectionPolicy> policy1 = new PluginSelectionPolicy;
+ ASSERT_TRUE(policy1->InitFromFile(path));
+ EXPECT_TRUE(policy1->IsAllowed(GURL("http://www.foo.com/blah.html"),
+ FilePath("/usr/local/bin/test.so")));
+ EXPECT_FALSE(policy1->IsAllowed(GURL("http://www.bar.com/blah.html"),
+ FilePath("/usr/local/bin/test.so")));
+ EXPECT_FALSE(policy1->IsAllowed(GURL("http://www.baz.com/blah.html"),
+ FilePath("/usr/local/bin/test.so")));
+ EXPECT_TRUE(policy1->IsAllowed(GURL("http://www.baz.com/blah.html"),
+ FilePath("/usr/local/bin/real.so")));
+
+ scoped_refptr<PluginSelectionPolicy> policy2 = new PluginSelectionPolicy;
+ ASSERT_TRUE(CreatePolicy("no_rules", kNoRulesPolicy, &path));
+ ASSERT_TRUE(policy2->InitFromFile(path));
+ EXPECT_FALSE(policy2->IsAllowed(GURL("http://www.foo.com/blah.html"),
+ FilePath("/usr/local/bin/test.so")));
+ EXPECT_FALSE(policy2->IsAllowed(GURL("http://www.bar.com/blah.html"),
+ FilePath("/usr/local/bin/test.so")));
+ EXPECT_FALSE(policy2->IsAllowed(GURL("http://www.baz.com/blah.html"),
+ FilePath("/usr/local/bin/test.so")));
+ EXPECT_TRUE(policy2->IsAllowed(GURL("http://www.baz.com/blah.html"),
+ FilePath("/usr/local/bin/real.so")));
+
+ scoped_refptr<PluginSelectionPolicy> policy3 = new PluginSelectionPolicy;
+ ASSERT_TRUE(CreatePolicy("empty", kEmptyPolicy, &path));
+ ASSERT_TRUE(policy3->InitFromFile(path));
+ EXPECT_TRUE(policy3->IsAllowed(GURL("http://www.foo.com/blah.html"),
+ FilePath("/usr/local/bin/test.so")));
+ EXPECT_TRUE(policy3->IsAllowed(GURL("http://www.bar.com/blah.html"),
+ FilePath("/usr/local/bin/test.so")));
+ EXPECT_TRUE(policy3->IsAllowed(GURL("http://www.baz.com/blah.html"),
+ FilePath("/usr/local/bin/test.so")));
+ EXPECT_TRUE(policy3->IsAllowed(GURL("http://www.baz.com/blah.html"),
+ FilePath("/usr/local/bin/real.so")));
+}
+
+TEST_F(PluginSelectionPolicyTest, FindFirstAllowed) {
+ FilePath path;
+ ASSERT_TRUE(CreatePolicy("multi", kMultiPluginTestPolicy, &path));
+ scoped_refptr<PluginSelectionPolicy> policy = new PluginSelectionPolicy;
+ ASSERT_TRUE(policy->InitFromFile(path));
+ EXPECT_TRUE(policy->IsAllowed(GURL("http://www.foo.com/blah.html"),
+ FilePath("/usr/local/bin/allow_foo.so")));
+ EXPECT_FALSE(policy->IsAllowed(GURL("http://www.bar.com/blah.html"),
+ FilePath("/usr/local/bin/allow_foo.so")));
+ EXPECT_FALSE(policy->IsAllowed(GURL("http://www.baz.com/blah.html"),
+ FilePath("/usr/local/bin/allow_foo.so")));
+ EXPECT_FALSE(policy->IsAllowed(GURL("http://www.bim.com/blah.html"),
+ FilePath("/usr/local/bin/allow_foo.so")));
+ EXPECT_FALSE(policy->IsAllowed(GURL("http://www.foo.com/blah.html"),
+ FilePath("/usr/local/bin/allow_baz_bim1.so")));
+ EXPECT_FALSE(policy->IsAllowed(GURL("http://www.bar.com/blah.html"),
+ FilePath("/usr/local/bin/allow_baz_bim1.so")));
+ EXPECT_TRUE(policy->IsAllowed(GURL("http://www.baz.com/blah.html"),
+ FilePath("/usr/local/bin/allow_baz_bim1.so")));
+ EXPECT_TRUE(policy->IsAllowed(GURL("http://www.bim.com/blah.html"),
+ FilePath("/usr/local/bin/allow_baz_bim1.so")));
+ EXPECT_FALSE(policy->IsAllowed(GURL("http://www.google.com/blah.html"),
+ FilePath("/usr/local/bin/allow_baz_bim1.so")));
+ EXPECT_FALSE(policy->IsAllowed(GURL("http://www.foo.com/blah.html"),
+ FilePath("/usr/local/bin/allow_baz_bim2.so")));
+ EXPECT_FALSE(policy->IsAllowed(GURL("http://www.bar.com/blah.html"),
+ FilePath("/usr/local/bin/allow_baz_bim2.so")));
+ EXPECT_TRUE(policy->IsAllowed(GURL("http://www.baz.com/blah.html"),
+ FilePath("/usr/local/bin/allow_baz_bim2.so")));
+ EXPECT_TRUE(policy->IsAllowed(GURL("http://www.bim.com/blah.html"),
+ FilePath("/usr/local/bin/allow_baz_bim2.so")));
+ EXPECT_FALSE(policy->IsAllowed(GURL("http://www.google.com/blah.html"),
+ FilePath("/usr/local/bin/allow_baz_bim2.so")));
+ std::vector<WebPluginInfo> info_vector;
+ WebPluginInfo info;
+ // First we test that the one without any policy gets
+ // selected for all if it's first.
+ info.path = FilePath("/usr/local/bin/no_policy.so");
+ info_vector.push_back(info);
+ info.path = FilePath("/usr/local/bin/allow_foo.so");
+ info_vector.push_back(info);
+ info.path = FilePath("/usr/local/bin/allow_baz_bim1.so");
+ info_vector.push_back(info);
+ info.path = FilePath("/usr/local/bin/allow_baz_bim2.so");
+ info_vector.push_back(info);
+ EXPECT_EQ(0, policy->FindFirstAllowed(GURL("http://www.baz.com/blah.html"),
+ info_vector));
+ EXPECT_EQ(0, policy->FindFirstAllowed(GURL("http://www.foo.com/blah.html"),
+ info_vector));
+ EXPECT_EQ(0, policy->FindFirstAllowed(GURL("http://www.bling.com/blah.html"),
+ info_vector));
+ EXPECT_EQ(0, policy->FindFirstAllowed(GURL("http://www.google.com/blah.html"),
+ info_vector));
+
+ // Now move the plugin without any policy to the end.
+ info_vector.clear();
+ info.path = FilePath("/usr/local/bin/allow_foo.so");
+ info_vector.push_back(info);
+ info.path = FilePath("/usr/local/bin/allow_baz_bim1.so");
+ info_vector.push_back(info);
+ info.path = FilePath("/usr/local/bin/allow_baz_bim2.so");
+ info_vector.push_back(info);
+ info.path = FilePath("/usr/local/bin/no_policy.so");
+ info_vector.push_back(info);
+ EXPECT_EQ(1, policy->FindFirstAllowed(GURL("http://www.baz.com/blah.html"),
+ info_vector));
+ EXPECT_EQ(0, policy->FindFirstAllowed(GURL("http://www.foo.com/blah.html"),
+ info_vector));
+ EXPECT_EQ(3, policy->FindFirstAllowed(GURL("http://www.bling.com/blah.html"),
+ info_vector));
+ EXPECT_EQ(3, policy->FindFirstAllowed(GURL("http://www.google.com/blah.html"),
+ info_vector));
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc
index ebf4338..5f86020 100644
--- a/chrome/browser/plugin_service.cc
+++ b/chrome/browser/plugin_service.cc
@@ -40,6 +40,11 @@
#endif
#include "webkit/glue/plugins/plugin_constants_win.h"
#include "webkit/glue/plugins/plugin_list.h"
+#include "webkit/glue/plugins/webplugininfo.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/plugin_selection_policy.h"
+#endif
#if defined(OS_MACOSX)
static void NotifyPluginsOfActivation() {
@@ -123,6 +128,11 @@ PluginService::PluginService()
}
#endif
+#if defined(OS_CHROMEOS)
+ plugin_selection_policy_ = new chromeos::PluginSelectionPolicy;
+ plugin_selection_policy_->StartInit();
+#endif
+
chrome::RegisterInternalGPUPlugin();
#if defined(OS_WIN)
@@ -243,17 +253,42 @@ void PluginService::OpenChannelToPlugin(
ResourceMessageFilter* renderer_msg_filter,
const GURL& url,
const std::string& mime_type,
- const std::string& locale,
IPC::Message* reply_msg) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // The PluginList::GetFirstAllowedPluginInfo may need to load the
+ // plugins. Don't do it on the IO thread.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(
+ this, &PluginService::GetAllowedPluginForOpenChannelToPlugin,
+ renderer_msg_filter, url, mime_type, reply_msg));
+}
- bool allow_wildcard = true;
+void PluginService::GetAllowedPluginForOpenChannelToPlugin(
+ ResourceMessageFilter* renderer_msg_filter,
+ const GURL& url,
+ const std::string& mime_type,
+ IPC::Message* reply_msg) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
WebPluginInfo info;
+ bool found = GetFirstAllowedPluginInfo(url, mime_type, &info, NULL);
FilePath plugin_path;
- if (NPAPI::PluginList::Singleton()->GetPluginInfo(
- url, mime_type, allow_wildcard, &info, NULL) && info.enabled) {
- plugin_path = info.path;
- }
+ if (found && info.enabled)
+ plugin_path = FilePath(info.path);
+
+ // Now we jump back to the IO thread to finish opening the channel.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableMethod(
+ this, &PluginService::FinishOpenChannelToPlugin,
+ renderer_msg_filter, mime_type, plugin_path, reply_msg));
+}
+
+void PluginService::FinishOpenChannelToPlugin(
+ ResourceMessageFilter* renderer_msg_filter,
+ const std::string& mime_type,
+ const FilePath& plugin_path,
+ IPC::Message* reply_msg) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
PluginProcessHost* plugin_host = FindOrStartPluginProcess(plugin_path);
if (plugin_host) {
@@ -264,6 +299,37 @@ void PluginService::OpenChannelToPlugin(
}
}
+bool PluginService::GetFirstAllowedPluginInfo(
+ const GURL& url,
+ const std::string& mime_type,
+ WebPluginInfo* info,
+ std::string* actual_mime_type) {
+ // GetPluginInfoArray may need to load the plugins, so we need to be
+ // on the FILE thread.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ bool allow_wildcard = true;
+#if defined(OS_CHROMEOS)
+ std::vector<WebPluginInfo> info_array;
+ std::vector<std::string> actual_mime_types;
+ NPAPI::PluginList::Singleton()->GetPluginInfoArray(
+ url, mime_type, allow_wildcard, &info_array, &actual_mime_types);
+
+ // Now we filter by the plugin selection policy.
+ int allowed_index = plugin_selection_policy_->FindFirstAllowed(url,
+ info_array);
+ if (!info_array.empty() && allowed_index >= 0) {
+ *info = info_array[allowed_index];
+ if (actual_mime_type)
+ *actual_mime_type = actual_mime_types[allowed_index];
+ return true;
+ }
+ return false;
+#else
+ return NPAPI::PluginList::Singleton()->GetPluginInfo(
+ url, mime_type, allow_wildcard, info, actual_mime_type);
+#endif
+}
+
static void PurgePluginListCache(bool reload_pages) {
for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
!it.IsAtEnd(); it.Advance()) {
diff --git a/chrome/browser/plugin_service.h b/chrome/browser/plugin_service.h
index 3f25c25..9ff7988 100644
--- a/chrome/browser/plugin_service.h
+++ b/chrome/browser/plugin_service.h
@@ -25,6 +25,12 @@
#include "base/scoped_ptr.h"
#endif
+#if defined(OS_CHROMEOS)
+namespace chromeos {
+class PluginSelectionPolicy;
+}
+#endif
+
namespace IPC {
class Message;
}
@@ -32,9 +38,10 @@ class Message;
class MessageLoop;
class PluginProcessHost;
class Profile;
-class URLRequestContext;
class ResourceDispatcherHost;
class ResourceMessageFilter;
+class URLRequestContext;
+struct WebPluginInfo;
// This must be created on the main thread but it's only called on the IO/file
// thread.
@@ -78,9 +85,15 @@ class PluginService
void OpenChannelToPlugin(ResourceMessageFilter* renderer_msg_filter,
const GURL& url,
const std::string& mime_type,
- const std::string& locale,
IPC::Message* reply_msg);
+ // Gets the first allowed plugin in the list of plugins that matches
+ // the given url and mime type. Must be called on the FILE thread.
+ bool GetFirstAllowedPluginInfo(const GURL& url,
+ const std::string& mime_type,
+ WebPluginInfo* info,
+ std::string* actual_mime_type);
+
// Returns true if the given plugin is allowed to be used by a page with
// the given URL.
bool PrivatePluginAllowedForURL(const FilePath& plugin_path, const GURL& url);
@@ -111,6 +124,21 @@ class PluginService
void RegisterPepperPlugins();
+ // Helper so we can do the plugin lookup on the FILE thread.
+ void GetAllowedPluginForOpenChannelToPlugin(
+ ResourceMessageFilter* renderer_msg_filter,
+ const GURL& url,
+ const std::string& mime_type,
+ IPC::Message* reply_msg);
+
+ // Helper so we can finish opening the channel after looking up the
+ // plugin.
+ void FinishOpenChannelToPlugin(
+ ResourceMessageFilter* renderer_msg_filter,
+ const std::string& mime_type,
+ const FilePath& plugin_path,
+ IPC::Message* reply_msg);
+
// mapping between plugin path and PluginProcessHost
typedef base::hash_map<FilePath, PluginProcessHost*> PluginMap;
PluginMap plugin_hosts_;
@@ -134,6 +162,10 @@ class PluginService
NotificationRegistrar registrar_;
+#if defined(OS_CHROMEOS)
+ scoped_refptr<chromeos::PluginSelectionPolicy> plugin_selection_policy_;
+#endif
+
#if defined(OS_WIN)
// Registry keys for getting notifications when new plugins are installed.
RegKey hkcu_key_;
@@ -150,4 +182,6 @@ class PluginService
DISALLOW_COPY_AND_ASSIGN(PluginService);
};
+DISABLE_RUNNABLE_METHOD_REFCOUNT(PluginService);
+
#endif // CHROME_BROWSER_PLUGIN_SERVICE_H_
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index d62f6d1..cc4e662 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -10,13 +10,13 @@
#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
#endif
-#include "base/file_util.h"
#include "base/file_path.h"
+#include "base/file_util.h"
#include "base/metrics/histogram.h"
#include "base/process_util.h"
#include "base/shared_memory.h"
-#include "base/thread.h"
#include "base/sys_string_conversions.h"
+#include "base/thread.h"
#include "base/utf_string_conversions.h"
#include "base/worker_pool.h"
#include "chrome/browser/appcache/appcache_dispatcher_host.h"
@@ -32,8 +32,8 @@
#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/file_system/file_system_dispatcher_host.h"
#include "chrome/browser/file_system/file_system_host_context.h"
-#include "chrome/browser/geolocation/geolocation_permission_context.h"
#include "chrome/browser/geolocation/geolocation_dispatcher_host.h"
+#include "chrome/browser/geolocation/geolocation_permission_context.h"
#include "chrome/browser/gpu_process_host.h"
#include "chrome/browser/host_zoom_map.h"
#include "chrome/browser/in_process_webkit/dom_storage_dispatcher_host.h"
@@ -44,8 +44,11 @@
#include "chrome/browser/net/predictor_api.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/notifications/notifications_prefs_cache.h"
-#include "chrome/browser/plugin_updater.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/plugin_selection_policy.h"
+#endif
#include "chrome/browser/plugin_service.h"
+#include "chrome/browser/plugin_updater.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/printer_query.h"
@@ -406,8 +409,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFont, OnPreCacheFont)
#endif
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPluginInfoArray,
- OnGetPluginInfoArray)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPluginInfo,
+ OnGetPluginInfo)
IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl)
IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_ContextMenu,
OnReceiveContextMenuMsg(msg))
@@ -759,12 +762,12 @@ void ResourceMessageFilter::OnGetPluginsOnFileThread(
NewRunnableMethod(this, &ResourceMessageFilter::Send, reply_msg));
}
-void ResourceMessageFilter::OnGetPluginInfoArray(const GURL& url,
- const GURL& policy_url,
- const std::string& mime_type,
- IPC::Message* reply_msg) {
- // The PluginList::GetPluginInfo may need to load the plugins. Don't do it
- // on the IO thread.
+void ResourceMessageFilter::OnGetPluginInfo(const GURL& url,
+ const GURL& policy_url,
+ const std::string& mime_type,
+ IPC::Message* reply_msg) {
+ // The PluginService::GetFirstAllowedPluginInfo may need to load the
+ // plugins. Don't do it on the IO thread.
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
NewRunnableMethod(
@@ -777,50 +780,45 @@ void ResourceMessageFilter::OnGetPluginInfoOnFileThread(
const GURL& policy_url,
const std::string& mime_type,
IPC::Message* reply_msg) {
- std::vector<WebPluginInfo> info;
- std::vector<std::string> actual_mime_types;
- bool allow_wildcard = true;
- NPAPI::PluginList::Singleton()->GetPluginInfoArray(
- url, mime_type, allow_wildcard, &info, &actual_mime_types);
+ std::string actual_mime_type;
+ WebPluginInfo info;
+ bool found = plugin_service_->GetFirstAllowedPluginInfo(url,
+ mime_type,
+ &info,
+ &actual_mime_type);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
NewRunnableMethod(
this, &ResourceMessageFilter::OnGotPluginInfo,
- info, actual_mime_types, policy_url, reply_msg));
-}
-
-void ResourceMessageFilter::OnGotPluginInfo(
- std::vector<WebPluginInfo> info,
- const std::vector<std::string>& actual_mime_types,
- const GURL& policy_url,
- IPC::Message* reply_msg) {
- std::vector<ContentSetting> settings;
- for (std::vector<WebPluginInfo>::iterator iter = info.begin();
- iter != info.end(); ++iter) {
- ContentSetting setting = CONTENT_SETTING_DEFAULT;
- WebPluginInfo& item(*iter);
- item.enabled = item.enabled &&
- plugin_service_->PrivatePluginAllowedForURL(item.path, policy_url);
+ found, info, actual_mime_type, policy_url, reply_msg));
+}
+
+void ResourceMessageFilter::OnGotPluginInfo(bool found,
+ WebPluginInfo info,
+ const std::string& actual_mime_type,
+ const GURL& policy_url,
+ IPC::Message* reply_msg) {
+ ContentSetting setting = CONTENT_SETTING_DEFAULT;
+ if (found) {
+ info.enabled = info.enabled &&
+ plugin_service_->PrivatePluginAllowedForURL(info.path, policy_url);
HostContentSettingsMap* map = profile_->GetHostContentSettingsMap();
- scoped_ptr<PluginGroup> group(PluginGroup::CopyOrCreatePluginGroup(item));
+ scoped_ptr<PluginGroup> group(PluginGroup::CopyOrCreatePluginGroup(info));
std::string resource = group->identifier();
setting = map->GetContentSetting(policy_url,
CONTENT_SETTINGS_TYPE_PLUGINS,
resource);
- settings.push_back(setting);
}
- ViewHostMsg_GetPluginInfoArray::WriteReplyParams(
- reply_msg, info, settings, actual_mime_types);
+ ViewHostMsg_GetPluginInfo::WriteReplyParams(
+ reply_msg, found, info, setting, actual_mime_type);
Send(reply_msg);
}
void ResourceMessageFilter::OnOpenChannelToPlugin(const GURL& url,
const std::string& mime_type,
- const std::string& locale,
IPC::Message* reply_msg) {
- plugin_service_->OpenChannelToPlugin(
- this, url, mime_type, locale, reply_msg);
+ plugin_service_->OpenChannelToPlugin(this, url, mime_type, reply_msg);
}
void ResourceMessageFilter::OnLaunchNaCl(
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 52db66c..ca4b920 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -180,22 +180,21 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
#endif
void OnGetPlugins(bool refresh, IPC::Message* reply_msg);
void OnGetPluginsOnFileThread(bool refresh, IPC::Message* reply_msg);
- void OnGetPluginInfoArray(const GURL& url,
- const GURL& policy_url,
- const std::string& mime_type,
- IPC::Message* reply_msg);
+ void OnGetPluginInfo(const GURL& url,
+ const GURL& policy_url,
+ const std::string& mime_type,
+ IPC::Message* reply_msg);
void OnGetPluginInfoOnFileThread(const GURL& url,
const GURL& policy_url,
const std::string& mime_type,
IPC::Message* reply_msg);
- void OnGotPluginInfo(
- std::vector<WebPluginInfo> info,
- const std::vector<std::string>& actual_mime_types,
- const GURL& policy_url,
- IPC::Message* reply_msg);
+ void OnGotPluginInfo(bool found,
+ WebPluginInfo info,
+ const std::string& actual_mime_type,
+ const GURL& policy_url,
+ IPC::Message* reply_msg);
void OnOpenChannelToPlugin(const GURL& url,
const std::string& mime_type,
- const std::string& locale,
IPC::Message* reply_msg);
void OnLaunchNaCl(const std::wstring& url,
int channel_descriptor,