1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_BROWSER_PERMISSIONS_MANAGER_H_
#define EXTENSIONS_BROWSER_PERMISSIONS_MANAGER_H_
#include <set>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "components/keyed_service/core/keyed_service.h"
#include "extensions/common/extension_id.h"
#include "url/origin.h"
class BrowserContextKeyedServiceFactory;
namespace content {
class BrowserContext;
}
namespace user_prefs {
class PrefRegistrySyncable;
}
namespace extensions {
class ExtensionPrefs;
class Extension;
class PermissionSet;
// Class for managing user-scoped extension permissions.
// Includes blocking all extensions from running on a site and automatically
// running all extensions on a site.
class PermissionsManager : public KeyedService {
public:
// A struct storing the user-specified settings that apply to all extensions,
// past, present, or future.
// We use url::Origin here (rather than URLPatternSet) because permission
// grants (and restrictions) are only meaningful at an origin level. It's not
// possible to, say, block an extension from running on google.com/maps while
// still allowing it to run on google.com/search.
// Note: Policy extensions and component extensions can bypass these
// settings.
struct UserPermissionsSettings {
UserPermissionsSettings();
~UserPermissionsSettings();
UserPermissionsSettings(const UserPermissionsSettings& other) = delete;
UserPermissionsSettings& operator=(UserPermissionsSettings& other) = delete;
// Sites the user has blocked all extensions from running on.
std::set<url::Origin> restricted_sites;
// Sites the user has allowed all extensions to run on.
std::set<url::Origin> permitted_sites;
};
struct ExtensionSiteAccess {
// The extension has access to the current domain.
bool has_site_access = false;
// The extension requested access to the current domain, but it was
// withheld.
bool withheld_site_access = false;
// The extension has access to all sites (or a pattern sufficiently broad
// as to be functionally similar, such as https://*.com/*). Note that since
// this includes "broad" patterns, this may be true even if
// `has_site_access` is false.
bool has_all_sites_access = false;
// The extension wants access to all sites (or a pattern sufficiently broad
// as to be functionally similar, such as https://*.com/*). Note that since
// this includes "broad" patterns, this may be true even if
// `withheld_site_access` is false.
bool withheld_all_sites_access = false;
};
// The user's site setting for a given site.
enum class UserSiteSetting {
// All extensions that request access are granted access in the site.
kGrantAllExtensions,
// All extensions that request access have withheld access in the site.
kBlockAllExtensions,
// Each extension that requests access can have its site access customized
// in the site.
kCustomizeByExtension,
};
enum class UpdateReason {
// Permissions were added to the extension.
kAdded,
// Permissions were removed from the extension.
kRemoved,
// Policy that affects permissions was updated.
kPolicy,
};
class Observer {
public:
virtual void OnUserPermissionsSettingsChanged(
const UserPermissionsSettings& settings) {}
virtual void OnExtensionPermissionsUpdated(const Extension& extension,
const PermissionSet& permissions,
UpdateReason reason) {}
};
explicit PermissionsManager(content::BrowserContext* browser_context);
~PermissionsManager() override;
PermissionsManager(const PermissionsManager&) = delete;
const PermissionsManager& operator=(const PermissionsManager&) = delete;
// Retrieves the PermissionsManager for a given `browser_context`.
static PermissionsManager* Get(content::BrowserContext* browser_context);
// Retrieves the factory instance for the PermissionsManager.
static BrowserContextKeyedServiceFactory* GetFactory();
// Registers the user preference that stores user permissions.
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// Updates the user site settings for the given `origin` to be
// `site_settings`.
void UpdateUserSiteSetting(const url::Origin& origin,
PermissionsManager::UserSiteSetting site_setting);
// Adds `origin` to the list of sites the user has blocked all
// extensions from running on. If `origin` is in permitted_sites, it will
// remove it from such list.
void AddUserRestrictedSite(const url::Origin& origin);
// Removes `origin` from the list of sites the user has blocked all
// extensions from running on and notifies observers.
void RemoveUserRestrictedSite(const url::Origin& origin);
// Adds `origin` to the list of sites the user has allowed all
// extensions to run on. If `origin` is in restricted_sites, it will remove it
// from such list.
void AddUserPermittedSite(const url::Origin& origin);
// Removes `origin` from the list of sites the user has allowed all
// extensions to run on and notifies observers.
void RemoveUserPermittedSite(const url::Origin& origin);
// Returns the user's permission settings.
const UserPermissionsSettings& GetUserPermissionsSettings() const;
// Returns the user's site setting for `origin`.
UserSiteSetting GetUserSiteSetting(const url::Origin& origin) const;
// Returns the current access level for the extension on the specified `url`.
ExtensionSiteAccess GetSiteAccess(const Extension& extension,
const GURL& url) const;
// Returns whether Chrome has withheld host permissions from the extension.
bool HasWithheldHostPermissions(const ExtensionId& extension_id) const;
// Returns the effective list of runtime-granted permissions for a given
// `extension` from its prefs. ExtensionPrefs doesn't store the valid schemes
// for URLPatterns, which results in the chrome:-scheme being included for
// <all_urls> when retrieving it directly from the prefs; this then causes
// CHECKs to fail when validating that permissions being revoked are present
// (see https://crbug.com/930062).
// Returns null if there are no stored runtime-granted permissions.
// TODO(https://crbug.com/931881): ExtensionPrefs should return
// properly-bounded permissions.
std::unique_ptr<PermissionSet> GetRuntimePermissionsFromPrefs(
const Extension& extension) const;
// Returns the set of permissions that the `extension` wants to have active at
// this time. This does *not* take into account user-granted or runtime-
// withheld permissions.
std::unique_ptr<PermissionSet> GetBoundedExtensionDesiredPermissions(
const Extension& extension) const;
// Returns the set of permissions that should be granted to the given
// `extension` according to the runtime-granted permissions and current
// preferences, omitting host permissions if the extension supports it and
// the user has withheld permissions.
std::unique_ptr<PermissionSet> GetEffectivePermissionsToGrant(
const Extension& extension,
const PermissionSet& desired_permissions) const;
// Notifies `observers_` that the permissions have been updated for an
// extension.
void NotifyExtensionPermissionsUpdated(const Extension& extension,
const PermissionSet& permissions,
UpdateReason reason);
// Adds or removes observers.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
private:
// Called whenever `user_permissions_` have changed.
void OnUserPermissionsSettingsChanged();
// Removes `origin` from the list of sites the user has allowed all
// extensions to run on and saves the change to `extension_prefs_`. Returns if
// the site has been removed.
bool RemovePermittedSiteAndUpdatePrefs(const url::Origin& origin);
// Removes `origin` from the list of sites the user has blocked all
// extensions from running on and saves the change to `extension_prefs_`.
// Returns if the site has been removed.
bool RemoveRestrictedSiteAndUpdatePrefs(const url::Origin& origin);
// Updates the given `extension` with the new `user_permitted_set` of sites
// all extensions are allowed to run on. Note that this only updates the
// permissions in the browser; updates must then be sent separately to the
// renderer and network service.
void UpdatePermissionsWithUserSettings(
const Extension& extension,
const PermissionSet& user_permitted_set);
// Notifies observers of a permissions change.
void NotifyObserversOfChange();
base::ObserverList<Observer>::Unchecked observers_;
// The associated browser context.
const raw_ptr<content::BrowserContext> browser_context_;
const raw_ptr<ExtensionPrefs> extension_prefs_;
UserPermissionsSettings user_permissions_;
base::WeakPtrFactory<PermissionsManager> weak_factory_{this};
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_PERMISSIONS_MANAGER_H_
|