Make the ChromeOS chromecast system tray integration use a private API.
[chromium-blink-merge.git] / chrome / browser / extensions / policy_handlers.cc
blob8e9be50b0213615c2b861fca58a0a7629d880eed
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.
5 #include "chrome/browser/extensions/policy_handlers.h"
7 #include "base/logging.h"
8 #include "base/prefs/pref_value_map.h"
9 #include "chrome/browser/extensions/extension_management_constants.h"
10 #include "chrome/browser/extensions/external_policy_loader.h"
11 #include "components/crx_file/id_util.h"
12 #include "components/policy/core/browser/policy_error_map.h"
13 #include "components/policy/core/common/policy_map.h"
14 #include "components/policy/core/common/schema.h"
15 #include "extensions/browser/pref_names.h"
16 #include "extensions/common/extension.h"
17 #include "grit/components_strings.h"
18 #include "policy/policy_constants.h"
19 #include "url/gurl.h"
21 namespace extensions {
23 // ExtensionListPolicyHandler implementation -----------------------------------
25 ExtensionListPolicyHandler::ExtensionListPolicyHandler(const char* policy_name,
26 const char* pref_path,
27 bool allow_wildcards)
28 : policy::TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST),
29 pref_path_(pref_path),
30 allow_wildcards_(allow_wildcards) {}
32 ExtensionListPolicyHandler::~ExtensionListPolicyHandler() {}
34 bool ExtensionListPolicyHandler::CheckPolicySettings(
35 const policy::PolicyMap& policies,
36 policy::PolicyErrorMap* errors) {
37 return CheckAndGetList(policies, errors, NULL);
40 void ExtensionListPolicyHandler::ApplyPolicySettings(
41 const policy::PolicyMap& policies,
42 PrefValueMap* prefs) {
43 scoped_ptr<base::ListValue> list;
44 policy::PolicyErrorMap errors;
45 if (CheckAndGetList(policies, &errors, &list) && list)
46 prefs->SetValue(pref_path(), list.Pass());
49 const char* ExtensionListPolicyHandler::pref_path() const {
50 return pref_path_;
53 bool ExtensionListPolicyHandler::CheckAndGetList(
54 const policy::PolicyMap& policies,
55 policy::PolicyErrorMap* errors,
56 scoped_ptr<base::ListValue>* extension_ids) {
57 if (extension_ids)
58 extension_ids->reset();
60 const base::Value* value = NULL;
61 if (!CheckAndGetValue(policies, errors, &value))
62 return false;
64 if (!value)
65 return true;
67 const base::ListValue* list_value = NULL;
68 if (!value->GetAsList(&list_value)) {
69 NOTREACHED();
70 return false;
73 // Filter the list, rejecting any invalid extension IDs.
74 scoped_ptr<base::ListValue> filtered_list(new base::ListValue());
75 for (base::ListValue::const_iterator entry(list_value->begin());
76 entry != list_value->end(); ++entry) {
77 std::string id;
78 if (!(*entry)->GetAsString(&id)) {
79 errors->AddError(policy_name(),
80 entry - list_value->begin(),
81 IDS_POLICY_TYPE_ERROR,
82 ValueTypeToString(base::Value::TYPE_STRING));
83 continue;
85 if (!(allow_wildcards_ && id == "*") && !crx_file::id_util::IdIsValid(id)) {
86 errors->AddError(policy_name(),
87 entry - list_value->begin(),
88 IDS_POLICY_VALUE_FORMAT_ERROR);
89 continue;
91 filtered_list->Append(new base::StringValue(id));
94 if (extension_ids)
95 *extension_ids = filtered_list.Pass();
97 return true;
100 // ExtensionInstallForcelistPolicyHandler implementation -----------------------
102 ExtensionInstallForcelistPolicyHandler::ExtensionInstallForcelistPolicyHandler()
103 : policy::TypeCheckingPolicyHandler(policy::key::kExtensionInstallForcelist,
104 base::Value::TYPE_LIST) {}
106 ExtensionInstallForcelistPolicyHandler::
107 ~ExtensionInstallForcelistPolicyHandler() {}
109 bool ExtensionInstallForcelistPolicyHandler::CheckPolicySettings(
110 const policy::PolicyMap& policies,
111 policy::PolicyErrorMap* errors) {
112 const base::Value* value;
113 return CheckAndGetValue(policies, errors, &value) &&
114 ParseList(value, NULL, errors);
117 void ExtensionInstallForcelistPolicyHandler::ApplyPolicySettings(
118 const policy::PolicyMap& policies,
119 PrefValueMap* prefs) {
120 const base::Value* value = NULL;
121 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
122 if (CheckAndGetValue(policies, NULL, &value) &&
123 value &&
124 ParseList(value, dict.get(), NULL)) {
125 prefs->SetValue(pref_names::kInstallForceList, dict.Pass());
129 bool ExtensionInstallForcelistPolicyHandler::ParseList(
130 const base::Value* policy_value,
131 base::DictionaryValue* extension_dict,
132 policy::PolicyErrorMap* errors) {
133 if (!policy_value)
134 return true;
136 const base::ListValue* policy_list_value = NULL;
137 if (!policy_value->GetAsList(&policy_list_value)) {
138 // This should have been caught in CheckPolicySettings.
139 NOTREACHED();
140 return false;
143 for (base::ListValue::const_iterator entry(policy_list_value->begin());
144 entry != policy_list_value->end(); ++entry) {
145 std::string entry_string;
146 if (!(*entry)->GetAsString(&entry_string)) {
147 if (errors) {
148 errors->AddError(policy_name(),
149 entry - policy_list_value->begin(),
150 IDS_POLICY_TYPE_ERROR,
151 ValueTypeToString(base::Value::TYPE_STRING));
153 continue;
156 // Each string item of the list has the following form:
157 // <extension_id>;<update_url>
158 // Note: The update URL might also contain semicolons.
159 size_t pos = entry_string.find(';');
160 if (pos == std::string::npos) {
161 if (errors) {
162 errors->AddError(policy_name(),
163 entry - policy_list_value->begin(),
164 IDS_POLICY_VALUE_FORMAT_ERROR);
166 continue;
169 std::string extension_id = entry_string.substr(0, pos);
170 std::string update_url = entry_string.substr(pos+1);
171 if (!crx_file::id_util::IdIsValid(extension_id) ||
172 !GURL(update_url).is_valid()) {
173 if (errors) {
174 errors->AddError(policy_name(),
175 entry - policy_list_value->begin(),
176 IDS_POLICY_VALUE_FORMAT_ERROR);
178 continue;
181 if (extension_dict) {
182 extensions::ExternalPolicyLoader::AddExtension(
183 extension_dict, extension_id, update_url);
187 return true;
190 // ExtensionURLPatternListPolicyHandler implementation -------------------------
192 ExtensionURLPatternListPolicyHandler::ExtensionURLPatternListPolicyHandler(
193 const char* policy_name,
194 const char* pref_path)
195 : policy::TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST),
196 pref_path_(pref_path) {}
198 ExtensionURLPatternListPolicyHandler::~ExtensionURLPatternListPolicyHandler() {}
200 bool ExtensionURLPatternListPolicyHandler::CheckPolicySettings(
201 const policy::PolicyMap& policies,
202 policy::PolicyErrorMap* errors) {
203 const base::Value* value = NULL;
204 if (!CheckAndGetValue(policies, errors, &value))
205 return false;
207 if (!value)
208 return true;
210 const base::ListValue* list_value = NULL;
211 if (!value->GetAsList(&list_value)) {
212 NOTREACHED();
213 return false;
216 // Check that the list contains valid URLPattern strings only.
217 for (base::ListValue::const_iterator entry(list_value->begin());
218 entry != list_value->end(); ++entry) {
219 std::string url_pattern_string;
220 if (!(*entry)->GetAsString(&url_pattern_string)) {
221 errors->AddError(policy_name(),
222 entry - list_value->begin(),
223 IDS_POLICY_TYPE_ERROR,
224 ValueTypeToString(base::Value::TYPE_STRING));
225 return false;
228 URLPattern pattern(URLPattern::SCHEME_ALL);
229 if (pattern.Parse(url_pattern_string) != URLPattern::PARSE_SUCCESS) {
230 errors->AddError(policy_name(),
231 entry - list_value->begin(),
232 IDS_POLICY_VALUE_FORMAT_ERROR);
233 return false;
237 return true;
240 void ExtensionURLPatternListPolicyHandler::ApplyPolicySettings(
241 const policy::PolicyMap& policies,
242 PrefValueMap* prefs) {
243 if (!pref_path_)
244 return;
245 const base::Value* value = policies.GetValue(policy_name());
246 if (value)
247 prefs->SetValue(pref_path_, value->CreateDeepCopy());
250 // ExtensionSettingsPolicyHandler implementation ------------------------------
252 ExtensionSettingsPolicyHandler::ExtensionSettingsPolicyHandler(
253 const policy::Schema& chrome_schema)
254 : policy::SchemaValidatingPolicyHandler(
255 policy::key::kExtensionSettings,
256 chrome_schema.GetKnownProperty(policy::key::kExtensionSettings),
257 policy::SCHEMA_ALLOW_UNKNOWN) {
260 ExtensionSettingsPolicyHandler::~ExtensionSettingsPolicyHandler() {
263 bool ExtensionSettingsPolicyHandler::CheckPolicySettings(
264 const policy::PolicyMap& policies,
265 policy::PolicyErrorMap* errors) {
266 scoped_ptr<base::Value> policy_value;
267 if (!CheckAndGetValue(policies, errors, &policy_value))
268 return false;
269 if (!policy_value)
270 return true;
272 // |policy_value| is expected to conform to the defined schema. But it's
273 // not strictly valid since there are additional restrictions.
274 const base::DictionaryValue* dict_value = NULL;
275 DCHECK(policy_value->IsType(base::Value::TYPE_DICTIONARY));
276 policy_value->GetAsDictionary(&dict_value);
278 for (base::DictionaryValue::Iterator it(*dict_value); !it.IsAtEnd();
279 it.Advance()) {
280 DCHECK(it.key() == schema_constants::kWildcard ||
281 crx_file::id_util::IdIsValid(it.key()));
282 DCHECK(it.value().IsType(base::Value::TYPE_DICTIONARY));
284 // Extracts sub dictionary.
285 const base::DictionaryValue* sub_dict = NULL;
286 it.value().GetAsDictionary(&sub_dict);
288 std::string installation_mode;
289 if (sub_dict->GetString(schema_constants::kInstallationMode,
290 &installation_mode)) {
291 if (installation_mode == schema_constants::kForceInstalled ||
292 installation_mode == schema_constants::kNormalInstalled) {
293 DCHECK(it.key() != schema_constants::kWildcard);
294 // Verifies that 'update_url' is specified for 'force_installed' and
295 // 'normal_installed' mode.
296 std::string update_url;
297 if (!sub_dict->GetString(schema_constants::kUpdateUrl, &update_url) ||
298 update_url.empty()) {
299 errors->AddError(policy_name(),
300 it.key() + "." + schema_constants::kUpdateUrl,
301 IDS_POLICY_NOT_SPECIFIED_ERROR);
302 return false;
304 // Verifies that update URL is valid.
305 if (!GURL(update_url).is_valid()) {
306 errors->AddError(
307 policy_name(), IDS_POLICY_INVALID_UPDATE_URL_ERROR, it.key());
308 return false;
314 return true;
317 void ExtensionSettingsPolicyHandler::ApplyPolicySettings(
318 const policy::PolicyMap& policies,
319 PrefValueMap* prefs) {
320 scoped_ptr<base::Value> policy_value;
321 if (!CheckAndGetValue(policies, NULL, &policy_value) || !policy_value)
322 return;
323 prefs->SetValue(pref_names::kExtensionManagement, policy_value.Pass());
326 } // namespace extensions