OLD | NEW |
---|---|
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 |
OLD | NEW |