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 3// found in the LICENSE file. 4 5#include "extensions/common/permissions/permissions_data.h" 6 7#include "base/command_line.h" 8#include "content/public/common/url_constants.h" 9#include "extensions/common/constants.h" 10#include "extensions/common/error_utils.h" 11#include "extensions/common/extensions_client.h" 12#include "extensions/common/manifest.h" 13#include "extensions/common/manifest_constants.h" 14#include "extensions/common/manifest_handlers/permissions_parser.h" 15#include "extensions/common/permissions/permission_message_provider.h" 16#include "extensions/common/switches.h" 17#include "extensions/common/url_pattern_set.h" 18#include "extensions/common/user_script.h" 19#include "url/gurl.h" 20#include "url/url_constants.h" 21 22namespace extensions { 23 24namespace { 25 26PermissionsData::PolicyDelegate* g_policy_delegate = NULL; 27 28} // namespace 29 30PermissionsData::PermissionsData(const Extension* extension) 31 : extension_id_(extension->id()), manifest_type_(extension->GetType()) { 32 base::AutoLock auto_lock(runtime_lock_); 33 scoped_refptr<const PermissionSet> required_permissions = 34 PermissionsParser::GetRequiredPermissions(extension); 35 active_permissions_unsafe_ = 36 new PermissionSet(required_permissions->apis(), 37 required_permissions->manifest_permissions(), 38 required_permissions->explicit_hosts(), 39 required_permissions->scriptable_hosts()); 40} 41 42PermissionsData::~PermissionsData() { 43} 44 45// static 46void PermissionsData::SetPolicyDelegate(PolicyDelegate* delegate) { 47 g_policy_delegate = delegate; 48} 49 50// static 51bool PermissionsData::CanSilentlyIncreasePermissions( 52 const Extension* extension) { 53 return extension->location() != Manifest::INTERNAL; 54} 55 56// static 57bool PermissionsData::CanExecuteScriptEverywhere(const Extension* extension) { 58 if (extension->location() == Manifest::COMPONENT) 59 return true; 60 61 const ExtensionsClient::ScriptingWhitelist& whitelist = 62 ExtensionsClient::Get()->GetScriptingWhitelist(); 63 64 return std::find(whitelist.begin(), whitelist.end(), extension->id()) != 65 whitelist.end(); 66} 67 68bool PermissionsData::ShouldSkipPermissionWarnings( 69 const std::string& extension_id) { 70 // See http://b/4946060 for more details. 71 return extension_id == std::string("nckgahadagoaajjgafhacjanaoiihapd"); 72} 73 74// static 75bool PermissionsData::IsRestrictedUrl(const GURL& document_url, 76 const GURL& top_frame_url, 77 const Extension* extension, 78 std::string* error) { 79 if (CanExecuteScriptEverywhere(extension)) 80 return false; 81 82 // Check if the scheme is valid for extensions. If not, return. 83 if (!URLPattern::IsValidSchemeForExtensions(document_url.scheme()) && 84 document_url.spec() != url::kAboutBlankURL) { 85 if (error) { 86 *error = ErrorUtils::FormatErrorMessage( 87 manifest_errors::kCannotAccessPage, 88 document_url.spec()); 89 } 90 return true; 91 } 92 93 if (!ExtensionsClient::Get()->IsScriptableURL(document_url, error)) 94 return true; 95 96 bool allow_on_chrome_urls = base::CommandLine::ForCurrentProcess()->HasSwitch( 97 switches::kExtensionsOnChromeURLs); 98 if (document_url.SchemeIs(content::kChromeUIScheme) && 99 !allow_on_chrome_urls) { 100 if (error) 101 *error = manifest_errors::kCannotAccessChromeUrl; 102 return true; 103 } 104 105 if (top_frame_url.SchemeIs(kExtensionScheme) && 106 top_frame_url.host() != extension->id() && 107 !allow_on_chrome_urls) { 108 if (error) 109 *error = manifest_errors::kCannotAccessExtensionUrl; 110 return true; 111 } 112 113 return false; 114} 115 116void PermissionsData::SetActivePermissions( 117 const PermissionSet* permissions) const { 118 base::AutoLock auto_lock(runtime_lock_); 119 active_permissions_unsafe_ = permissions; 120} 121 122void PermissionsData::UpdateTabSpecificPermissions( 123 int tab_id, 124 scoped_refptr<const PermissionSet> permissions) const { 125 base::AutoLock auto_lock(runtime_lock_); 126 CHECK_GE(tab_id, 0); 127 TabPermissionsMap::iterator iter = tab_specific_permissions_.find(tab_id); 128 if (iter == tab_specific_permissions_.end()) 129 tab_specific_permissions_[tab_id] = permissions; 130 else 131 iter->second = PermissionSet::CreateUnion(iter->second, permissions); 132} 133 134void PermissionsData::ClearTabSpecificPermissions(int tab_id) const { 135 base::AutoLock auto_lock(runtime_lock_); 136 CHECK_GE(tab_id, 0); 137 tab_specific_permissions_.erase(tab_id); 138} 139 140bool PermissionsData::HasAPIPermission(APIPermission::ID permission) const { 141 return active_permissions()->HasAPIPermission(permission); 142} 143 144bool PermissionsData::HasAPIPermission( 145 const std::string& permission_name) const { 146 return active_permissions()->HasAPIPermission(permission_name); 147} 148 149bool PermissionsData::HasAPIPermissionForTab( 150 int tab_id, 151 APIPermission::ID permission) const { 152 if (HasAPIPermission(permission)) 153 return true; 154 155 scoped_refptr<const PermissionSet> tab_permissions = 156 GetTabSpecificPermissions(tab_id); 157 158 // Place autolock below the HasAPIPermission() and 159 // GetTabSpecificPermissions(), since each already acquires the lock. 160 base::AutoLock auto_lock(runtime_lock_); 161 return tab_permissions.get() && tab_permissions->HasAPIPermission(permission); 162} 163 164bool PermissionsData::CheckAPIPermissionWithParam( 165 APIPermission::ID permission, 166 const APIPermission::CheckParam* param) const { 167 return active_permissions()->CheckAPIPermissionWithParam(permission, param); 168} 169 170const URLPatternSet& PermissionsData::GetEffectiveHostPermissions() const { 171 return active_permissions()->effective_hosts(); 172} 173 174bool PermissionsData::HasHostPermission(const GURL& url) const { 175 return active_permissions()->HasExplicitAccessToOrigin(url); 176} 177 178bool PermissionsData::HasEffectiveAccessToAllHosts() const { 179 return active_permissions()->HasEffectiveAccessToAllHosts(); 180} 181 182PermissionMessages PermissionsData::GetPermissionMessages() const { 183 if (ShouldSkipPermissionWarnings(extension_id_)) { 184 return PermissionMessages(); 185 } else { 186 return PermissionMessageProvider::Get()->GetPermissionMessages( 187 active_permissions(), manifest_type_); 188 } 189} 190 191std::vector<base::string16> PermissionsData::GetPermissionMessageStrings() 192 const { 193 if (ShouldSkipPermissionWarnings(extension_id_)) 194 return std::vector<base::string16>(); 195 return PermissionMessageProvider::Get()->GetWarningMessages( 196 active_permissions(), manifest_type_); 197} 198 199std::vector<base::string16> 200PermissionsData::GetPermissionMessageDetailsStrings() const { 201 if (ShouldSkipPermissionWarnings(extension_id_)) 202 return std::vector<base::string16>(); 203 return PermissionMessageProvider::Get()->GetWarningMessagesDetails( 204 active_permissions(), manifest_type_); 205} 206 207bool PermissionsData::CanAccessPage(const Extension* extension, 208 const GURL& document_url, 209 const GURL& top_frame_url, 210 int tab_id, 211 int process_id, 212 std::string* error) const { 213 return CanRunOnPage(extension, 214 document_url, 215 top_frame_url, 216 tab_id, 217 process_id, 218 active_permissions()->explicit_hosts(), 219 error); 220} 221 222bool PermissionsData::CanRunContentScriptOnPage(const Extension* extension, 223 const GURL& document_url, 224 const GURL& top_frame_url, 225 int tab_id, 226 int process_id, 227 std::string* error) const { 228 return CanRunOnPage(extension, 229 document_url, 230 top_frame_url, 231 tab_id, 232 process_id, 233 active_permissions()->scriptable_hosts(), 234 error); 235} 236 237bool PermissionsData::CanCaptureVisiblePage(int tab_id, 238 std::string* error) const { 239 const URLPattern all_urls(URLPattern::SCHEME_ALL, 240 URLPattern::kAllUrlsPattern); 241 242 if (active_permissions()->explicit_hosts().ContainsPattern(all_urls)) 243 return true; 244 245 if (tab_id >= 0) { 246 scoped_refptr<const PermissionSet> tab_permissions = 247 GetTabSpecificPermissions(tab_id); 248 if (tab_permissions && 249 tab_permissions->HasAPIPermission(APIPermission::kTab)) { 250 return true; 251 } 252 if (error) 253 *error = manifest_errors::kActiveTabPermissionNotGranted; 254 return false; 255 } 256 257 if (error) 258 *error = manifest_errors::kAllURLOrActiveTabNeeded; 259 return false; 260} 261 262// static 263bool PermissionsData::RequiresActionForScriptExecution( 264 const Extension* extension) const { 265 return RequiresActionForScriptExecution(extension, -1, GURL()); 266} 267 268// static 269bool PermissionsData::RequiresActionForScriptExecution( 270 const Extension* extension, 271 int tab_id, 272 const GURL& url) const { 273 // For now, the user should be notified when an extension with all hosts 274 // permission tries to execute a script on a page. Exceptions for policy- 275 // enabled and component extensions, and extensions which are whitelisted to 276 // execute scripts everywhere. 277 if (!extension->ShouldDisplayInExtensionSettings() || 278 Manifest::IsPolicyLocation(extension->location()) || 279 Manifest::IsComponentLocation(extension->location()) || 280 CanExecuteScriptEverywhere(extension) || 281 !active_permissions()->ShouldWarnAllHosts()) { 282 return false; 283 } 284 285 // If the extension has explicit permission to run on the given tab, then 286 // we don't need to alert the user. 287 if (HasTabSpecificPermissionToExecuteScript(tab_id, url)) 288 return false; 289 290 return true; 291} 292 293scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions( 294 int tab_id) const { 295 base::AutoLock auto_lock(runtime_lock_); 296 CHECK_GE(tab_id, 0); 297 TabPermissionsMap::const_iterator iter = 298 tab_specific_permissions_.find(tab_id); 299 return (iter != tab_specific_permissions_.end()) ? iter->second : NULL; 300} 301 302bool PermissionsData::HasTabSpecificPermissionToExecuteScript( 303 int tab_id, 304 const GURL& url) const { 305 if (tab_id >= 0) { 306 scoped_refptr<const PermissionSet> tab_permissions = 307 GetTabSpecificPermissions(tab_id); 308 if (tab_permissions.get() && 309 tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) { 310 return true; 311 } 312 } 313 return false; 314} 315 316bool PermissionsData::CanRunOnPage(const Extension* extension, 317 const GURL& document_url, 318 const GURL& top_frame_url, 319 int tab_id, 320 int process_id, 321 const URLPatternSet& permitted_url_patterns, 322 std::string* error) const { 323 if (g_policy_delegate && 324 !g_policy_delegate->CanExecuteScriptOnPage( 325 extension, document_url, top_frame_url, tab_id, process_id, error)) { 326 return false; 327 } 328 329 if (IsRestrictedUrl(document_url, top_frame_url, extension, error)) 330 return false; 331 332 if (HasTabSpecificPermissionToExecuteScript(tab_id, top_frame_url)) 333 return true; 334 335 bool can_access = permitted_url_patterns.MatchesURL(document_url); 336 337 if (!can_access && error) { 338 *error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage, 339 document_url.spec()); 340 } 341 342 return can_access; 343} 344 345} // namespace extensions 346