Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / policy_handlers.cc
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/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"
20
21 namespace extensions {
22
23 // ExtensionListPolicyHandler implementation -----------------------------------
24
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) {}
31
32 ExtensionListPolicyHandler::~ExtensionListPolicyHandler() {}
33
34 bool ExtensionListPolicyHandler::CheckPolicySettings(
35     const policy::PolicyMap& policies,
36     policy::PolicyErrorMap* errors) {
37   return CheckAndGetList(policies, errors, NULL);
38 }
39
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.release());
47 }
48
49 const char* ExtensionListPolicyHandler::pref_path() const {
50   return pref_path_;
51 }
52
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();
59
60   const base::Value* value = NULL;
61   if (!CheckAndGetValue(policies, errors, &value))
62     return false;
63
64   if (!value)
65     return true;
66
67   const base::ListValue* list_value = NULL;
68   if (!value->GetAsList(&list_value)) {
69     NOTREACHED();
70     return false;
71   }
72
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;
84     }
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;
90     }
91     filtered_list->Append(new base::StringValue(id));
92   }
93
94   if (extension_ids)
95     *extension_ids = filtered_list.Pass();
96
97   return true;
98 }
99
100 // ExtensionInstallForcelistPolicyHandler implementation -----------------------
101
102 ExtensionInstallForcelistPolicyHandler::ExtensionInstallForcelistPolicyHandler()
103     : policy::TypeCheckingPolicyHandler(policy::key::kExtensionInstallForcelist,
104                                         base::Value::TYPE_LIST) {}
105
106 ExtensionInstallForcelistPolicyHandler::
107     ~ExtensionInstallForcelistPolicyHandler() {}
108
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);
115 }
116
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.release());
126   }
127 }
128
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;
135
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;
141   }
142
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));
152       }
153       continue;
154     }
155
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);
165       }
166       continue;
167     }
168
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);
177       }
178       continue;
179     }
180
181     if (extension_dict) {
182       extensions::ExternalPolicyLoader::AddExtension(
183           extension_dict, extension_id, update_url);
184     }
185   }
186
187   return true;
188 }
189
190 // ExtensionURLPatternListPolicyHandler implementation -------------------------
191
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) {}
197
198 ExtensionURLPatternListPolicyHandler::~ExtensionURLPatternListPolicyHandler() {}
199
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;
206
207   if (!value)
208     return true;
209
210   const base::ListValue* list_value = NULL;
211   if (!value->GetAsList(&list_value)) {
212     NOTREACHED();
213     return false;
214   }
215
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;
226     }
227
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;
234     }
235   }
236
237   return true;
238 }
239
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->DeepCopy());
248 }
249
250 // ExtensionSettingsPolicyHandler implementation  ------------------------------
251
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) {
258 }
259
260 ExtensionSettingsPolicyHandler::~ExtensionSettingsPolicyHandler() {
261 }
262
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;
271
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);
277
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));
283
284     // Extracts sub dictionary.
285     const base::DictionaryValue* sub_dict = NULL;
286     it.value().GetAsDictionary(&sub_dict);
287
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;
303         }
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;
309         }
310       }
311     }
312   }
313
314   return true;
315 }
316
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.release());
324 }
325
326 }  // namespace extensions