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"
21 namespace extensions
{
23 // ExtensionListPolicyHandler implementation -----------------------------------
25 ExtensionListPolicyHandler::ExtensionListPolicyHandler(const char* policy_name
,
26 const char* pref_path
,
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 {
53 bool ExtensionListPolicyHandler::CheckAndGetList(
54 const policy::PolicyMap
& policies
,
55 policy::PolicyErrorMap
* errors
,
56 scoped_ptr
<base::ListValue
>* extension_ids
) {
58 extension_ids
->reset();
60 const base::Value
* value
= NULL
;
61 if (!CheckAndGetValue(policies
, errors
, &value
))
67 const base::ListValue
* list_value
= NULL
;
68 if (!value
->GetAsList(&list_value
)) {
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
) {
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
));
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
);
91 filtered_list
->Append(new base::StringValue(id
));
95 *extension_ids
= filtered_list
.Pass();
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
) &&
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
) {
136 const base::ListValue
* policy_list_value
= NULL
;
137 if (!policy_value
->GetAsList(&policy_list_value
)) {
138 // This should have been caught in CheckPolicySettings.
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
)) {
148 errors
->AddError(policy_name(),
149 entry
- policy_list_value
->begin(),
150 IDS_POLICY_TYPE_ERROR
,
151 ValueTypeToString(base::Value::TYPE_STRING
));
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
) {
162 errors
->AddError(policy_name(),
163 entry
- policy_list_value
->begin(),
164 IDS_POLICY_VALUE_FORMAT_ERROR
);
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()) {
174 errors
->AddError(policy_name(),
175 entry
- policy_list_value
->begin(),
176 IDS_POLICY_VALUE_FORMAT_ERROR
);
181 if (extension_dict
) {
182 extensions::ExternalPolicyLoader::AddExtension(
183 extension_dict
, extension_id
, update_url
);
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
))
210 const base::ListValue
* list_value
= NULL
;
211 if (!value
->GetAsList(&list_value
)) {
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
));
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
);
240 void ExtensionURLPatternListPolicyHandler::ApplyPolicySettings(
241 const policy::PolicyMap
& policies
,
242 PrefValueMap
* prefs
) {
245 const base::Value
* value
= policies
.GetValue(policy_name());
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
))
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();
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
);
304 // Verifies that update URL is valid.
305 if (!GURL(update_url
).is_valid()) {
307 policy_name(), IDS_POLICY_INVALID_UPDATE_URL_ERROR
, it
.key());
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
)
323 prefs
->SetValue(pref_names::kExtensionManagement
, policy_value
.Pass());
326 } // namespace extensions