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 "extensions/browser/admin_policy.h"
6
7#include "base/strings/utf_string_conversions.h"
8#include "extensions/common/extension.h"
9#include "extensions/common/manifest.h"
10#include "grit/extensions_strings.h"
11#include "ui/base/l10n/l10n_util.h"
12
13namespace {
14
15bool ManagementPolicyImpl(const extensions::Extension* extension,
16                          base::string16* error,
17                          bool modifiable_value) {
18  // Note that COMPONENT and EXTERNAL_COMPONENT are treated differently
19  // below. EXTERNAL_COMPONENT extensions can be modified including
20  // enabled, disabled, uninstalled while COMPONENT extensions cannot.
21  // However, those options are only available for EXTERNAL_COMPONENT
22  // extensions when the proper command line flag is passed.
23  bool modifiable =
24      extension->location() != extensions::Manifest::COMPONENT &&
25      !extensions::Manifest::IsPolicyLocation(extension->location());
26  // Some callers equate "no restriction" to true, others to false.
27  if (modifiable)
28    return modifiable_value;
29
30  if (error) {
31    *error = l10n_util::GetStringFUTF16(
32        IDS_EXTENSION_CANT_MODIFY_POLICY_REQUIRED,
33        base::UTF8ToUTF16(extension->name()));
34  }
35  return !modifiable_value;
36}
37
38bool ReturnLoadError(const extensions::Extension* extension,
39                     base::string16* error) {
40  if (error) {
41    *error = l10n_util::GetStringFUTF16(
42          IDS_EXTENSION_CANT_INSTALL_POLICY_BLOCKED,
43          base::UTF8ToUTF16(extension->name()),
44          base::UTF8ToUTF16(extension->id()));
45  }
46  return false;
47}
48
49}  // namespace
50
51namespace extensions {
52namespace admin_policy {
53
54bool BlacklistedByDefault(const base::ListValue* blacklist) {
55  base::StringValue wildcard("*");
56  return blacklist && blacklist->Find(wildcard) != blacklist->end();
57}
58
59bool UserMayLoad(const base::ListValue* blacklist,
60                 const base::ListValue* whitelist,
61                 const base::DictionaryValue* forcelist,
62                 const base::ListValue* allowed_types,
63                 const Extension* extension,
64                 base::string16* error) {
65  // Component extensions are always allowed.
66  if (extension->location() == Manifest::COMPONENT)
67    return true;
68
69  // Forced installed extensions cannot be overwritten manually.
70  if (extension->location() != Manifest::EXTERNAL_POLICY &&
71      extension->location() != Manifest::EXTERNAL_POLICY_DOWNLOAD &&
72      forcelist && forcelist->HasKey(extension->id())) {
73    return ReturnLoadError(extension, error);
74  }
75
76  // Early exit for the common case of no policy restrictions.
77  if ((!blacklist || blacklist->empty()) && (!allowed_types))
78    return true;
79
80  // Check whether the extension type is allowed.
81  //
82  // If you get a compile error here saying that the type you added is not
83  // handled by the switch statement below, please consider whether enterprise
84  // policy should be able to disallow extensions of the new type. If so, add a
85  // branch to the second block and add a line to the definition of
86  // kExtensionAllowedTypesMap in configuration_policy_handler_list.cc.
87  switch (extension->GetType()) {
88    case Manifest::TYPE_UNKNOWN:
89      break;
90    case Manifest::TYPE_EXTENSION:
91    case Manifest::TYPE_THEME:
92    case Manifest::TYPE_USER_SCRIPT:
93    case Manifest::TYPE_HOSTED_APP:
94    case Manifest::TYPE_LEGACY_PACKAGED_APP:
95    case Manifest::TYPE_PLATFORM_APP:
96    case Manifest::TYPE_SHARED_MODULE: {
97      base::FundamentalValue type_value(extension->GetType());
98      if (allowed_types &&
99          allowed_types->Find(type_value) == allowed_types->end())
100        return ReturnLoadError(extension, error);
101      break;
102    }
103    case Manifest::NUM_LOAD_TYPES:
104      NOTREACHED();
105  }
106
107  // Check the whitelist/forcelist first.
108  base::StringValue id_value(extension->id());
109  if ((whitelist && whitelist->Find(id_value) != whitelist->end()) ||
110      (forcelist && forcelist->HasKey(extension->id())))
111    return true;
112
113  // Then check the admin blacklist.
114  if ((blacklist && blacklist->Find(id_value) != blacklist->end()) ||
115      BlacklistedByDefault(blacklist))
116    return ReturnLoadError(extension, error);
117
118  return true;
119}
120
121bool UserMayModifySettings(const Extension* extension, base::string16* error) {
122  return ManagementPolicyImpl(extension, error, true);
123}
124
125bool MustRemainEnabled(const Extension* extension, base::string16* error) {
126  return ManagementPolicyImpl(extension, error, false);
127}
128
129}  // namespace admin_policy
130}  // namespace extensions
131