policy_handlers.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
1// Copyright 2013 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/extensions/policy_handlers.h"
6
7#include "base/logging.h"
8#include "base/prefs/pref_value_map.h"
9#include "chrome/browser/extensions/external_policy_loader.h"
10#include "chrome/common/pref_names.h"
11#include "components/policy/core/browser/policy_error_map.h"
12#include "components/policy/core/common/policy_map.h"
13#include "extensions/common/extension.h"
14#include "grit/component_strings.h"
15#include "policy/policy_constants.h"
16
17namespace extensions {
18
19// ExtensionListPolicyHandler implementation -----------------------------------
20
21ExtensionListPolicyHandler::ExtensionListPolicyHandler(const char* policy_name,
22                                                       const char* pref_path,
23                                                       bool allow_wildcards)
24    : policy::TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST),
25      pref_path_(pref_path),
26      allow_wildcards_(allow_wildcards) {}
27
28ExtensionListPolicyHandler::~ExtensionListPolicyHandler() {}
29
30bool ExtensionListPolicyHandler::CheckPolicySettings(
31    const policy::PolicyMap& policies,
32    policy::PolicyErrorMap* errors) {
33  return CheckAndGetList(policies, errors, NULL);
34}
35
36void ExtensionListPolicyHandler::ApplyPolicySettings(
37    const policy::PolicyMap& policies,
38    PrefValueMap* prefs) {
39  scoped_ptr<base::ListValue> list;
40  policy::PolicyErrorMap errors;
41  if (CheckAndGetList(policies, &errors, &list) && list)
42    prefs->SetValue(pref_path(), list.release());
43}
44
45const char* ExtensionListPolicyHandler::pref_path() const {
46  return pref_path_;
47}
48
49bool ExtensionListPolicyHandler::CheckAndGetList(
50    const policy::PolicyMap& policies,
51    policy::PolicyErrorMap* errors,
52    scoped_ptr<base::ListValue>* extension_ids) {
53  if (extension_ids)
54    extension_ids->reset();
55
56  const base::Value* value = NULL;
57  if (!CheckAndGetValue(policies, errors, &value))
58    return false;
59
60  if (!value)
61    return true;
62
63  const base::ListValue* list_value = NULL;
64  if (!value->GetAsList(&list_value)) {
65    NOTREACHED();
66    return false;
67  }
68
69  // Filter the list, rejecting any invalid extension IDs.
70  scoped_ptr<base::ListValue> filtered_list(new base::ListValue());
71  for (base::ListValue::const_iterator entry(list_value->begin());
72       entry != list_value->end(); ++entry) {
73    std::string id;
74    if (!(*entry)->GetAsString(&id)) {
75      errors->AddError(policy_name(),
76                       entry - list_value->begin(),
77                       IDS_POLICY_TYPE_ERROR,
78                       ValueTypeToString(base::Value::TYPE_STRING));
79      continue;
80    }
81    if (!(allow_wildcards_ && id == "*") &&
82        !extensions::Extension::IdIsValid(id)) {
83      errors->AddError(policy_name(),
84                       entry - list_value->begin(),
85                       IDS_POLICY_VALUE_FORMAT_ERROR);
86      continue;
87    }
88    filtered_list->Append(base::Value::CreateStringValue(id));
89  }
90
91  if (extension_ids)
92    *extension_ids = filtered_list.Pass();
93
94  return true;
95}
96
97// ExtensionInstallForcelistPolicyHandler implementation -----------------------
98
99ExtensionInstallForcelistPolicyHandler::ExtensionInstallForcelistPolicyHandler()
100    : policy::TypeCheckingPolicyHandler(policy::key::kExtensionInstallForcelist,
101                                        base::Value::TYPE_LIST) {}
102
103ExtensionInstallForcelistPolicyHandler::
104    ~ExtensionInstallForcelistPolicyHandler() {}
105
106bool ExtensionInstallForcelistPolicyHandler::CheckPolicySettings(
107    const policy::PolicyMap& policies,
108    policy::PolicyErrorMap* errors) {
109  const base::Value* value;
110  return CheckAndGetValue(policies, errors, &value) &&
111      ParseList(value, NULL, errors);
112}
113
114void ExtensionInstallForcelistPolicyHandler::ApplyPolicySettings(
115    const policy::PolicyMap& policies,
116    PrefValueMap* prefs) {
117  const base::Value* value = NULL;
118  scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
119  if (CheckAndGetValue(policies, NULL, &value) &&
120      value &&
121      ParseList(value, dict.get(), NULL)) {
122    prefs->SetValue(prefs::kExtensionInstallForceList, dict.release());
123  }
124}
125
126bool ExtensionInstallForcelistPolicyHandler::ParseList(
127    const base::Value* policy_value,
128    base::DictionaryValue* extension_dict,
129    policy::PolicyErrorMap* errors) {
130  if (!policy_value)
131    return true;
132
133  const base::ListValue* policy_list_value = NULL;
134  if (!policy_value->GetAsList(&policy_list_value)) {
135    // This should have been caught in CheckPolicySettings.
136    NOTREACHED();
137    return false;
138  }
139
140  for (base::ListValue::const_iterator entry(policy_list_value->begin());
141       entry != policy_list_value->end(); ++entry) {
142    std::string entry_string;
143    if (!(*entry)->GetAsString(&entry_string)) {
144      if (errors) {
145        errors->AddError(policy_name(),
146                         entry - policy_list_value->begin(),
147                         IDS_POLICY_TYPE_ERROR,
148                         ValueTypeToString(base::Value::TYPE_STRING));
149      }
150      continue;
151    }
152
153    // Each string item of the list has the following form:
154    // <extension_id>;<update_url>
155    // Note: The update URL might also contain semicolons.
156    size_t pos = entry_string.find(';');
157    if (pos == std::string::npos) {
158      if (errors) {
159        errors->AddError(policy_name(),
160                         entry - policy_list_value->begin(),
161                         IDS_POLICY_VALUE_FORMAT_ERROR);
162      }
163      continue;
164    }
165
166    std::string extension_id = entry_string.substr(0, pos);
167    std::string update_url = entry_string.substr(pos+1);
168    if (!extensions::Extension::IdIsValid(extension_id) ||
169        !GURL(update_url).is_valid()) {
170      if (errors) {
171        errors->AddError(policy_name(),
172                         entry - policy_list_value->begin(),
173                         IDS_POLICY_VALUE_FORMAT_ERROR);
174      }
175      continue;
176    }
177
178    if (extension_dict) {
179      extensions::ExternalPolicyLoader::AddExtension(
180          extension_dict, extension_id, update_url);
181    }
182  }
183
184  return true;
185}
186
187// ExtensionURLPatternListPolicyHandler implementation -------------------------
188
189ExtensionURLPatternListPolicyHandler::ExtensionURLPatternListPolicyHandler(
190    const char* policy_name,
191    const char* pref_path)
192    : policy::TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST),
193      pref_path_(pref_path) {}
194
195ExtensionURLPatternListPolicyHandler::~ExtensionURLPatternListPolicyHandler() {}
196
197bool ExtensionURLPatternListPolicyHandler::CheckPolicySettings(
198    const policy::PolicyMap& policies,
199    policy::PolicyErrorMap* errors) {
200  const base::Value* value = NULL;
201  if (!CheckAndGetValue(policies, errors, &value))
202    return false;
203
204  if (!value)
205    return true;
206
207  const base::ListValue* list_value = NULL;
208  if (!value->GetAsList(&list_value)) {
209    NOTREACHED();
210    return false;
211  }
212
213  // Check that the list contains valid URLPattern strings only.
214  for (base::ListValue::const_iterator entry(list_value->begin());
215       entry != list_value->end(); ++entry) {
216    std::string url_pattern_string;
217    if (!(*entry)->GetAsString(&url_pattern_string)) {
218      errors->AddError(policy_name(),
219                       entry - list_value->begin(),
220                       IDS_POLICY_TYPE_ERROR,
221                       ValueTypeToString(base::Value::TYPE_STRING));
222      return false;
223    }
224
225    URLPattern pattern(URLPattern::SCHEME_ALL);
226    if (pattern.Parse(url_pattern_string) != URLPattern::PARSE_SUCCESS) {
227      errors->AddError(policy_name(),
228                       entry - list_value->begin(),
229                       IDS_POLICY_VALUE_FORMAT_ERROR);
230      return false;
231    }
232  }
233
234  return true;
235}
236
237void ExtensionURLPatternListPolicyHandler::ApplyPolicySettings(
238    const policy::PolicyMap& policies,
239    PrefValueMap* prefs) {
240  if (!pref_path_)
241    return;
242  const Value* value = policies.GetValue(policy_name());
243  if (value)
244    prefs->SetValue(pref_path_, value->DeepCopy());
245}
246
247}  // namespace extensions
248