1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Use of this source code is governed by a BSD-style license that can be
3731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// found in the LICENSE file.
4731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/chromeos/plugin_selection_policy.h"
6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
7731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <algorithm>
8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <iostream>
9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <map>
10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <sstream>
11731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <string>
12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include <vector>
13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
14731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/auto_reset.h"
15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/file_path.h"
16731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/file_util.h"
17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/logging.h"
18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/string_util.h"
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "googleurl/src/gurl.h"
21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
22731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#if !defined(OS_CHROMEOS)
23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#error This file is meant to be compiled on ChromeOS only.
24731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#endif
25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing std::vector;
27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing std::string;
28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing std::pair;
29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing std::map;
30731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
31731df977c0511bca2206b5f333555b1205ff1f43Iain Merricknamespace chromeos {
32731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
33731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstatic const char kPluginSelectionPolicyFile[] =
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    "/usr/share/chromeos-assets/flash/plugin_policy";
35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
36513209b27ff55e2841eac0e4120199c23acce758Ben MurdochPluginSelectionPolicy::PluginSelectionPolicy()
37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    : init_from_file_finished_(false) {
38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid PluginSelectionPolicy::StartInit() {
41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Initialize the policy on the FILE thread, since it reads from a
42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // policy file.
43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::FILE, FROM_HERE,
45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      NewRunnableMethod(this, &chromeos::PluginSelectionPolicy::Init));
46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool PluginSelectionPolicy::Init() {
49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return InitFromFile(FilePath(kPluginSelectionPolicyFile));
50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool PluginSelectionPolicy::InitFromFile(const FilePath& policy_file) {
53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // This must always be called from the FILE thread.
54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  string data;
57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // This should be a really small file, so we're OK with just
58731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // slurping it.
59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!file_util::ReadFileToString(policy_file, &data)) {
60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LOG(ERROR) << "Unable to read plugin policy file \""
61731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick               << policy_file.value() << "\".";
62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    init_from_file_finished_ = true;
63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return false;
64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
65731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::istringstream input_stream(data);
67731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  string line;
68731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  map<string, Policy> policies;
69731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Policy policy;
70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  string last_plugin;
71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  while (std::getline(input_stream, line)) {
73731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Strip comments.
74731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    string::size_type pos = line.find("#");
75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (pos != string::npos) {
76731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      line = line.substr(0, pos);
77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    TrimWhitespaceASCII(line, TRIM_ALL, &line);
79731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (line.find("allow") == 0) {
80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // Has to be preceeded by a "plugin" statement.
81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (last_plugin.empty()) {
82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        LOG(ERROR) << "Plugin policy file error: 'allow' out of context.";
83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        init_from_file_finished_ = true;
84731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        return false;
85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      line = line.substr(5);
87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      TrimWhitespaceASCII(line, TRIM_ALL, &line);
88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      line = StringToLowerASCII(line);
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      policy.push_back(make_pair(true, line));
90731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (line.find("deny") == 0) {
92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      // Has to be preceeded by a "plugin" statement.
93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (last_plugin.empty()) {
94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        LOG(ERROR) << "Plugin policy file error: 'deny' out of context.";
95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        init_from_file_finished_ = true;
96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        return false;
97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      line = line.substr(4);
99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      TrimWhitespaceASCII(line, TRIM_ALL, &line);
100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      line = StringToLowerASCII(line);
101731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      policy.push_back(make_pair(false, line));
102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
103731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (line.find("plugin") == 0) {
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      line = line.substr(6);
105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      TrimWhitespaceASCII(line, TRIM_ALL, &line);
106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (!policy.empty() && !last_plugin.empty())
107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        policies.insert(make_pair(last_plugin, policy));
108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      last_plugin = line;
109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      policy.clear();
110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
113731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!last_plugin.empty())
114731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    policies.insert(make_pair(last_plugin, policy));
115731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
116731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  policies_.swap(policies);
117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  init_from_file_finished_ = true;
118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return true;
119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint PluginSelectionPolicy::FindFirstAllowed(
122731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const GURL& url,
12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const std::vector<webkit::npapi::WebPluginInfo>& info) {
12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (std::vector<webkit::npapi::WebPluginInfo>::size_type i = 0;
12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       i < info.size(); ++i) {
126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (IsAllowed(url, info[i].path))
127731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return i;
128731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
129731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return -1;
130731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
131731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
132731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool PluginSelectionPolicy::IsAllowed(const GURL& url,
133731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                      const FilePath& path) {
134731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // This must always be called from the FILE thread, to be sure
135731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // initialization doesn't happen at the same time.
136731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
137731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
138731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Make sure that we notice if this starts being called before
139731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // initialization is complete.  Right now it is guaranteed only by
140731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // the startup order and the fact that InitFromFile runs on the FILE
141731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // thread too.
142513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  DCHECK(init_from_file_finished_)
143513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      << "Tried to check policy before policy is initialized.";
144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
145731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  string name = path.BaseName().value();
146731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  PolicyMap::iterator policy_iter = policies_.find(name);
148731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (policy_iter != policies_.end()) {
149731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    Policy& policy(policy_iter->second);
150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
151731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // We deny by default. (equivalent to "deny" at the top of the section)
152731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    bool allow = false;
153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
154731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    for (Policy::iterator iter = policy.begin(); iter != policy.end(); ++iter) {
155731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      bool policy_allow = iter->first;
156731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      string& policy_domain = iter->second;
157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      if (policy_domain.empty() || url.DomainIs(policy_domain.c_str(),
158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                policy_domain.size())) {
159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        allow = policy_allow;
160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      }
161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return allow;
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // If it's not in the policy file, then we assume it's OK to allow
166731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // it.
167731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return true;
168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}  // namespace chromeos
171