• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/chromeos/plugin_selection_policy.h"
6 
7 #include <algorithm>
8 #include <iostream>
9 #include <map>
10 #include <sstream>
11 #include <string>
12 #include <vector>
13 
14 #include "base/auto_reset.h"
15 #include "base/file_path.h"
16 #include "base/file_util.h"
17 #include "base/logging.h"
18 #include "base/string_util.h"
19 #include "content/browser/browser_thread.h"
20 #include "googleurl/src/gurl.h"
21 
22 #if !defined(OS_CHROMEOS)
23 #error This file is meant to be compiled on ChromeOS only.
24 #endif
25 
26 using std::vector;
27 using std::string;
28 using std::pair;
29 using std::map;
30 
31 namespace chromeos {
32 
33 static const char kPluginSelectionPolicyFile[] =
34     "/usr/share/chromeos-assets/flash/plugin_policy";
35 
PluginSelectionPolicy()36 PluginSelectionPolicy::PluginSelectionPolicy()
37     : init_from_file_finished_(false) {
38 }
39 
StartInit()40 void PluginSelectionPolicy::StartInit() {
41   // Initialize the policy on the FILE thread, since it reads from a
42   // policy file.
43   BrowserThread::PostTask(
44       BrowserThread::FILE, FROM_HERE,
45       NewRunnableMethod(this, &chromeos::PluginSelectionPolicy::Init));
46 }
47 
Init()48 bool PluginSelectionPolicy::Init() {
49   return InitFromFile(FilePath(kPluginSelectionPolicyFile));
50 }
51 
InitFromFile(const FilePath & policy_file)52 bool PluginSelectionPolicy::InitFromFile(const FilePath& policy_file) {
53   // This must always be called from the FILE thread.
54   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
55 
56   string data;
57   // This should be a really small file, so we're OK with just
58   // slurping it.
59   if (!file_util::ReadFileToString(policy_file, &data)) {
60     LOG(ERROR) << "Unable to read plugin policy file \""
61                << policy_file.value() << "\".";
62     init_from_file_finished_ = true;
63     return false;
64   }
65 
66   std::istringstream input_stream(data);
67   string line;
68   map<string, Policy> policies;
69   Policy policy;
70   string last_plugin;
71 
72   while (std::getline(input_stream, line)) {
73     // Strip comments.
74     string::size_type pos = line.find("#");
75     if (pos != string::npos) {
76       line = line.substr(0, pos);
77     }
78     TrimWhitespaceASCII(line, TRIM_ALL, &line);
79     if (line.find("allow") == 0) {
80       // Has to be preceeded by a "plugin" statement.
81       if (last_plugin.empty()) {
82         LOG(ERROR) << "Plugin policy file error: 'allow' out of context.";
83         init_from_file_finished_ = true;
84         return false;
85       }
86       line = line.substr(5);
87       TrimWhitespaceASCII(line, TRIM_ALL, &line);
88       line = StringToLowerASCII(line);
89       policy.push_back(make_pair(true, line));
90     }
91     if (line.find("deny") == 0) {
92       // Has to be preceeded by a "plugin" statement.
93       if (last_plugin.empty()) {
94         LOG(ERROR) << "Plugin policy file error: 'deny' out of context.";
95         init_from_file_finished_ = true;
96         return false;
97       }
98       line = line.substr(4);
99       TrimWhitespaceASCII(line, TRIM_ALL, &line);
100       line = StringToLowerASCII(line);
101       policy.push_back(make_pair(false, line));
102     }
103     if (line.find("plugin") == 0) {
104       line = line.substr(6);
105       TrimWhitespaceASCII(line, TRIM_ALL, &line);
106       if (!policy.empty() && !last_plugin.empty())
107         policies.insert(make_pair(last_plugin, policy));
108       last_plugin = line;
109       policy.clear();
110     }
111   }
112 
113   if (!last_plugin.empty())
114     policies.insert(make_pair(last_plugin, policy));
115 
116   policies_.swap(policies);
117   init_from_file_finished_ = true;
118   return true;
119 }
120 
FindFirstAllowed(const GURL & url,const std::vector<webkit::npapi::WebPluginInfo> & info)121 int PluginSelectionPolicy::FindFirstAllowed(
122     const GURL& url,
123     const std::vector<webkit::npapi::WebPluginInfo>& info) {
124   for (std::vector<webkit::npapi::WebPluginInfo>::size_type i = 0;
125        i < info.size(); ++i) {
126     if (IsAllowed(url, info[i].path))
127       return i;
128   }
129   return -1;
130 }
131 
IsAllowed(const GURL & url,const FilePath & path)132 bool PluginSelectionPolicy::IsAllowed(const GURL& url,
133                                       const FilePath& path) {
134   // This must always be called from the FILE thread, to be sure
135   // initialization doesn't happen at the same time.
136   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
137 
138   // Make sure that we notice if this starts being called before
139   // initialization is complete.  Right now it is guaranteed only by
140   // the startup order and the fact that InitFromFile runs on the FILE
141   // thread too.
142   DCHECK(init_from_file_finished_)
143       << "Tried to check policy before policy is initialized.";
144 
145   string name = path.BaseName().value();
146 
147   PolicyMap::iterator policy_iter = policies_.find(name);
148   if (policy_iter != policies_.end()) {
149     Policy& policy(policy_iter->second);
150 
151     // We deny by default. (equivalent to "deny" at the top of the section)
152     bool allow = false;
153 
154     for (Policy::iterator iter = policy.begin(); iter != policy.end(); ++iter) {
155       bool policy_allow = iter->first;
156       string& policy_domain = iter->second;
157       if (policy_domain.empty() || url.DomainIs(policy_domain.c_str(),
158                                                 policy_domain.size())) {
159         allow = policy_allow;
160       }
161     }
162     return allow;
163   }
164 
165   // If it's not in the policy file, then we assume it's OK to allow
166   // it.
167   return true;
168 }
169 
170 }  // namespace chromeos
171