Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(437)

Side by Side Diff: chrome/browser/extensions/permissions_updater.cc

Issue 348313003: Create withheld permissions (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Latest master Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/permissions_updater.h" 5 #include "chrome/browser/extensions/permissions_updater.h"
6 6
7 #include "base/json/json_writer.h" 7 #include "base/json/json_writer.h"
8 #include "base/memory/ref_counted.h" 8 #include "base/memory/ref_counted.h"
9 #include "base/values.h" 9 #include "base/values.h"
10 #include "chrome/browser/chrome_notification_types.h" 10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h" 11 #include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h"
12 #include "chrome/browser/extensions/extension_util.h"
12 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/common/extensions/api/permissions.h" 14 #include "chrome/common/extensions/api/permissions.h"
14 #include "content/public/browser/notification_observer.h" 15 #include "content/public/browser/notification_observer.h"
15 #include "content/public/browser/notification_registrar.h" 16 #include "content/public/browser/notification_registrar.h"
16 #include "content/public/browser/notification_service.h" 17 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/render_process_host.h" 18 #include "content/public/browser/render_process_host.h"
18 #include "extensions/browser/event_router.h" 19 #include "extensions/browser/event_router.h"
19 #include "extensions/browser/extension_prefs.h" 20 #include "extensions/browser/extension_prefs.h"
20 #include "extensions/common/extension.h" 21 #include "extensions/common/extension.h"
21 #include "extensions/common/extension_messages.h" 22 #include "extensions/common/extension_messages.h"
23 #include "extensions/common/feature_switch.h"
22 #include "extensions/common/manifest_handlers/permissions_parser.h" 24 #include "extensions/common/manifest_handlers/permissions_parser.h"
23 #include "extensions/common/permissions/permission_set.h" 25 #include "extensions/common/permissions/permission_set.h"
24 #include "extensions/common/permissions/permissions_data.h" 26 #include "extensions/common/permissions/permissions_data.h"
27 #include "extensions/common/url_pattern.h"
28 #include "extensions/common/url_pattern_set.h"
25 29
26 using content::RenderProcessHost; 30 using content::RenderProcessHost;
27 using extensions::permissions_api_helpers::PackPermissionSet; 31 using extensions::permissions_api_helpers::PackPermissionSet;
28 32
29 namespace extensions { 33 namespace extensions {
30 34
31 namespace permissions = api::permissions; 35 namespace permissions = api::permissions;
32 36
37 namespace {
38
39 // Returns a PermissionSet that has the active permissions of the extension,
40 // bounded to its current manifest.
41 scoped_refptr<const PermissionSet> GetBoundedActivePermissions(
42 const Extension* extension, ExtensionPrefs* extension_prefs) {
43 // If the extension has used the optional permissions API, it will have a
44 // custom set of active permissions defined in the extension prefs. Here,
45 // we update the extension's active permissions based on the prefs.
46 scoped_refptr<const PermissionSet> active_permissions =
47 extension_prefs->GetActivePermissions(extension->id());
48 if (!active_permissions)
49 return extension->permissions_data()->active_permissions();
50
51 scoped_refptr<const PermissionSet> required_permissions =
52 PermissionsParser::GetRequiredPermissions(extension);
53
54 // We restrict the active permissions to be within the bounds defined in the
55 // extension's manifest.
56 // a) active permissions must be a subset of optional + default permissions
57 // b) active permissions must contains all default permissions
58 scoped_refptr<PermissionSet> total_permissions = PermissionSet::CreateUnion(
59 required_permissions,
60 PermissionsParser::GetOptionalPermissions(extension));
61
62 // Make sure the active permissions contain no more than optional + default.
63 scoped_refptr<PermissionSet> adjusted_active =
64 PermissionSet::CreateIntersection(total_permissions, active_permissions);
65
66 // Make sure the active permissions contain the default permissions.
67 adjusted_active =
68 PermissionSet::CreateUnion(required_permissions, adjusted_active);
69
70 return adjusted_active;
71 }
72
73 // Divvy up the |url patterns| between those we grant and those we do not. If
74 // |withhold_permissions| is false (because the requisite feature is not
75 // enabled), no permissions are withheld.
76 void SegregateUrlPermissions(const URLPatternSet& url_patterns,
77 bool withhold_permissions,
78 URLPatternSet* granted,
79 URLPatternSet* withheld) {
80 for (URLPatternSet::const_iterator iter = url_patterns.begin();
81 iter != url_patterns.end();
82 ++iter) {
83 if (withhold_permissions && iter->ImpliesAllHosts())
84 withheld->AddPattern(*iter);
85 else
86 granted->AddPattern(*iter);
87 }
88 }
89
90 } // namespace
91
33 PermissionsUpdater::PermissionsUpdater(content::BrowserContext* browser_context) 92 PermissionsUpdater::PermissionsUpdater(content::BrowserContext* browser_context)
34 : browser_context_(browser_context) { 93 : browser_context_(browser_context) {
35 } 94 }
36 95
37 PermissionsUpdater::~PermissionsUpdater() {} 96 PermissionsUpdater::~PermissionsUpdater() {}
38 97
39 void PermissionsUpdater::AddPermissions( 98 void PermissionsUpdater::AddPermissions(
40 const Extension* extension, const PermissionSet* permissions) { 99 const Extension* extension, const PermissionSet* permissions) {
41 scoped_refptr<const PermissionSet> existing( 100 scoped_refptr<const PermissionSet> existing(
42 extension->permissions_data()->active_permissions()); 101 extension->permissions_data()->active_permissions());
43 scoped_refptr<PermissionSet> total( 102 scoped_refptr<PermissionSet> total(
44 PermissionSet::CreateUnion(existing.get(), permissions)); 103 PermissionSet::CreateUnion(existing.get(), permissions));
45 scoped_refptr<PermissionSet> added( 104 scoped_refptr<PermissionSet> added(
46 PermissionSet::CreateDifference(total.get(), existing.get())); 105 PermissionSet::CreateDifference(total.get(), existing.get()));
47 106
48 SetActivePermissions(extension, total.get()); 107 SetPermissions(extension, total, NULL);
49 108
50 // Update the granted permissions so we don't auto-disable the extension. 109 // Update the granted permissions so we don't auto-disable the extension.
51 GrantActivePermissions(extension); 110 GrantActivePermissions(extension);
52 111
53 NotifyPermissionsUpdated(ADDED, extension, added.get()); 112 NotifyPermissionsUpdated(ADDED, extension, added.get());
54 } 113 }
55 114
56 void PermissionsUpdater::RemovePermissions( 115 void PermissionsUpdater::RemovePermissions(
57 const Extension* extension, const PermissionSet* permissions) { 116 const Extension* extension, const PermissionSet* permissions) {
58 scoped_refptr<const PermissionSet> existing( 117 scoped_refptr<const PermissionSet> existing(
59 extension->permissions_data()->active_permissions()); 118 extension->permissions_data()->active_permissions());
60 scoped_refptr<PermissionSet> total( 119 scoped_refptr<PermissionSet> total(
61 PermissionSet::CreateDifference(existing.get(), permissions)); 120 PermissionSet::CreateDifference(existing.get(), permissions));
62 scoped_refptr<PermissionSet> removed( 121 scoped_refptr<PermissionSet> removed(
63 PermissionSet::CreateDifference(existing.get(), total.get())); 122 PermissionSet::CreateDifference(existing.get(), total.get()));
64 123
65 // We update the active permissions, and not the granted permissions, because 124 // We update the active permissions, and not the granted permissions, because
66 // the extension, not the user, removed the permissions. This allows the 125 // the extension, not the user, removed the permissions. This allows the
67 // extension to add them again without prompting the user. 126 // extension to add them again without prompting the user.
68 SetActivePermissions(extension, total.get()); 127 SetPermissions(extension, total, NULL);
69 128
70 NotifyPermissionsUpdated(REMOVED, extension, removed.get()); 129 NotifyPermissionsUpdated(REMOVED, extension, removed.get());
71 } 130 }
72 131
73 void PermissionsUpdater::GrantActivePermissions(const Extension* extension) { 132 void PermissionsUpdater::GrantActivePermissions(const Extension* extension) {
74 CHECK(extension); 133 CHECK(extension);
75 134
76 // We only maintain the granted permissions prefs for INTERNAL and LOAD 135 // We only maintain the granted permissions prefs for INTERNAL and LOAD
77 // extensions. 136 // extensions.
78 if (!Manifest::IsUnpackedLocation(extension->location()) && 137 if (!Manifest::IsUnpackedLocation(extension->location()) &&
79 extension->location() != Manifest::INTERNAL) 138 extension->location() != Manifest::INTERNAL)
80 return; 139 return;
81 140
82 ExtensionPrefs::Get(browser_context_)->AddGrantedPermissions( 141 ExtensionPrefs::Get(browser_context_)->AddGrantedPermissions(
83 extension->id(), 142 extension->id(),
84 extension->permissions_data()->active_permissions().get()); 143 extension->permissions_data()->active_permissions().get());
85 } 144 }
86 145
87 void PermissionsUpdater::InitializeActivePermissions( 146 void PermissionsUpdater::InitializePermissions(const Extension* extension) {
88 const Extension* extension) { 147 scoped_refptr<const PermissionSet> bounded_active =
89 // If the extension has used the optional permissions API, it will have a 148 GetBoundedActivePermissions(extension,
90 // custom set of active permissions defined in the extension prefs. Here, 149 ExtensionPrefs::Get(browser_context_));
91 // we update the extension's active permissions based on the prefs.
92 scoped_refptr<PermissionSet> active_permissions =
93 ExtensionPrefs::Get(browser_context_)->GetActivePermissions(
94 extension->id());
95 if (!active_permissions)
96 return;
97 150
98 // We restrict the active permissions to be within the bounds defined in the 151 // We withhold permissions iff the switch to do so is enabled, the extension
99 // extension's manifest. 152 // shows up in chrome:extensions (so the user can grant withheld permissions),
100 // a) active permissions must be a subset of optional + default permissions 153 // the extension is not part of chrome or corporate policy, and also not on
101 // b) active permissions must contains all default permissions 154 // the scripting whitelist. Additionally, we don't withhold if the extension
102 scoped_refptr<PermissionSet> total_permissions = PermissionSet::CreateUnion( 155 // has the preference to allow scripting on all urls.
103 PermissionsParser::GetRequiredPermissions(extension), 156 bool should_withhold_permissions =
104 PermissionsParser::GetOptionalPermissions(extension)); 157 FeatureSwitch::scripts_require_action()->IsEnabled() &&
158 extension->ShouldDisplayInExtensionSettings() &&
159 !Manifest::IsPolicyLocation(extension->location()) &&
160 !Manifest::IsComponentLocation(extension->location()) &&
161 !PermissionsData::CanExecuteScriptEverywhere(extension) &&
162 !util::AllowedScriptingOnAllUrls(extension->id(), browser_context_);
105 163
106 // Make sure the active permissions contain no more than optional + default. 164 URLPatternSet granted_explicit_hosts;
107 scoped_refptr<PermissionSet> adjusted_active = 165 URLPatternSet withheld_explicit_hosts;
108 PermissionSet::CreateIntersection(total_permissions, active_permissions); 166 SegregateUrlPermissions(bounded_active->explicit_hosts(),
167 should_withhold_permissions,
168 &granted_explicit_hosts,
169 &withheld_explicit_hosts);
109 170
110 // Make sure the active permissions contain the default permissions. 171 URLPatternSet granted_scriptable_hosts;
111 adjusted_active = PermissionSet::CreateUnion( 172 URLPatternSet withheld_scriptable_hosts;
112 PermissionsParser::GetRequiredPermissions(extension), 173 SegregateUrlPermissions(bounded_active->scriptable_hosts(),
113 adjusted_active); 174 should_withhold_permissions,
175 &granted_scriptable_hosts,
176 &withheld_scriptable_hosts);
114 177
115 SetActivePermissions(extension, adjusted_active); 178 bounded_active = new PermissionSet(bounded_active->apis(),
179 bounded_active->manifest_permissions(),
180 granted_explicit_hosts,
181 granted_scriptable_hosts);
182
183 scoped_refptr<const PermissionSet> withheld =
184 new PermissionSet(APIPermissionSet(),
185 ManifestPermissionSet(),
186 withheld_explicit_hosts,
187 withheld_scriptable_hosts);
188 SetPermissions(extension, bounded_active, withheld);
116 } 189 }
117 190
118 void PermissionsUpdater::SetActivePermissions( 191 void PermissionsUpdater::WithholdImpliedAllHosts(const Extension* extension) {
119 const Extension* extension, const PermissionSet* permissions) { 192 scoped_refptr<const PermissionSet> active =
193 extension->permissions_data()->active_permissions();
194 scoped_refptr<const PermissionSet> withheld =
195 extension->permissions_data()->withheld_permissions();
196
197 URLPatternSet withheld_scriptable = withheld->scriptable_hosts();
198 URLPatternSet active_scriptable;
199 SegregateUrlPermissions(active->scriptable_hosts(),
200 true, // withhold permissions
201 &active_scriptable,
202 &withheld_scriptable);
203
204 URLPatternSet withheld_explicit = withheld->explicit_hosts();
205 URLPatternSet active_explicit;
206 SegregateUrlPermissions(active->explicit_hosts(),
207 true, // withhold permissions
208 &active_explicit,
209 &withheld_explicit);
210
211 SetPermissions(extension,
212 new PermissionSet(active->apis(),
213 active->manifest_permissions(),
214 active_explicit,
215 active_scriptable),
216 new PermissionSet(withheld->apis(),
217 withheld->manifest_permissions(),
218 withheld_explicit,
219 withheld_scriptable));
220 // TODO(rdevlin.cronin) We should notify the observers/renderer.
221 }
222
223 void PermissionsUpdater::GrantWithheldImpliedAllHosts(
224 const Extension* extension) {
225 scoped_refptr<const PermissionSet> active =
226 extension->permissions_data()->active_permissions();
227 scoped_refptr<const PermissionSet> withheld =
228 extension->permissions_data()->withheld_permissions();
229
230 // Move the all-hosts permission from withheld to active.
231 // We can cheat a bit here since we know that the only host permission we
232 // withhold is allhosts (or something similar enough to it), so we can just
233 // grant all withheld host permissions.
234 URLPatternSet explicit_hosts;
235 URLPatternSet::CreateUnion(
236 active->explicit_hosts(), withheld->explicit_hosts(), &explicit_hosts);
237 URLPatternSet scriptable_hosts;
238 URLPatternSet::CreateUnion(active->scriptable_hosts(),
239 withheld->scriptable_hosts(),
240 &scriptable_hosts);
241
242 // Since we only withhold host permissions (so far), we know that withheld
243 // permissions will be empty.
244 SetPermissions(extension,
245 new PermissionSet(active->apis(),
246 active->manifest_permissions(),
247 explicit_hosts,
248 scriptable_hosts),
249 new PermissionSet());
250 // TODO(rdevlin.cronin) We should notify the observers/renderer.
251 }
252
253 void PermissionsUpdater::SetPermissions(
254 const Extension* extension,
255 const scoped_refptr<const PermissionSet>& active,
256 scoped_refptr<const PermissionSet> withheld) {
257 withheld = withheld.get() ? withheld
258 : extension->permissions_data()->withheld_permissions();
259 extension->permissions_data()->SetPermissions(active, withheld);
120 ExtensionPrefs::Get(browser_context_)->SetActivePermissions( 260 ExtensionPrefs::Get(browser_context_)->SetActivePermissions(
121 extension->id(), permissions); 261 extension->id(), active.get());
122 extension->permissions_data()->SetActivePermissions(permissions);
123 } 262 }
124 263
125 void PermissionsUpdater::DispatchEvent( 264 void PermissionsUpdater::DispatchEvent(
126 const std::string& extension_id, 265 const std::string& extension_id,
127 const char* event_name, 266 const char* event_name,
128 const PermissionSet* changed_permissions) { 267 const PermissionSet* changed_permissions) {
129 EventRouter* event_router = EventRouter::Get(browser_context_); 268 EventRouter* event_router = EventRouter::Get(browser_context_);
130 if (!event_router) 269 if (!event_router)
131 return; 270 return;
132 271
(...skipping 28 matching lines...) Expand all
161 // Notify other APIs or interested parties. 300 // Notify other APIs or interested parties.
162 UpdatedExtensionPermissionsInfo info = UpdatedExtensionPermissionsInfo( 301 UpdatedExtensionPermissionsInfo info = UpdatedExtensionPermissionsInfo(
163 extension, changed, reason); 302 extension, changed, reason);
164 Profile* profile = Profile::FromBrowserContext(browser_context_); 303 Profile* profile = Profile::FromBrowserContext(browser_context_);
165 content::NotificationService::current()->Notify( 304 content::NotificationService::current()->Notify(
166 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, 305 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
167 content::Source<Profile>(profile), 306 content::Source<Profile>(profile),
168 content::Details<UpdatedExtensionPermissionsInfo>(&info)); 307 content::Details<UpdatedExtensionPermissionsInfo>(&info));
169 308
170 ExtensionMsg_UpdatePermissions_Params params; 309 ExtensionMsg_UpdatePermissions_Params params;
171 params.reason_id = static_cast<int>(reason);
172 params.extension_id = extension->id(); 310 params.extension_id = extension->id();
173 params.apis = changed->apis(); 311 params.active_permissions = ExtensionMsg_PermissionSetStruct(
174 params.manifest_permissions = changed->manifest_permissions(); 312 extension->permissions_data()->active_permissions());
175 params.explicit_hosts = changed->explicit_hosts(); 313 params.withheld_permissions = ExtensionMsg_PermissionSetStruct(
176 params.scriptable_hosts = changed->scriptable_hosts(); 314 extension->permissions_data()->withheld_permissions());
177 315
178 // Send the new permissions to the renderers. 316 // Send the new permissions to the renderers.
179 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); 317 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
180 !i.IsAtEnd(); i.Advance()) { 318 !i.IsAtEnd(); i.Advance()) {
181 RenderProcessHost* host = i.GetCurrentValue(); 319 RenderProcessHost* host = i.GetCurrentValue();
182 if (profile->IsSameProfile( 320 if (profile->IsSameProfile(
183 Profile::FromBrowserContext(host->GetBrowserContext()))) { 321 Profile::FromBrowserContext(host->GetBrowserContext()))) {
184 host->Send(new ExtensionMsg_UpdatePermissions(params)); 322 host->Send(new ExtensionMsg_UpdatePermissions(params));
185 } 323 }
186 } 324 }
187 325
188 // Trigger the onAdded and onRemoved events in the extension. 326 // Trigger the onAdded and onRemoved events in the extension.
189 DispatchEvent(extension->id(), event_name, changed); 327 DispatchEvent(extension->id(), event_name, changed);
190 } 328 }
191 329
192 } // namespace extensions 330 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/permissions_updater.h ('k') | chrome/browser/extensions/permissions_updater_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698