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 22 namespace extensions { 23 24 namespace { 25 26 PermissionsData::PolicyDelegate* g_policy_delegate = NULL; 27 28 } // namespace 29 30 PermissionsData::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 42 PermissionsData::~PermissionsData() { 43 } 44 45 // static 46 void PermissionsData::SetPolicyDelegate(PolicyDelegate* delegate) { 47 g_policy_delegate = delegate; 48 } 49 50 // static 51 bool PermissionsData::CanSilentlyIncreasePermissions( 52 const Extension* extension) { 53 return extension->location() != Manifest::INTERNAL; 54 } 55 56 // static 57 bool 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 68 bool 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 75 bool 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 116 void PermissionsData::SetActivePermissions( 117 const PermissionSet* permissions) const { 118 base::AutoLock auto_lock(runtime_lock_); 119 active_permissions_unsafe_ = permissions; 120 } 121 122 void 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 134 void 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 140 bool PermissionsData::HasAPIPermission(APIPermission::ID permission) const { 141 return active_permissions()->HasAPIPermission(permission); 142 } 143 144 bool PermissionsData::HasAPIPermission( 145 const std::string& permission_name) const { 146 return active_permissions()->HasAPIPermission(permission_name); 147 } 148 149 bool 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 164 bool PermissionsData::CheckAPIPermissionWithParam( 165 APIPermission::ID permission, 166 const APIPermission::CheckParam* param) const { 167 return active_permissions()->CheckAPIPermissionWithParam(permission, param); 168 } 169 170 const URLPatternSet& PermissionsData::GetEffectiveHostPermissions() const { 171 return active_permissions()->effective_hosts(); 172 } 173 174 bool PermissionsData::HasHostPermission(const GURL& url) const { 175 return active_permissions()->HasExplicitAccessToOrigin(url); 176 } 177 178 bool PermissionsData::HasEffectiveAccessToAllHosts() const { 179 return active_permissions()->HasEffectiveAccessToAllHosts(); 180 } 181 182 PermissionMessages 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 191 std::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 199 std::vector<base::string16> 200 PermissionsData::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 207 bool 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 222 bool 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 237 bool 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 263 bool PermissionsData::RequiresActionForScriptExecution( 264 const Extension* extension) const { 265 return RequiresActionForScriptExecution(extension, -1, GURL()); 266 } 267 268 // static 269 bool 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 293 scoped_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 302 bool 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 316 bool 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