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

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"
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()), manifest_type_(extension->GetType()) {
264 ManifestPermissionSet manifest_permissions; 37 base::AutoLock aut_lock(runtime_lock_);
not at google - send to devlin 2014/06/03 15:51:43 auto_lock
Devlin 2014/06/03 15:56:16 Done.
265 URLPatternSet host_permissions; 38 scoped_refptr<const PermissionSet> required_permissions =
266 URLPatternSet scriptable_hosts; 39 PermissionsParser::GetRequiredPermissions(extension);
267 }; 40 active_permissions_unsafe_ =
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(
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_unsafe_ = 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 return active_permissions()->HasAPIPermission(permission);
107 }
108
109 bool PermissionsData::HasAPIPermission(
110 const std::string& permission_name) const {
111 return active_permissions()->HasAPIPermission(permission_name);
112 }
113
114 bool PermissionsData::HasAPIPermissionForTab(
115 int tab_id,
116 APIPermission::ID permission) const {
117 if (HasAPIPermission(permission))
118 return true;
119
120 scoped_refptr<const PermissionSet> tab_permissions =
121 GetTabSpecificPermissions(tab_id);
122
123 // Place autolock below the HasAPIPermission() and
124 // GetTabSpecificPermissions(), since each already acquires the lock.
125 base::AutoLock auto_lock(runtime_lock_);
126 return tab_permissions.get() && tab_permissions->HasAPIPermission(permission);
127 }
128
129 bool PermissionsData::CheckAPIPermissionWithParam(
130 APIPermission::ID permission,
131 const APIPermission::CheckParam* param) const {
132 return active_permissions()->CheckAPIPermissionWithParam(permission, param);
133 }
134
135 const URLPatternSet& PermissionsData::GetEffectiveHostPermissions() const {
136 return active_permissions()->effective_hosts();
137 }
138
139 bool PermissionsData::HasHostPermission(const GURL& url) const {
140 return active_permissions()->HasExplicitAccessToOrigin(url);
141 }
142
143 bool PermissionsData::HasEffectiveAccessToAllHosts() const {
144 return active_permissions()->HasEffectiveAccessToAllHosts();
145 }
146
147 PermissionMessages PermissionsData::GetPermissionMessages() const {
148 if (ShouldSkipPermissionWarnings(extension_id_)) {
440 return PermissionMessages(); 149 return PermissionMessages();
441 } else { 150 } else {
442 return PermissionMessageProvider::Get()->GetPermissionMessages( 151 return PermissionMessageProvider::Get()->GetPermissionMessages(
443 GetActivePermissions(extension), extension->GetType()); 152 active_permissions(), manifest_type_);
444 } 153 }
445 } 154 }
446 155
447 // static 156 std::vector<base::string16> PermissionsData::GetPermissionMessageStrings()
448 std::vector<base::string16> PermissionsData::GetPermissionMessageStrings( 157 const {
449 const Extension* extension) { 158 if (ShouldSkipPermissionWarnings(extension_id_))
450 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_);
451 if (ShouldSkipPermissionWarnings(extension)) {
452 return std::vector<base::string16>(); 159 return std::vector<base::string16>();
453 } else { 160 return PermissionMessageProvider::Get()->GetWarningMessages(
454 return PermissionMessageProvider::Get()->GetWarningMessages( 161 active_permissions(), manifest_type_);
455 GetActivePermissions(extension), extension->GetType());
456 }
457 } 162 }
458 163
459 // static 164 std::vector<base::string16>
460 std::vector<base::string16> PermissionsData::GetPermissionMessageDetailsStrings( 165 PermissionsData::GetPermissionMessageDetailsStrings() const {
461 const Extension* extension) { 166 base::AutoLock auto_lock(runtime_lock_);
462 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_); 167 if (ShouldSkipPermissionWarnings(extension_id_))
463 if (ShouldSkipPermissionWarnings(extension)) {
464 return std::vector<base::string16>(); 168 return std::vector<base::string16>();
465 } else { 169 return PermissionMessageProvider::Get()->GetWarningMessagesDetails(
466 return PermissionMessageProvider::Get()->GetWarningMessagesDetails( 170 active_permissions(), manifest_type_);
467 GetActivePermissions(extension), extension->GetType());
468 }
469 } 171 }
470 172
471 // static
472 bool PermissionsData::CanExecuteScriptOnPage(const Extension* extension, 173 bool PermissionsData::CanExecuteScriptOnPage(const Extension* extension,
473 const GURL& document_url, 174 const GURL& document_url,
474 const GURL& top_frame_url, 175 const GURL& top_frame_url,
475 int tab_id, 176 int tab_id,
476 const UserScript* script, 177 const UserScript* script,
477 int process_id, 178 int process_id,
478 std::string* error) { 179 std::string* error) const {
479 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_); 180 if (g_policy_delegate &&
480 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 181 !g_policy_delegate->CanExecuteScriptOnPage(extension,
182 document_url,
183 top_frame_url,
184 tab_id,
185 script,
186 process_id,
187 error)) {
188 return false;
189 }
190
481 bool can_execute_everywhere = CanExecuteScriptEverywhere(extension); 191 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 && 192 if (!can_execute_everywhere &&
490 !ExtensionsClient::Get()->IsScriptableURL(document_url, error)) { 193 !ExtensionsClient::Get()->IsScriptableURL(document_url, error)) {
491 return false; 194 return false;
492 } 195 }
493 196
494 if (!command_line->HasSwitch(switches::kExtensionsOnChromeURLs)) { 197 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
198 switches::kExtensionsOnChromeURLs)) {
495 if (document_url.SchemeIs(content::kChromeUIScheme) && 199 if (document_url.SchemeIs(content::kChromeUIScheme) &&
496 !can_execute_everywhere) { 200 !can_execute_everywhere) {
497 if (error) 201 if (error)
498 *error = errors::kCannotAccessChromeUrl; 202 *error = manifest_errors::kCannotAccessChromeUrl;
499 return false; 203 return false;
500 } 204 }
501 } 205 }
502 206
503 if (top_frame_url.SchemeIs(extensions::kExtensionScheme) && 207 if (top_frame_url.SchemeIs(kExtensionScheme) &&
504 top_frame_url.GetOrigin() != 208 top_frame_url.GetOrigin() !=
505 Extension::GetBaseURLFromExtensionId(extension->id()).GetOrigin() && 209 Extension::GetBaseURLFromExtensionId(extension->id()).GetOrigin() &&
506 !can_execute_everywhere) { 210 !can_execute_everywhere) {
507 if (error) 211 if (error)
508 *error = errors::kCannotAccessExtensionUrl; 212 *error = manifest_errors::kCannotAccessExtensionUrl;
509 return false; 213 return false;
510 } 214 }
511 215
512 if (HasTabSpecificPermissionToExecuteScript(extension, tab_id, top_frame_url)) 216 if (HasTabSpecificPermissionToExecuteScript(tab_id, top_frame_url))
513 return true; 217 return true;
514 218
515 bool can_access = false; 219 bool can_access = false;
516 220
517 if (script) { 221 if (script) {
518 // If a script is specified, use its matches. 222 // If a script is specified, use its matches.
519 can_access = script->MatchesURL(document_url); 223 can_access = script->MatchesURL(document_url);
520 } else { 224 } else {
521 // Otherwise, see if this extension has permission to execute script 225 // Otherwise, see if this extension has permission to execute script
522 // programmatically on pages. 226 // programmatically on pages.
523 can_access = GetActivePermissions(extension)-> 227 can_access = active_permissions()->HasExplicitAccessToOrigin(document_url);
524 HasExplicitAccessToOrigin(document_url);
525 } 228 }
526 229
527 if (!can_access && error) { 230 if (!can_access && error) {
528 *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage, 231 *error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage,
529 document_url.spec()); 232 document_url.spec());
530 } 233 }
531 234
532 return can_access; 235 return can_access;
533 } 236 }
534 237
535 // static 238 bool PermissionsData::CanCaptureVisiblePage(int tab_id,
536 bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) { 239 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, 240 const URLPattern all_urls(URLPattern::SCHEME_ALL,
554 URLPattern::kAllUrlsPattern); 241 URLPattern::kAllUrlsPattern);
555 if (active_permissions->explicit_hosts().ContainsPattern(all_urls)) 242
243 if (active_permissions()->explicit_hosts().ContainsPattern(all_urls))
556 return true; 244 return true;
557 245
558 if (tab_id >= 0) { 246 if (tab_id >= 0) {
559 scoped_refptr<const PermissionSet> tab_permissions = 247 scoped_refptr<const PermissionSet> tab_permissions =
560 GetTabSpecificPermissions(extension, tab_id); 248 GetTabSpecificPermissions(tab_id);
561 if (tab_permissions && 249 if (tab_permissions &&
562 tab_permissions->HasAPIPermission(APIPermission::kTab)) { 250 tab_permissions->HasAPIPermission(APIPermission::kTab)) {
563 return true; 251 return true;
564 } 252 }
565 if (error) 253 if (error)
566 *error = errors::kActiveTabPermissionNotGranted; 254 *error = manifest_errors::kActiveTabPermissionNotGranted;
567 return false; 255 return false;
568 } 256 }
569 257
570 if (error) 258 if (error)
571 *error = errors::kAllURLOrActiveTabNeeded; 259 *error = manifest_errors::kAllURLOrActiveTabNeeded;
572 return false; 260 return false;
573 } 261 }
574 262
575 // static 263 // static
576 bool PermissionsData::RequiresActionForScriptExecution( 264 bool PermissionsData::RequiresActionForScriptExecution(
577 const Extension* extension) { 265 const Extension* extension) const {
578 return RequiresActionForScriptExecution(extension, -1, GURL()); 266 return RequiresActionForScriptExecution(extension, -1, GURL());
579 } 267 }
580 268
581 // static 269 // static
582 bool PermissionsData::RequiresActionForScriptExecution( 270 bool PermissionsData::RequiresActionForScriptExecution(
583 const Extension* extension, 271 const Extension* extension,
584 int tab_id, 272 int tab_id,
585 const GURL& url) { 273 const GURL& url) const {
586 // For now, the user should be notified when an extension with all hosts 274 // For now, the user should be notified when an extension with all hosts
587 // permission tries to execute a script on a page, with exceptions for policy- 275 // permission tries to execute a script on a page, with exceptions for
588 // enabled and component extensions. If this doesn't meet those criteria, 276 // policy-enabled and component extensions. If this doesn't meet those
589 // return immediately. 277 // criteria, return immediately.
590 if (!extension->ShouldDisplayInExtensionSettings() || 278 if (!extension->ShouldDisplayInExtensionSettings() ||
591 Manifest::IsPolicyLocation(extension->location()) || 279 Manifest::IsPolicyLocation(extension->location()) ||
592 Manifest::IsComponentLocation(extension->location()) || 280 Manifest::IsComponentLocation(extension->location()) ||
593 !ShouldWarnAllHosts(extension)) { 281 !active_permissions()->ShouldWarnAllHosts()) {
594 return false; 282 return false;
595 } 283 }
596 284
597 // If the extension has explicit permission to run on the given tab, then 285 // If the extension has explicit permission to run on the given tab, then
598 // we don't need to alert the user. 286 // we don't need to alert the user.
599 if (HasTabSpecificPermissionToExecuteScript(extension, tab_id, url)) 287 if (HasTabSpecificPermissionToExecuteScript(tab_id, url))
600 return false; 288 return false;
601 289
602 return true; 290 return true;
603 } 291 }
604 292
605 bool PermissionsData::ParsePermissions(Extension* extension, 293 scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions(
606 base::string16* error) { 294 int tab_id) const {
607 initial_required_permissions_.reset(new InitialPermissions); 295 base::AutoLock auto_lock(runtime_lock_);
608 if (!ParseHelper(extension, 296 CHECK_GE(tab_id, 0);
609 keys::kPermissions, 297 TabPermissionsMap::const_iterator iter =
610 &initial_required_permissions_->api_permissions, 298 tab_specific_permissions_.find(tab_id);
611 &initial_required_permissions_->host_permissions, 299 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 } 300 }
627 301
628 void PermissionsData::InitializeManifestPermissions(Extension* extension) { 302 bool PermissionsData::HasTabSpecificPermissionToExecuteScript(
629 ManifestHandler::AddExtensionInitialRequiredPermissions( 303 int tab_id,
630 extension, &initial_required_permissions_->manifest_permissions); 304 const GURL& url) const {
631 } 305 if (tab_id >= 0) {
632 306 scoped_refptr<const PermissionSet> tab_permissions =
633 void PermissionsData::FinalizePermissions(Extension* extension) { 307 GetTabSpecificPermissions(tab_id);
634 active_permissions_ = new PermissionSet( 308 if (tab_permissions.get() &&
635 initial_required_permissions_->api_permissions, 309 tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) {
636 initial_required_permissions_->manifest_permissions, 310 return true;
637 initial_required_permissions_->host_permissions, 311 }
638 initial_required_permissions_->scriptable_hosts); 312 }
639 313 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 } 314 }
660 315
661 } // namespace extensions 316 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698