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

Side by Side Diff: extensions/common/permissions/permissions_data.cc

Issue 309533007: Refactor PermissionsData pt1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 6 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) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "extensions/common/permissions/permissions_data.h" 5 #include "extensions/common/permissions/permissions_data.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/string16.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "content/public/common/url_constants.h" 8 #include "content/public/common/url_constants.h"
15 #include "extensions/common/constants.h" 9 #include "extensions/common/constants.h"
16 #include "extensions/common/error_utils.h" 10 #include "extensions/common/error_utils.h"
not at google - send to devlin 2014/06/02 23:20:06 changes to this file is pretty crazy. effectively
Devlin 2014/06/03 15:28:21 Effectively... yes.
17 #include "extensions/common/extension.h"
18 #include "extensions/common/extensions_client.h" 11 #include "extensions/common/extensions_client.h"
19 #include "extensions/common/features/feature.h"
20 #include "extensions/common/features/feature_provider.h"
21 #include "extensions/common/manifest.h" 12 #include "extensions/common/manifest.h"
22 #include "extensions/common/manifest_constants.h" 13 #include "extensions/common/manifest_constants.h"
23 #include "extensions/common/manifest_handler.h" 14 #include "extensions/common/manifest_handlers/permissions_parser.h"
24 #include "extensions/common/permissions/api_permission_set.h"
25 #include "extensions/common/permissions/permission_message_provider.h" 15 #include "extensions/common/permissions/permission_message_provider.h"
26 #include "extensions/common/permissions/permission_set.h"
27 #include "extensions/common/permissions/permissions_info.h"
28 #include "extensions/common/switches.h" 16 #include "extensions/common/switches.h"
29 #include "extensions/common/url_pattern_set.h" 17 #include "extensions/common/url_pattern_set.h"
30 #include "extensions/common/user_script.h" 18 #include "extensions/common/user_script.h"
31 #include "url/gurl.h" 19 #include "url/gurl.h"
32 20
33 namespace extensions { 21 namespace extensions {
34 22
35 namespace keys = manifest_keys;
36 namespace errors = manifest_errors;
37
38 namespace { 23 namespace {
39 24
40 PermissionsData::PolicyDelegate* g_policy_delegate = NULL; 25 PermissionsData::PolicyDelegate* g_policy_delegate = NULL;
41 26
42 // Custom checks for the experimental permission that can't be expressed in
43 // _permission_features.json.
44 bool CanSpecifyExperimentalPermission(const Extension* extension) {
45 if (extension->location() == Manifest::COMPONENT)
46 return true;
47
48 if (CommandLine::ForCurrentProcess()->HasSwitch(
49 switches::kEnableExperimentalExtensionApis)) {
50 return true;
51 }
52
53 // We rely on the webstore to check access to experimental. This way we can
54 // whitelist extensions to have access to experimental in just the store, and
55 // not have to push a new version of the client.
56 if (extension->from_webstore())
57 return true;
58
59 return false;
60 }
61
62 // Checks whether the host |pattern| is allowed for the given |extension|,
63 // given API permissions |permissions|.
64 bool CanSpecifyHostPermission(const Extension* extension,
65 const URLPattern& pattern,
66 const APIPermissionSet& permissions) {
67 if (!pattern.match_all_urls() &&
68 pattern.MatchesScheme(content::kChromeUIScheme)) {
69 URLPatternSet chrome_scheme_hosts = ExtensionsClient::Get()->
70 GetPermittedChromeSchemeHosts(extension, permissions);
71 if (chrome_scheme_hosts.ContainsPattern(pattern))
72 return true;
73
74 // Component extensions can have access to all of chrome://*.
75 if (PermissionsData::CanExecuteScriptEverywhere(extension))
76 return true;
77
78 if (CommandLine::ForCurrentProcess()->HasSwitch(
79 switches::kExtensionsOnChromeURLs)) {
80 return true;
81 }
82
83 // TODO(aboxhall): return from_webstore() when webstore handles blocking
84 // extensions which request chrome:// urls
85 return false;
86 }
87
88 // Otherwise, the valid schemes were handled by URLPattern.
89 return true;
90 }
91
92 // Parses the host and api permissions from the specified permission |key|
93 // from |extension|'s manifest.
94 bool ParseHelper(Extension* extension,
95 const char* key,
96 APIPermissionSet* api_permissions,
97 URLPatternSet* host_permissions,
98 base::string16* error) {
99 if (!extension->manifest()->HasKey(key))
100 return true;
101
102 const base::ListValue* permissions = NULL;
103 if (!extension->manifest()->GetList(key, &permissions)) {
104 *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidPermissions,
105 std::string());
106 return false;
107 }
108
109 // NOTE: We need to get the APIPermission before we check if features
110 // associated with them are available because the feature system does not
111 // know about aliases.
112
113 std::vector<std::string> host_data;
114 if (!APIPermissionSet::ParseFromJSON(
115 permissions, APIPermissionSet::kDisallowInternalPermissions,
116 api_permissions, error, &host_data)) {
117 return false;
118 }
119
120 // Verify feature availability of permissions.
121 std::vector<APIPermission::ID> to_remove;
122 const FeatureProvider* permission_features =
123 FeatureProvider::GetPermissionFeatures();
124 for (APIPermissionSet::const_iterator iter = api_permissions->begin();
125 iter != api_permissions->end(); ++iter) {
126 Feature* feature = permission_features->GetFeature(iter->name());
127
128 // The feature should exist since we just got an APIPermission for it. The
129 // two systems should be updated together whenever a permission is added.
130 DCHECK(feature) << "Could not find feature for " << iter->name();
131 // http://crbug.com/176381
132 if (!feature) {
133 to_remove.push_back(iter->id());
134 continue;
135 }
136
137 Feature::Availability availability =
138 feature->IsAvailableToExtension(extension);
139
140 if (!availability.is_available()) {
141 // Don't fail, but warn the developer that the manifest contains
142 // unrecognized permissions. This may happen legitimately if the
143 // extensions requests platform- or channel-specific permissions.
144 extension->AddInstallWarning(InstallWarning(availability.message(),
145 feature->name()));
146 to_remove.push_back(iter->id());
147 continue;
148 }
149
150 if (iter->id() == APIPermission::kExperimental) {
151 if (!CanSpecifyExperimentalPermission(extension)) {
152 *error = base::ASCIIToUTF16(errors::kExperimentalFlagRequired);
153 return false;
154 }
155 }
156 }
157
158 api_permissions->AddImpliedPermissions();
159
160 // Remove permissions that are not available to this extension.
161 for (std::vector<APIPermission::ID>::const_iterator iter = to_remove.begin();
162 iter != to_remove.end(); ++iter) {
163 api_permissions->erase(*iter);
164 }
165
166 // Parse host pattern permissions.
167 const int kAllowedSchemes =
168 PermissionsData::CanExecuteScriptEverywhere(extension) ?
169 URLPattern::SCHEME_ALL : Extension::kValidHostPermissionSchemes;
170
171 for (std::vector<std::string>::const_iterator iter = host_data.begin();
172 iter != host_data.end(); ++iter) {
173 const std::string& permission_str = *iter;
174
175 // Check if it's a host pattern permission.
176 URLPattern pattern = URLPattern(kAllowedSchemes);
177 URLPattern::ParseResult parse_result = pattern.Parse(permission_str);
178 if (parse_result == URLPattern::PARSE_SUCCESS) {
179 // The path component is not used for host permissions, so we force it
180 // to match all paths.
181 pattern.SetPath("/*");
182 int valid_schemes = pattern.valid_schemes();
183 if (pattern.MatchesScheme(url::kFileScheme) &&
184 !PermissionsData::CanExecuteScriptEverywhere(extension)) {
185 extension->set_wants_file_access(true);
186 if (!(extension->creation_flags() & Extension::ALLOW_FILE_ACCESS))
187 valid_schemes &= ~URLPattern::SCHEME_FILE;
188 }
189
190 if (pattern.scheme() != content::kChromeUIScheme &&
191 !PermissionsData::CanExecuteScriptEverywhere(extension)) {
192 // Keep chrome:// in allowed schemes only if it's explicitly requested
193 // or CanExecuteScriptEverywhere is true. If the
194 // extensions_on_chrome_urls flag is not set, CanSpecifyHostPermission
195 // will fail, so don't check the flag here.
196 valid_schemes &= ~URLPattern::SCHEME_CHROMEUI;
197 }
198 pattern.SetValidSchemes(valid_schemes);
199
200 if (!CanSpecifyHostPermission(extension, pattern, *api_permissions)) {
201 // TODO(aboxhall): make a warning (see pattern.match_all_urls() block
202 // below).
203 extension->AddInstallWarning(InstallWarning(
204 ErrorUtils::FormatErrorMessage(
205 errors::kInvalidPermissionScheme, permission_str),
206 key,
207 permission_str));
208 continue;
209 }
210
211 host_permissions->AddPattern(pattern);
212 // We need to make sure all_urls matches chrome://favicon and (maybe)
213 // chrome://thumbnail, so add them back in to host_permissions separately.
214 if (pattern.match_all_urls()) {
215 host_permissions->AddPatterns(
216 ExtensionsClient::Get()->GetPermittedChromeSchemeHosts(
217 extension, *api_permissions));
218 }
219 continue;
220 }
221
222 // It's probably an unknown API permission. Do not throw an error so
223 // extensions can retain backwards compatability (http://crbug.com/42742).
224 extension->AddInstallWarning(InstallWarning(
225 ErrorUtils::FormatErrorMessage(
226 manifest_errors::kPermissionUnknownOrMalformed,
227 permission_str),
228 key,
229 permission_str));
230 }
231
232 return true;
233 }
234
235 // Returns true if this extension id is from a trusted provider. 27 // Returns true if this extension id is from a trusted provider.
236 bool IsTrustedId(const std::string& extension_id) { 28 bool ShouldSkipPermissionWarnings(const std::string& extension_id) {
237 // See http://b/4946060 for more details. 29 // See http://b/4946060 for more details.
238 return extension_id == std::string("nckgahadagoaajjgafhacjanaoiihapd"); 30 return extension_id == std::string("nckgahadagoaajjgafhacjanaoiihapd");
239 } 31 }
240 32
241 // Returns true if the |extension| has tab-specific permission to operate on
242 // the tab specified by |tab_id| with the given |url|.
243 // Note that if this returns false, it doesn't mean the extension can't run on
244 // the given tab, only that it does not have tab-specific permission to do so.
245 bool HasTabSpecificPermissionToExecuteScript(
246 const Extension* extension,
247 int tab_id,
248 const GURL& url) {
249 if (tab_id >= 0) {
250 scoped_refptr<const PermissionSet> tab_permissions =
251 PermissionsData::GetTabSpecificPermissions(extension, tab_id);
252 if (tab_permissions.get() &&
253 tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) {
254 return true;
255 }
256 }
257 return false;
258 }
259
260 } // namespace 33 } // namespace
261 34
262 struct PermissionsData::InitialPermissions { 35 PermissionsData::PermissionsData(const Extension* extension)
263 APIPermissionSet api_permissions; 36 : extension_id_(extension->id()),
264 ManifestPermissionSet manifest_permissions; 37 manifest_type_(extension->GetType()) {
265 URLPatternSet host_permissions; 38 scoped_refptr<const PermissionSet> required_permissions =
266 URLPatternSet scriptable_hosts; 39 PermissionsParser::GetRequiredPermissions(extension);
267 }; 40 active_permissions_ =
268 41 new PermissionSet(required_permissions->apis(),
269 PermissionsData::PermissionsData() { 42 required_permissions->manifest_permissions(),
43 required_permissions->explicit_hosts(),
44 required_permissions->scriptable_hosts());
270 } 45 }
271 46
272 PermissionsData::~PermissionsData() { 47 PermissionsData::~PermissionsData() {
273 } 48 }
274 49
275 // static 50 // static
276 void PermissionsData::SetPolicyDelegate(PolicyDelegate* delegate) { 51 void PermissionsData::SetPolicyDelegate(PolicyDelegate* delegate) {
277 g_policy_delegate = delegate; 52 g_policy_delegate = delegate;
278 } 53 }
279 54
280 // static 55 // static
281 const PermissionSet* PermissionsData::GetOptionalPermissions( 56 const PermissionsData* PermissionsData::ForExtension(
282 const Extension* extension) { 57 const Extension* extension) {
283 return extension->permissions_data()->optional_permission_set_.get(); 58 // TODO(rdevlin.cronin): Figure out what we're doing with this (i.e. whether
284 } 59 // or not we want to expose PermissionsData on the extension).
285 60 return extension->permissions_data();
286 // static
287 const PermissionSet* PermissionsData::GetRequiredPermissions(
288 const Extension* extension) {
289 return extension->permissions_data()->required_permission_set_.get();
290 }
291
292 // static
293 const APIPermissionSet* PermissionsData::GetInitialAPIPermissions(
294 const Extension* extension) {
295 return &extension->permissions_data()->
296 initial_required_permissions_->api_permissions;
297 }
298
299 // static
300 APIPermissionSet* PermissionsData::GetInitialAPIPermissions(
301 Extension* extension) {
302 return &extension->permissions_data()->
303 initial_required_permissions_->api_permissions;
304 }
305
306 // static
307 void PermissionsData::SetInitialScriptableHosts(
308 Extension* extension, const URLPatternSet& scriptable_hosts) {
309 extension->permissions_data()->
310 initial_required_permissions_->scriptable_hosts = scriptable_hosts;
311 }
312
313 // static
314 void PermissionsData::SetActivePermissions(const Extension* extension,
315 const PermissionSet* permissions) {
316 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
317 extension->permissions_data()->active_permissions_ = permissions;
318 }
319
320 // static
321 scoped_refptr<const PermissionSet> PermissionsData::GetActivePermissions(
not at google - send to devlin 2014/06/02 23:20:06 i actually liked this method, it means you don't n
Devlin 2014/06/03 15:28:21 Since active_permissions() is public, it seems odd
not at google - send to devlin 2014/06/03 15:45:16 Hm I didn't see that active_permissions() got adde
322 const Extension* extension) {
323 return extension->permissions_data()->active_permissions_;
324 }
325
326 // static
327 scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions(
328 const Extension* extension,
329 int tab_id) {
330 CHECK_GE(tab_id, 0);
331 TabPermissionsMap::const_iterator iter =
332 extension->permissions_data()->tab_specific_permissions_.find(tab_id);
333 return
334 (iter != extension->permissions_data()->tab_specific_permissions_.end())
335 ? iter->second
336 : NULL;
337 }
338
339 // static
340 void PermissionsData::UpdateTabSpecificPermissions(
341 const Extension* extension,
342 int tab_id,
343 scoped_refptr<const PermissionSet> permissions) {
344 CHECK_GE(tab_id, 0);
345 TabPermissionsMap* tab_permissions =
346 &extension->permissions_data()->tab_specific_permissions_;
347 if (tab_permissions->count(tab_id)) {
348 (*tab_permissions)[tab_id] = PermissionSet::CreateUnion(
349 (*tab_permissions)[tab_id].get(), permissions.get());
350 } else {
351 (*tab_permissions)[tab_id] = permissions;
352 }
353 }
354
355 // static
356 void PermissionsData::ClearTabSpecificPermissions(
357 const Extension* extension,
358 int tab_id) {
359 CHECK_GE(tab_id, 0);
360 extension->permissions_data()->tab_specific_permissions_.erase(tab_id);
361 }
362
363 // static
364 bool PermissionsData::HasAPIPermission(const Extension* extension,
365 APIPermission::ID permission) {
366 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
367 return GetActivePermissions(extension)->HasAPIPermission(permission);
368 }
369
370 // static
371 bool PermissionsData::HasAPIPermission(
372 const Extension* extension,
373 const std::string& permission_name) {
374 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
375 return GetActivePermissions(extension)->HasAPIPermission(permission_name);
376 }
377
378 // static
379 bool PermissionsData::HasAPIPermissionForTab(
380 const Extension* extension,
381 int tab_id,
382 APIPermission::ID permission) {
383 if (HasAPIPermission(extension, permission))
384 return true;
385
386 // Place autolock below the HasAPIPermission() check, since HasAPIPermission
387 // also acquires the lock.
388 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
389 scoped_refptr<const PermissionSet> tab_permissions =
390 GetTabSpecificPermissions(extension, tab_id);
391 return tab_permissions.get() && tab_permissions->HasAPIPermission(permission);
392 }
393
394 // static
395 bool PermissionsData::CheckAPIPermissionWithParam(
396 const Extension* extension,
397 APIPermission::ID permission,
398 const APIPermission::CheckParam* param) {
399 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
400 return GetActivePermissions(extension)->CheckAPIPermissionWithParam(
401 permission, param);
402 }
403
404 // static
405 const URLPatternSet& PermissionsData::GetEffectiveHostPermissions(
406 const Extension* extension) {
407 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
408 return GetActivePermissions(extension)->effective_hosts();
409 } 61 }
410 62
411 // static 63 // static
412 bool PermissionsData::CanSilentlyIncreasePermissions( 64 bool PermissionsData::CanSilentlyIncreasePermissions(
413 const Extension* extension) { 65 const Extension* extension) {
414 return extension->location() != Manifest::INTERNAL; 66 return extension->location() != Manifest::INTERNAL;
415 } 67 }
416 68
417 // static 69 // static
418 bool PermissionsData::ShouldSkipPermissionWarnings(const Extension* extension) { 70 bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) {
419 return IsTrustedId(extension->id()); 71 if (extension->location() == Manifest::COMPONENT)
72 return true;
73
74 const ExtensionsClient::ScriptingWhitelist& whitelist =
75 ExtensionsClient::Get()->GetScriptingWhitelist();
76
77 return std::find(whitelist.begin(), whitelist.end(), extension->id()) !=
78 whitelist.end();
420 } 79 }
421 80
422 // static 81 void PermissionsData::SetActivePermissions(
423 bool PermissionsData::HasHostPermission(const Extension* extension, 82 const PermissionSet* permissions) const {
424 const GURL& url) { 83 base::AutoLock auto_lock(runtime_lock_);
425 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_); 84 active_permissions_ = permissions;
426 return GetActivePermissions(extension)->HasExplicitAccessToOrigin(url);
427 } 85 }
428 86
429 // static 87 void PermissionsData::UpdateTabSpecificPermissions(
430 bool PermissionsData::HasEffectiveAccessToAllHosts(const Extension* extension) { 88 int tab_id,
431 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_); 89 scoped_refptr<const PermissionSet> permissions) const {
432 return GetActivePermissions(extension)->HasEffectiveAccessToAllHosts(); 90 base::AutoLock auto_lock(runtime_lock_);
91 CHECK_GE(tab_id, 0);
92 TabPermissionsMap::iterator iter = tab_specific_permissions_.find(tab_id);
93 if (iter == tab_specific_permissions_.end())
94 tab_specific_permissions_[tab_id] = permissions;
95 else
96 iter->second = PermissionSet::CreateUnion(iter->second, permissions);
433 } 97 }
434 98
435 // static 99 void PermissionsData::ClearTabSpecificPermissions(int tab_id) const {
436 PermissionMessages PermissionsData::GetPermissionMessages( 100 base::AutoLock auto_lock(runtime_lock_);
437 const Extension* extension) { 101 CHECK_GE(tab_id, 0);
438 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_); 102 tab_specific_permissions_.erase(tab_id);
439 if (ShouldSkipPermissionWarnings(extension)) { 103 }
104
105 bool PermissionsData::HasAPIPermission(APIPermission::ID permission) const {
106 base::AutoLock auto_lock(runtime_lock_);
107 return active_permissions_->HasAPIPermission(permission);
108 }
109
110 bool PermissionsData::HasAPIPermission(
111 const std::string& permission_name) const {
112 base::AutoLock auto_lock(runtime_lock_);
113 return active_permissions_->HasAPIPermission(permission_name);
114 }
115
116 bool PermissionsData::HasAPIPermissionForTab(
117 int tab_id,
118 APIPermission::ID permission) const {
119 if (HasAPIPermission(permission))
120 return true;
121
122 scoped_refptr<const PermissionSet> tab_permissions =
123 GetTabSpecificPermissions(tab_id);
124
125 // Place autolock below the HasAPIPermission() and
126 // GetTabSpecificPermissions(), since each already acquires the lock.
127 base::AutoLock auto_lock(runtime_lock_);
128 return tab_permissions.get() && tab_permissions->HasAPIPermission(permission);
129 }
130
131 bool PermissionsData::CheckAPIPermissionWithParam(
132 APIPermission::ID permission,
133 const APIPermission::CheckParam* param) const {
134 base::AutoLock auto_lock(runtime_lock_);
135 return active_permissions_->CheckAPIPermissionWithParam(permission, param);
136 }
137
138 const URLPatternSet& PermissionsData::GetEffectiveHostPermissions() const {
139 base::AutoLock auto_lock(runtime_lock_);
140 return active_permissions_->effective_hosts();
141 }
142
143 bool PermissionsData::HasHostPermission(const GURL& url) const {
144 base::AutoLock auto_lock(runtime_lock_);
145 return active_permissions_->HasExplicitAccessToOrigin(url);
146 }
147
148 bool PermissionsData::HasEffectiveAccessToAllHosts() const {
149 base::AutoLock auto_lock(runtime_lock_);
150 return active_permissions_->HasEffectiveAccessToAllHosts();
151 }
152
153 PermissionMessages PermissionsData::GetPermissionMessages() const {
154 base::AutoLock auto_lock(runtime_lock_);
155 if (ShouldSkipPermissionWarnings(extension_id_)) {
440 return PermissionMessages(); 156 return PermissionMessages();
441 } else { 157 } else {
442 return PermissionMessageProvider::Get()->GetPermissionMessages( 158 return PermissionMessageProvider::Get()->GetPermissionMessages(
443 GetActivePermissions(extension), extension->GetType()); 159 active_permissions_, manifest_type_);
444 } 160 }
445 } 161 }
446 162
447 // static 163 std::vector<base::string16> PermissionsData::GetPermissionMessageStrings()
448 std::vector<base::string16> PermissionsData::GetPermissionMessageStrings( 164 const {
449 const Extension* extension) { 165 base::AutoLock auto_lock(runtime_lock_);
450 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_); 166 if (ShouldSkipPermissionWarnings(extension_id_))
451 if (ShouldSkipPermissionWarnings(extension)) {
452 return std::vector<base::string16>(); 167 return std::vector<base::string16>();
453 } else { 168 return PermissionMessageProvider::Get()->GetWarningMessages(
454 return PermissionMessageProvider::Get()->GetWarningMessages( 169 active_permissions_, manifest_type_);
455 GetActivePermissions(extension), extension->GetType());
456 }
457 } 170 }
458 171
459 // static 172 std::vector<base::string16>
460 std::vector<base::string16> PermissionsData::GetPermissionMessageDetailsStrings( 173 PermissionsData::GetPermissionMessageDetailsStrings() const {
461 const Extension* extension) { 174 base::AutoLock auto_lock(runtime_lock_);
462 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_); 175 if (ShouldSkipPermissionWarnings(extension_id_))
463 if (ShouldSkipPermissionWarnings(extension)) {
464 return std::vector<base::string16>(); 176 return std::vector<base::string16>();
465 } else { 177 return PermissionMessageProvider::Get()->GetWarningMessagesDetails(
466 return PermissionMessageProvider::Get()->GetWarningMessagesDetails( 178 active_permissions_, manifest_type_);
467 GetActivePermissions(extension), extension->GetType());
468 }
469 } 179 }
470 180
471 // static
472 bool PermissionsData::CanExecuteScriptOnPage(const Extension* extension, 181 bool PermissionsData::CanExecuteScriptOnPage(const Extension* extension,
473 const GURL& document_url, 182 const GURL& document_url,
474 const GURL& top_frame_url, 183 const GURL& top_frame_url,
475 int tab_id, 184 int tab_id,
476 const UserScript* script, 185 const UserScript* script,
477 int process_id, 186 int process_id,
478 std::string* error) { 187 std::string* error) const {
479 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_); 188 if (g_policy_delegate &&
480 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 189 !g_policy_delegate->CanExecuteScriptOnPage(extension,
190 document_url,
191 top_frame_url,
192 tab_id,
193 script,
194 process_id,
195 error)) {
196 return false;
197 }
198
481 bool can_execute_everywhere = CanExecuteScriptEverywhere(extension); 199 bool can_execute_everywhere = CanExecuteScriptEverywhere(extension);
482
483 if (g_policy_delegate &&
484 !g_policy_delegate->CanExecuteScriptOnPage(
485 extension, document_url, top_frame_url, tab_id,
486 script, process_id, error))
487 return false;
488
489 if (!can_execute_everywhere && 200 if (!can_execute_everywhere &&
490 !ExtensionsClient::Get()->IsScriptableURL(document_url, error)) { 201 !ExtensionsClient::Get()->IsScriptableURL(document_url, error)) {
491 return false; 202 return false;
492 } 203 }
493 204
494 if (!command_line->HasSwitch(switches::kExtensionsOnChromeURLs)) { 205 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
206 switches::kExtensionsOnChromeURLs)) {
495 if (document_url.SchemeIs(content::kChromeUIScheme) && 207 if (document_url.SchemeIs(content::kChromeUIScheme) &&
496 !can_execute_everywhere) { 208 !can_execute_everywhere) {
497 if (error) 209 if (error)
498 *error = errors::kCannotAccessChromeUrl; 210 *error = manifest_errors::kCannotAccessChromeUrl;
499 return false; 211 return false;
500 } 212 }
501 } 213 }
502 214
503 if (top_frame_url.SchemeIs(extensions::kExtensionScheme) && 215 if (top_frame_url.SchemeIs(kExtensionScheme) &&
504 top_frame_url.GetOrigin() != 216 top_frame_url.GetOrigin() !=
505 Extension::GetBaseURLFromExtensionId(extension->id()).GetOrigin() && 217 Extension::GetBaseURLFromExtensionId(extension->id()).GetOrigin() &&
506 !can_execute_everywhere) { 218 !can_execute_everywhere) {
507 if (error) 219 if (error)
508 *error = errors::kCannotAccessExtensionUrl; 220 *error = manifest_errors::kCannotAccessExtensionUrl;
509 return false; 221 return false;
510 } 222 }
511 223
512 if (HasTabSpecificPermissionToExecuteScript(extension, tab_id, top_frame_url)) 224 if (HasTabSpecificPermissionToExecuteScript(tab_id, top_frame_url))
513 return true; 225 return true;
514 226
515 bool can_access = false; 227 bool can_access = false;
516 228
517 if (script) { 229 if (script) {
518 // If a script is specified, use its matches. 230 // If a script is specified, use its matches.
519 can_access = script->MatchesURL(document_url); 231 can_access = script->MatchesURL(document_url);
520 } else { 232 } else {
233 base::AutoLock auto_lock(runtime_lock_);
521 // Otherwise, see if this extension has permission to execute script 234 // Otherwise, see if this extension has permission to execute script
522 // programmatically on pages. 235 // programmatically on pages.
523 can_access = GetActivePermissions(extension)-> 236 can_access = active_permissions_->HasExplicitAccessToOrigin(document_url);
524 HasExplicitAccessToOrigin(document_url);
525 } 237 }
526 238
527 if (!can_access && error) { 239 if (!can_access && error) {
528 *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage, 240 *error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage,
529 document_url.spec()); 241 document_url.spec());
530 } 242 }
531 243
532 return can_access; 244 return can_access;
533 } 245 }
534 246
535 // static 247 bool PermissionsData::CanCaptureVisiblePage(int tab_id,
536 bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) { 248 std::string* error) const {
537 if (extension->location() == Manifest::COMPONENT)
538 return true;
539
540 const ExtensionsClient::ScriptingWhitelist& whitelist =
541 ExtensionsClient::Get()->GetScriptingWhitelist();
542
543 return std::find(whitelist.begin(), whitelist.end(), extension->id()) !=
544 whitelist.end();
545 }
546
547 // static
548 bool PermissionsData::CanCaptureVisiblePage(const Extension* extension,
549 int tab_id,
550 std::string* error) {
551 scoped_refptr<const PermissionSet> active_permissions =
552 GetActivePermissions(extension);
553 const URLPattern all_urls(URLPattern::SCHEME_ALL, 249 const URLPattern all_urls(URLPattern::SCHEME_ALL,
554 URLPattern::kAllUrlsPattern); 250 URLPattern::kAllUrlsPattern);
555 if (active_permissions->explicit_hosts().ContainsPattern(all_urls)) 251
556 return true; 252 {
253 base::AutoLock auto_lock(runtime_lock_);
254 if (active_permissions_->explicit_hosts().ContainsPattern(all_urls))
255 return true;
256 }
557 257
558 if (tab_id >= 0) { 258 if (tab_id >= 0) {
559 scoped_refptr<const PermissionSet> tab_permissions = 259 scoped_refptr<const PermissionSet> tab_permissions =
560 GetTabSpecificPermissions(extension, tab_id); 260 GetTabSpecificPermissions(tab_id);
561 if (tab_permissions && 261 if (tab_permissions &&
562 tab_permissions->HasAPIPermission(APIPermission::kTab)) { 262 tab_permissions->HasAPIPermission(APIPermission::kTab)) {
563 return true; 263 return true;
564 } 264 }
565 if (error) 265 if (error)
566 *error = errors::kActiveTabPermissionNotGranted; 266 *error = manifest_errors::kActiveTabPermissionNotGranted;
567 return false; 267 return false;
568 } 268 }
569 269
570 if (error) 270 if (error)
571 *error = errors::kAllURLOrActiveTabNeeded; 271 *error = manifest_errors::kAllURLOrActiveTabNeeded;
572 return false; 272 return false;
573 } 273 }
574 274
575 // static 275 // static
576 bool PermissionsData::RequiresActionForScriptExecution( 276 bool PermissionsData::RequiresActionForScriptExecution(
577 const Extension* extension) { 277 const Extension* extension) const {
578 return RequiresActionForScriptExecution(extension, -1, GURL()); 278 return RequiresActionForScriptExecution(extension, -1, GURL());
579 } 279 }
580 280
581 // static 281 // static
582 bool PermissionsData::RequiresActionForScriptExecution( 282 bool PermissionsData::RequiresActionForScriptExecution(
583 const Extension* extension, 283 const Extension* extension,
584 int tab_id, 284 int tab_id,
585 const GURL& url) { 285 const GURL& url) const {
586 // For now, the user should be notified when an extension with all hosts 286 {
587 // permission tries to execute a script on a page, with exceptions for policy- 287 base::AutoLock auto_lock(runtime_lock_);
588 // enabled and component extensions. If this doesn't meet those criteria, 288 // For now, the user should be notified when an extension with all hosts
589 // return immediately. 289 // permission tries to execute a script on a page, with exceptions for
590 if (!extension->ShouldDisplayInExtensionSettings() || 290 // policy-enabled and component extensions. If this doesn't meet those
591 Manifest::IsPolicyLocation(extension->location()) || 291 // criteria, return immediately.
592 Manifest::IsComponentLocation(extension->location()) || 292 if (!extension->ShouldDisplayInExtensionSettings() ||
593 !ShouldWarnAllHosts(extension)) { 293 Manifest::IsPolicyLocation(extension->location()) ||
594 return false; 294 Manifest::IsComponentLocation(extension->location()) ||
295 !active_permissions_->ShouldWarnAllHosts()) {
296 return false;
297 }
595 } 298 }
596 299
597 // If the extension has explicit permission to run on the given tab, then 300 // If the extension has explicit permission to run on the given tab, then
598 // we don't need to alert the user. 301 // we don't need to alert the user.
599 if (HasTabSpecificPermissionToExecuteScript(extension, tab_id, url)) 302 if (HasTabSpecificPermissionToExecuteScript(tab_id, url))
600 return false; 303 return false;
601 304
602 return true; 305 return true;
603 } 306 }
604 307
605 bool PermissionsData::ParsePermissions(Extension* extension, 308 scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions(
606 base::string16* error) { 309 int tab_id) const {
607 initial_required_permissions_.reset(new InitialPermissions); 310 base::AutoLock auto_lock(runtime_lock_);
608 if (!ParseHelper(extension, 311 CHECK_GE(tab_id, 0);
609 keys::kPermissions, 312 TabPermissionsMap::const_iterator iter =
610 &initial_required_permissions_->api_permissions, 313 tab_specific_permissions_.find(tab_id);
611 &initial_required_permissions_->host_permissions, 314 return (iter != tab_specific_permissions_.end()) ? iter->second : NULL;
612 error)) {
613 return false;
614 }
615
616 initial_optional_permissions_.reset(new InitialPermissions);
617 if (!ParseHelper(extension,
618 keys::kOptionalPermissions,
619 &initial_optional_permissions_->api_permissions,
620 &initial_optional_permissions_->host_permissions,
621 error)) {
622 return false;
623 }
624
625 return true;
626 } 315 }
627 316
628 void PermissionsData::InitializeManifestPermissions(Extension* extension) { 317 bool PermissionsData::HasTabSpecificPermissionToExecuteScript(
629 ManifestHandler::AddExtensionInitialRequiredPermissions( 318 int tab_id,
630 extension, &initial_required_permissions_->manifest_permissions); 319 const GURL& url) const {
631 } 320 if (tab_id >= 0) {
632 321 scoped_refptr<const PermissionSet> tab_permissions =
633 void PermissionsData::FinalizePermissions(Extension* extension) { 322 GetTabSpecificPermissions(tab_id);
634 active_permissions_ = new PermissionSet( 323 if (tab_permissions.get() &&
635 initial_required_permissions_->api_permissions, 324 tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) {
636 initial_required_permissions_->manifest_permissions, 325 return true;
637 initial_required_permissions_->host_permissions, 326 }
638 initial_required_permissions_->scriptable_hosts); 327 }
639 328 return false;
640 required_permission_set_ = new PermissionSet(
641 initial_required_permissions_->api_permissions,
642 initial_required_permissions_->manifest_permissions,
643 initial_required_permissions_->host_permissions,
644 initial_required_permissions_->scriptable_hosts);
645
646 optional_permission_set_ = new PermissionSet(
647 initial_optional_permissions_->api_permissions,
648 initial_optional_permissions_->manifest_permissions,
649 initial_optional_permissions_->host_permissions,
650 URLPatternSet());
651
652 initial_required_permissions_.reset();
653 initial_optional_permissions_.reset();
654 }
655
656 bool PermissionsData::ShouldWarnAllHosts(const Extension* extension) {
657 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
658 return PermissionsData::GetActivePermissions(extension)->ShouldWarnAllHosts();
659 } 329 }
660 330
661 } // namespace extensions 331 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698