summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/plugin_selection_policy.cc
blob: 477965a0ad4404667824f3e66abc39d3bbaf1c0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// 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