blob: 477965a0ad4404667824f3e66abc39d3bbaf1c0f [file] [log] [blame]
// 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()
: init_from_file_finished_(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));
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() << "\".";
init_from_file_finished_ = true;
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.";
init_from_file_finished_ = true;
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.";
init_from_file_finished_ = true;
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);
init_from_file_finished_ = true;
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(init_from_file_finished_)
<< "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