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 auto_lock(runtime_lock_); |
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 if (ShouldSkipPermissionWarnings(extension_id_)) |
462 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_); | |
463 if (ShouldSkipPermissionWarnings(extension)) { | |
464 return std::vector<base::string16>(); | 167 return std::vector<base::string16>(); |
465 } else { | 168 return PermissionMessageProvider::Get()->GetWarningMessagesDetails( |
466 return PermissionMessageProvider::Get()->GetWarningMessagesDetails( | 169 active_permissions(), manifest_type_); |
467 GetActivePermissions(extension), extension->GetType()); | |
468 } | |
469 } | 170 } |
470 | 171 |
471 // static | |
472 bool PermissionsData::CanExecuteScriptOnPage(const Extension* extension, | 172 bool PermissionsData::CanExecuteScriptOnPage(const Extension* extension, |
473 const GURL& document_url, | 173 const GURL& document_url, |
474 const GURL& top_frame_url, | 174 const GURL& top_frame_url, |
475 int tab_id, | 175 int tab_id, |
476 const UserScript* script, | 176 const UserScript* script, |
477 int process_id, | 177 int process_id, |
478 std::string* error) { | 178 std::string* error) const { |
479 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_); | 179 if (g_policy_delegate && |
480 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 180 !g_policy_delegate->CanExecuteScriptOnPage(extension, |
| 181 document_url, |
| 182 top_frame_url, |
| 183 tab_id, |
| 184 script, |
| 185 process_id, |
| 186 error)) { |
| 187 return false; |
| 188 } |
| 189 |
481 bool can_execute_everywhere = CanExecuteScriptEverywhere(extension); | 190 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 && | 191 if (!can_execute_everywhere && |
490 !ExtensionsClient::Get()->IsScriptableURL(document_url, error)) { | 192 !ExtensionsClient::Get()->IsScriptableURL(document_url, error)) { |
491 return false; | 193 return false; |
492 } | 194 } |
493 | 195 |
494 if (!command_line->HasSwitch(switches::kExtensionsOnChromeURLs)) { | 196 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 197 switches::kExtensionsOnChromeURLs)) { |
495 if (document_url.SchemeIs(content::kChromeUIScheme) && | 198 if (document_url.SchemeIs(content::kChromeUIScheme) && |
496 !can_execute_everywhere) { | 199 !can_execute_everywhere) { |
497 if (error) | 200 if (error) |
498 *error = errors::kCannotAccessChromeUrl; | 201 *error = manifest_errors::kCannotAccessChromeUrl; |
499 return false; | 202 return false; |
500 } | 203 } |
501 } | 204 } |
502 | 205 |
503 if (top_frame_url.SchemeIs(extensions::kExtensionScheme) && | 206 if (top_frame_url.SchemeIs(kExtensionScheme) && |
504 top_frame_url.GetOrigin() != | 207 top_frame_url.GetOrigin() != |
505 Extension::GetBaseURLFromExtensionId(extension->id()).GetOrigin() && | 208 Extension::GetBaseURLFromExtensionId(extension->id()).GetOrigin() && |
506 !can_execute_everywhere) { | 209 !can_execute_everywhere) { |
507 if (error) | 210 if (error) |
508 *error = errors::kCannotAccessExtensionUrl; | 211 *error = manifest_errors::kCannotAccessExtensionUrl; |
509 return false; | 212 return false; |
510 } | 213 } |
511 | 214 |
512 if (HasTabSpecificPermissionToExecuteScript(extension, tab_id, top_frame_url)) | 215 if (HasTabSpecificPermissionToExecuteScript(tab_id, top_frame_url)) |
513 return true; | 216 return true; |
514 | 217 |
515 bool can_access = false; | 218 bool can_access = false; |
516 | 219 |
517 if (script) { | 220 if (script) { |
518 // If a script is specified, use its matches. | 221 // If a script is specified, use its matches. |
519 can_access = script->MatchesURL(document_url); | 222 can_access = script->MatchesURL(document_url); |
520 } else { | 223 } else { |
521 // Otherwise, see if this extension has permission to execute script | 224 // Otherwise, see if this extension has permission to execute script |
522 // programmatically on pages. | 225 // programmatically on pages. |
523 can_access = GetActivePermissions(extension)-> | 226 can_access = active_permissions()->HasExplicitAccessToOrigin(document_url); |
524 HasExplicitAccessToOrigin(document_url); | |
525 } | 227 } |
526 | 228 |
527 if (!can_access && error) { | 229 if (!can_access && error) { |
528 *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage, | 230 *error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage, |
529 document_url.spec()); | 231 document_url.spec()); |
530 } | 232 } |
531 | 233 |
532 return can_access; | 234 return can_access; |
533 } | 235 } |
534 | 236 |
535 // static | 237 bool PermissionsData::CanCaptureVisiblePage(int tab_id, |
536 bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) { | 238 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, | 239 const URLPattern all_urls(URLPattern::SCHEME_ALL, |
554 URLPattern::kAllUrlsPattern); | 240 URLPattern::kAllUrlsPattern); |
555 if (active_permissions->explicit_hosts().ContainsPattern(all_urls)) | 241 |
| 242 if (active_permissions()->explicit_hosts().ContainsPattern(all_urls)) |
556 return true; | 243 return true; |
557 | 244 |
558 if (tab_id >= 0) { | 245 if (tab_id >= 0) { |
559 scoped_refptr<const PermissionSet> tab_permissions = | 246 scoped_refptr<const PermissionSet> tab_permissions = |
560 GetTabSpecificPermissions(extension, tab_id); | 247 GetTabSpecificPermissions(tab_id); |
561 if (tab_permissions && | 248 if (tab_permissions && |
562 tab_permissions->HasAPIPermission(APIPermission::kTab)) { | 249 tab_permissions->HasAPIPermission(APIPermission::kTab)) { |
563 return true; | 250 return true; |
564 } | 251 } |
565 if (error) | 252 if (error) |
566 *error = errors::kActiveTabPermissionNotGranted; | 253 *error = manifest_errors::kActiveTabPermissionNotGranted; |
567 return false; | 254 return false; |
568 } | 255 } |
569 | 256 |
570 if (error) | 257 if (error) |
571 *error = errors::kAllURLOrActiveTabNeeded; | 258 *error = manifest_errors::kAllURLOrActiveTabNeeded; |
572 return false; | 259 return false; |
573 } | 260 } |
574 | 261 |
575 // static | 262 // static |
576 bool PermissionsData::RequiresActionForScriptExecution( | 263 bool PermissionsData::RequiresActionForScriptExecution( |
577 const Extension* extension) { | 264 const Extension* extension) const { |
578 return RequiresActionForScriptExecution(extension, -1, GURL()); | 265 return RequiresActionForScriptExecution(extension, -1, GURL()); |
579 } | 266 } |
580 | 267 |
581 // static | 268 // static |
582 bool PermissionsData::RequiresActionForScriptExecution( | 269 bool PermissionsData::RequiresActionForScriptExecution( |
583 const Extension* extension, | 270 const Extension* extension, |
584 int tab_id, | 271 int tab_id, |
585 const GURL& url) { | 272 const GURL& url) const { |
586 // For now, the user should be notified when an extension with all hosts | 273 // For now, the user should be notified when an extension with all hosts |
587 // permission tries to execute a script on a page. Exceptions for policy- | 274 // permission tries to execute a script on a page. Exceptions for policy- |
588 // enabled and component extensions, and extensions which are whitelisted to | 275 // enabled and component extensions, and extensions which are whitelisted to |
589 // execute scripts everywhere. | 276 // execute scripts everywhere. |
590 if (!extension->ShouldDisplayInExtensionSettings() || | 277 if (!extension->ShouldDisplayInExtensionSettings() || |
591 Manifest::IsPolicyLocation(extension->location()) || | 278 Manifest::IsPolicyLocation(extension->location()) || |
592 Manifest::IsComponentLocation(extension->location()) || | 279 Manifest::IsComponentLocation(extension->location()) || |
593 CanExecuteScriptEverywhere(extension) || | 280 CanExecuteScriptEverywhere(extension) || |
594 !ShouldWarnAllHosts(extension)) { | 281 !active_permissions()->ShouldWarnAllHosts()) { |
595 return false; | 282 return false; |
596 } | 283 } |
597 | 284 |
598 // 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 |
599 // we don't need to alert the user. | 286 // we don't need to alert the user. |
600 if (HasTabSpecificPermissionToExecuteScript(extension, tab_id, url)) | 287 if (HasTabSpecificPermissionToExecuteScript(tab_id, url)) |
601 return false; | 288 return false; |
602 | 289 |
603 return true; | 290 return true; |
604 } | 291 } |
605 | 292 |
606 bool PermissionsData::ParsePermissions(Extension* extension, | 293 scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions( |
607 base::string16* error) { | 294 int tab_id) const { |
608 initial_required_permissions_.reset(new InitialPermissions); | 295 base::AutoLock auto_lock(runtime_lock_); |
609 if (!ParseHelper(extension, | 296 CHECK_GE(tab_id, 0); |
610 keys::kPermissions, | 297 TabPermissionsMap::const_iterator iter = |
611 &initial_required_permissions_->api_permissions, | 298 tab_specific_permissions_.find(tab_id); |
612 &initial_required_permissions_->host_permissions, | 299 return (iter != tab_specific_permissions_.end()) ? iter->second : NULL; |
613 error)) { | |
614 return false; | |
615 } | |
616 | |
617 initial_optional_permissions_.reset(new InitialPermissions); | |
618 if (!ParseHelper(extension, | |
619 keys::kOptionalPermissions, | |
620 &initial_optional_permissions_->api_permissions, | |
621 &initial_optional_permissions_->host_permissions, | |
622 error)) { | |
623 return false; | |
624 } | |
625 | |
626 return true; | |
627 } | 300 } |
628 | 301 |
629 void PermissionsData::InitializeManifestPermissions(Extension* extension) { | 302 bool PermissionsData::HasTabSpecificPermissionToExecuteScript( |
630 ManifestHandler::AddExtensionInitialRequiredPermissions( | 303 int tab_id, |
631 extension, &initial_required_permissions_->manifest_permissions); | 304 const GURL& url) const { |
632 } | 305 if (tab_id >= 0) { |
633 | 306 scoped_refptr<const PermissionSet> tab_permissions = |
634 void PermissionsData::FinalizePermissions(Extension* extension) { | 307 GetTabSpecificPermissions(tab_id); |
635 active_permissions_ = new PermissionSet( | 308 if (tab_permissions.get() && |
636 initial_required_permissions_->api_permissions, | 309 tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) { |
637 initial_required_permissions_->manifest_permissions, | 310 return true; |
638 initial_required_permissions_->host_permissions, | 311 } |
639 initial_required_permissions_->scriptable_hosts); | 312 } |
640 | 313 return false; |
641 required_permission_set_ = new PermissionSet( | |
642 initial_required_permissions_->api_permissions, | |
643 initial_required_permissions_->manifest_permissions, | |
644 initial_required_permissions_->host_permissions, | |
645 initial_required_permissions_->scriptable_hosts); | |
646 | |
647 optional_permission_set_ = new PermissionSet( | |
648 initial_optional_permissions_->api_permissions, | |
649 initial_optional_permissions_->manifest_permissions, | |
650 initial_optional_permissions_->host_permissions, | |
651 URLPatternSet()); | |
652 | |
653 initial_required_permissions_.reset(); | |
654 initial_optional_permissions_.reset(); | |
655 } | |
656 | |
657 bool PermissionsData::ShouldWarnAllHosts(const Extension* extension) { | |
658 base::AutoLock auto_lock(extension->permissions_data()->runtime_lock_); | |
659 return PermissionsData::GetActivePermissions(extension)->ShouldWarnAllHosts(); | |
660 } | 314 } |
661 | 315 |
662 } // namespace extensions | 316 } // namespace extensions |
OLD | NEW |