blob: 0633000fd4db48c83365b900824996a2a55364db [file] [log] [blame]
binjin5f405ef2014-09-03 21:23:161// Copyright 2014 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#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGEMENT_H_
6#define CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGEMENT_H_
7
dchengc963c7142016-04-08 03:55:228#include <memory>
binjin685ade82014-11-06 09:53:569#include <string>
avi3ec9c0d2016-12-27 22:38:0610#include <unordered_map>
binjine6b58b52014-10-31 01:55:5711#include <vector>
12
binjin5f405ef2014-09-03 21:23:1613#include "base/macros.h"
binjine6b58b52014-10-31 01:55:5714#include "base/memory/ref_counted.h"
binjin1569c9b2014-09-05 13:33:1815#include "base/memory/singleton.h"
16#include "base/observer_list.h"
binjin5f405ef2014-09-03 21:23:1617#include "base/values.h"
binjin1569c9b2014-09-05 13:33:1818#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
19#include "components/keyed_service/core/keyed_service.h"
brettwb1fc1b82016-02-02 00:19:0820#include "components/prefs/pref_change_registrar.h"
binjin1569c9b2014-09-05 13:33:1821#include "extensions/browser/management_policy.h"
rdevlin.cronin0670b562016-07-02 02:05:4322#include "extensions/common/extension_id.h"
binjin5f405ef2014-09-03 21:23:1623#include "extensions/common/manifest.h"
binjin5f405ef2014-09-03 21:23:1624
binjin311ecdf2014-09-12 22:56:5225class GURL;
binjin5f405ef2014-09-03 21:23:1626class PrefService;
Sergey Poromov741e70702018-10-11 20:11:5427class Profile;
binjin5f405ef2014-09-03 21:23:1628
binjin1569c9b2014-09-05 13:33:1829namespace content {
30class BrowserContext;
31} // namespace content
32
binjin5f405ef2014-09-03 21:23:1633namespace extensions {
34
binjin81d7c552014-10-02 11:47:1235namespace internal {
36
37struct IndividualSettings;
38struct GlobalSettings;
39
40} // namespace internal
41
binjine6b58b52014-10-31 01:55:5742class APIPermissionSet;
rdevlin.cronin0670b562016-07-02 02:05:4343class Extension;
binjine6b58b52014-10-31 01:55:5744class PermissionSet;
45
binjin5f405ef2014-09-03 21:23:1646// Tracks the management policies that affect extensions and provides interfaces
47// for observing and obtaining the global settings for all extensions, as well
48// as per-extension settings.
binjin1569c9b2014-09-05 13:33:1849class ExtensionManagement : public KeyedService {
binjin5f405ef2014-09-03 21:23:1650 public:
binjin1569c9b2014-09-05 13:33:1851 // Observer class for extension management settings changes.
52 class Observer {
53 public:
54 virtual ~Observer() {}
55
binjin81d7c552014-10-02 11:47:1256 // Called when the extension management settings change.
binjin1569c9b2014-09-05 13:33:1857 virtual void OnExtensionManagementSettingsChanged() = 0;
58 };
59
binjin5f405ef2014-09-03 21:23:1660 // Installation mode for extensions, default is INSTALLATION_ALLOWED.
61 // * INSTALLATION_ALLOWED: Extension can be installed.
62 // * INSTALLATION_BLOCKED: Extension cannot be installed.
63 // * INSTALLATION_FORCED: Extension will be installed automatically
64 // and cannot be disabled.
65 // * INSTALLATION_RECOMMENDED: Extension will be installed automatically but
66 // can be disabled.
Kyle Spiersbb4b9f5f52019-05-02 17:17:1567 // * INSTALLATION_REMOVED: Extension cannot be installed and will be
68 // automatically removed.
binjin5f405ef2014-09-03 21:23:1669 enum InstallationMode {
70 INSTALLATION_ALLOWED = 0,
71 INSTALLATION_BLOCKED,
72 INSTALLATION_FORCED,
73 INSTALLATION_RECOMMENDED,
Kyle Spiersbb4b9f5f52019-05-02 17:17:1574 INSTALLATION_REMOVED,
binjin5f405ef2014-09-03 21:23:1675 };
76
Sergey Poromov741e70702018-10-11 20:11:5477 explicit ExtensionManagement(Profile* profile);
dchengae36a4a2014-10-21 12:36:3678 ~ExtensionManagement() override;
binjin5f405ef2014-09-03 21:23:1679
binjine6b58b52014-10-31 01:55:5780 // KeyedService implementations:
81 void Shutdown() override;
82
binjin1569c9b2014-09-05 13:33:1883 void AddObserver(Observer* observer);
84 void RemoveObserver(Observer* observer);
85
binjine6b58b52014-10-31 01:55:5786 // Get the list of ManagementPolicy::Provider controlled by extension
87 // management policy settings.
lazyboy4aeef202016-09-07 21:28:5988 const std::vector<std::unique_ptr<ManagementPolicy::Provider>>& GetProviders()
89 const;
binjin1569c9b2014-09-05 13:33:1890
91 // Checks if extensions are blacklisted by default, by policy. When true,
92 // this means that even extensions without an ID should be blacklisted (e.g.
93 // from the command line, or when loaded as an unpacked extension).
binjin81d7c552014-10-02 11:47:1294 bool BlacklistedByDefault() const;
95
96 // Returns installation mode for an extension.
binjin685ade82014-11-06 09:53:5697 InstallationMode GetInstallationMode(const Extension* extension) const;
binjin5f405ef2014-09-03 21:23:1698
binjin30301062014-09-08 20:27:3499 // Returns the force install list, in format specified by
100 // ExternalPolicyLoader::AddExtension().
dchengc963c7142016-04-08 03:55:22101 std::unique_ptr<base::DictionaryValue> GetForceInstallList() const;
binjin30301062014-09-08 20:27:34102
binjincccacef2014-10-13 19:00:20103 // Like GetForceInstallList(), but returns recommended install list instead.
dchengc963c7142016-04-08 03:55:22104 std::unique_ptr<base::DictionaryValue> GetRecommendedInstallList() const;
binjincccacef2014-10-13 19:00:20105
Yann Dago726278c62019-03-18 14:59:55106 // Returns |true| if there is at least one extension with
107 // |INSTALLATION_ALLOWED| as installation mode. This excludes force installed
108 // extensions.
109 bool HasWhitelistedExtension() const;
110
binjinc641add2014-10-15 16:20:45111 // Returns if an extension with id |id| is explicitly allowed by enterprise
112 // policy or not.
113 bool IsInstallationExplicitlyAllowed(const ExtensionId& id) const;
binjin30301062014-09-08 20:27:34114
binjin311ecdf2014-09-12 22:56:52115 // Returns true if an extension download should be allowed to proceed.
binjin81d7c552014-10-02 11:47:12116 bool IsOffstoreInstallAllowed(const GURL& url,
117 const GURL& referrer_url) const;
binjin311ecdf2014-09-12 22:56:52118
Owen Mina9a13e12018-11-01 20:43:52119 // Returns true if an extension with manifest type |manifest_type| and
120 // id |extension_id| is allowed to be installed.
121 bool IsAllowedManifestType(Manifest::Type manifest_type,
122 const std::string& extension_id) const;
binjin5f405ef2014-09-03 21:23:16123
binjin685ade82014-11-06 09:53:56124 // Returns the list of blocked API permissions for |extension|.
125 APIPermissionSet GetBlockedAPIPermissions(const Extension* extension) const;
binjine6b58b52014-10-31 01:55:57126
nrpeter40e16382017-04-13 17:34:58127 // Returns the list of hosts blocked by policy for |extension|.
Devlin Cronin7e0f41ff2018-05-16 17:19:36128 const URLPatternSet& GetPolicyBlockedHosts(const Extension* extension) const;
nrpeter40e16382017-04-13 17:34:58129
Devlin Cronin7e0f41ff2018-05-16 17:19:36130 // Returns the hosts exempted by policy from the PolicyBlockedHosts for
nrpetere33d2a5b2017-04-25 00:12:31131 // |extension|.
Devlin Cronin7e0f41ff2018-05-16 17:19:36132 const URLPatternSet& GetPolicyAllowedHosts(const Extension* extension) const;
nrpeter40e16382017-04-13 17:34:58133
nrpetere33d2a5b2017-04-25 00:12:31134 // Returns the list of hosts blocked by policy for Default scope. This can be
Devlin Cronin7e0f41ff2018-05-16 17:19:36135 // overridden by an individual scope which is queried via
136 // GetPolicyBlockedHosts.
137 const URLPatternSet& GetDefaultPolicyBlockedHosts() const;
nrpetere33d2a5b2017-04-25 00:12:31138
Devlin Cronin7e0f41ff2018-05-16 17:19:36139 // Returns the hosts exempted by policy from PolicyBlockedHosts for
nrpetere33d2a5b2017-04-25 00:12:31140 // the default scope. This can be overridden by an individual scope which is
Devlin Cronin7e0f41ff2018-05-16 17:19:36141 // queries via GetPolicyAllowedHosts. This should only be used to
nrpetere33d2a5b2017-04-25 00:12:31142 // initialize a new renderer.
Devlin Cronin7e0f41ff2018-05-16 17:19:36143 const URLPatternSet& GetDefaultPolicyAllowedHosts() const;
nrpetere33d2a5b2017-04-25 00:12:31144
145 // Checks if an |extension| has its own runtime_blocked_hosts or
146 // runtime_allowed_hosts defined in the individual scope of the
147 // ExtensionSettings policy.
148 // Returns false if an individual scoped setting isn't defined.
Devlin Cronin7e0f41ff2018-05-16 17:19:36149 bool UsesDefaultPolicyHostRestrictions(const Extension* extension) const;
nrpetere33d2a5b2017-04-25 00:12:31150
nrpeter40e16382017-04-13 17:34:58151 // Checks if a URL is on the blocked host permissions list for a specific
152 // extension.
Devlin Cronin7e0f41ff2018-05-16 17:19:36153 bool IsPolicyBlockedHost(const Extension* extension, const GURL& url) const;
nrpeter40e16382017-04-13 17:34:58154
binjin685ade82014-11-06 09:53:56155 // Returns blocked permission set for |extension|.
dchengc963c7142016-04-08 03:55:22156 std::unique_ptr<const PermissionSet> GetBlockedPermissions(
binjin685ade82014-11-06 09:53:56157 const Extension* extension) const;
binjine6b58b52014-10-31 01:55:57158
nrpeter2362e7e2017-05-10 17:21:26159 // If the extension is blocked from install and a custom error message
160 // was defined returns it. Otherwise returns an empty string. The maximum
161 // string length is 1000 characters.
162 const std::string BlockedInstallMessage(const ExtensionId& id) const;
163
binjin685ade82014-11-06 09:53:56164 // Returns true if every permission in |perms| is allowed for |extension|.
165 bool IsPermissionSetAllowed(const Extension* extension,
rdevlin.cronine2d0fd02015-09-24 22:35:49166 const PermissionSet& perms) const;
binjine6b58b52014-10-31 01:55:57167
binjin8e3d0182014-12-04 16:44:28168 // Returns true if |extension| meets the minimum required version set for it.
169 // If there is no such requirement set for it, returns true as well.
170 // If false is returned and |required_version| is not null, the minimum
171 // required version is returned.
172 bool CheckMinimumVersion(const Extension* extension,
173 std::string* required_version) const;
174
binjin5f405ef2014-09-03 21:23:16175 private:
avi3ec9c0d2016-12-27 22:38:06176 using SettingsIdMap =
177 std::unordered_map<ExtensionId,
178 std::unique_ptr<internal::IndividualSettings>>;
179 using SettingsUpdateUrlMap =
180 std::unordered_map<std::string,
181 std::unique_ptr<internal::IndividualSettings>>;
binjin81d7c552014-10-02 11:47:12182 friend class ExtensionManagementServiceTest;
183
binjin1569c9b2014-09-05 13:33:18184 // Load all extension management preferences from |pref_service|, and
185 // refresh the settings.
186 void Refresh();
187
binjin5f405ef2014-09-03 21:23:16188 // Load preference with name |pref_name| and expected type |expected_type|.
189 // If |force_managed| is true, only loading from the managed preference store
190 // is allowed. Returns NULL if the preference is not present, not allowed to
191 // be loaded from or has the wrong type.
192 const base::Value* LoadPreference(const char* pref_name,
193 bool force_managed,
Owen Mina9a13e12018-11-01 20:43:52194 base::Value::Type expected_type) const;
binjin5f405ef2014-09-03 21:23:16195
binjin1569c9b2014-09-05 13:33:18196 void OnExtensionPrefChanged();
197 void NotifyExtensionManagementPrefChanged();
198
achuith4607f072017-03-08 11:49:13199 // Helper to return an extension install list, in format specified by
200 // ExternalPolicyLoader::AddExtension().
201 std::unique_ptr<base::DictionaryValue> GetInstallListByMode(
202 InstallationMode installation_mode) const;
203
204 // Helper to update |extension_dict| for forced installs.
205 void UpdateForcedExtensions(const base::DictionaryValue* extension_dict);
206
Owen Mina9a13e12018-11-01 20:43:52207 // Helper to update |settings_by_id_| for forced cloud reporting extension.
208 void UpdateForcedCloudReportingExtension();
209
210 // Returns true if cloud reporting policy is enabled.
211 bool IsCloudReportingPolicyEnabled() const;
212
binjin5f405ef2014-09-03 21:23:16213 // Helper function to access |settings_by_id_| with |id| as key.
214 // Adds a new IndividualSettings entry to |settings_by_id_| if none exists for
215 // |id| yet.
binjin81d7c552014-10-02 11:47:12216 internal::IndividualSettings* AccessById(const ExtensionId& id);
binjin5f405ef2014-09-03 21:23:16217
binjin685ade82014-11-06 09:53:56218 // Similar to AccessById(), but access |settings_by_update_url_| instead.
219 internal::IndividualSettings* AccessByUpdateUrl(
220 const std::string& update_url);
221
binjin5f405ef2014-09-03 21:23:16222 // A map containing all IndividualSettings applied to an individual extension
223 // identified by extension ID. The extension ID is used as index key of the
224 // map.
binjin5f405ef2014-09-03 21:23:16225 SettingsIdMap settings_by_id_;
226
binjin685ade82014-11-06 09:53:56227 // Similar to |settings_by_id_|, but contains the settings for a group of
228 // extensions with same update URL. The update url itself is used as index
229 // key for the map.
230 SettingsUpdateUrlMap settings_by_update_url_;
231
binjin5f405ef2014-09-03 21:23:16232 // The default IndividualSettings.
233 // For extension settings applied to an individual extension (identified by
234 // extension ID) or a group of extension (with specified extension update
235 // URL), all unspecified part will take value from |default_settings_|.
236 // For all other extensions, all settings from |default_settings_| will be
237 // enforced.
dchengc963c7142016-04-08 03:55:22238 std::unique_ptr<internal::IndividualSettings> default_settings_;
binjin5f405ef2014-09-03 21:23:16239
240 // Extension settings applicable to all extensions.
dchengc963c7142016-04-08 03:55:22241 std::unique_ptr<internal::GlobalSettings> global_settings_;
binjin5f405ef2014-09-03 21:23:16242
Sergey Poromov741e70702018-10-11 20:11:54243 Profile* const profile_ = nullptr;
achuith4607f072017-03-08 11:49:13244 PrefService* pref_service_ = nullptr;
245 bool is_signin_profile_ = false;
binjin5f405ef2014-09-03 21:23:16246
Trent Apteda250ec3ab2018-08-19 08:52:19247 base::ObserverList<Observer, true>::Unchecked observer_list_;
binjin1569c9b2014-09-05 13:33:18248 PrefChangeRegistrar pref_change_registrar_;
lazyboy4aeef202016-09-07 21:28:59249 std::vector<std::unique_ptr<ManagementPolicy::Provider>> providers_;
binjin1569c9b2014-09-05 13:33:18250
binjin5f405ef2014-09-03 21:23:16251 DISALLOW_COPY_AND_ASSIGN(ExtensionManagement);
252};
253
binjin1569c9b2014-09-05 13:33:18254class ExtensionManagementFactory : public BrowserContextKeyedServiceFactory {
255 public:
256 static ExtensionManagement* GetForBrowserContext(
257 content::BrowserContext* context);
258 static ExtensionManagementFactory* GetInstance();
259
260 private:
olli.raula36aa8be2015-09-10 11:14:22261 friend struct base::DefaultSingletonTraits<ExtensionManagementFactory>;
binjin1569c9b2014-09-05 13:33:18262
263 ExtensionManagementFactory();
dchengae36a4a2014-10-21 12:36:36264 ~ExtensionManagementFactory() override;
binjin1569c9b2014-09-05 13:33:18265
266 // BrowserContextKeyedServiceExtensionManagementFactory:
dchengae36a4a2014-10-21 12:36:36267 KeyedService* BuildServiceInstanceFor(
mostynba15bee12014-10-04 00:40:32268 content::BrowserContext* context) const override;
dchengae36a4a2014-10-21 12:36:36269 content::BrowserContext* GetBrowserContextToUse(
mostynba15bee12014-10-04 00:40:32270 content::BrowserContext* context) const override;
dchengae36a4a2014-10-21 12:36:36271 void RegisterProfilePrefs(
mostynba15bee12014-10-04 00:40:32272 user_prefs::PrefRegistrySyncable* registry) override;
binjin1569c9b2014-09-05 13:33:18273
274 DISALLOW_COPY_AND_ASSIGN(ExtensionManagementFactory);
275};
276
binjin5f405ef2014-09-03 21:23:16277} // namespace extensions
278
279#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGEMENT_H_