| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/lazy_instance.h" |
| 11 #include "base/macros.h" | 12 #include "base/macros.h" |
| 12 #include "content/public/common/url_constants.h" | 13 #include "content/public/common/url_constants.h" |
| 13 #include "extensions/common/constants.h" | 14 #include "extensions/common/constants.h" |
| 14 #include "extensions/common/error_utils.h" | 15 #include "extensions/common/error_utils.h" |
| 15 #include "extensions/common/extension.h" | 16 #include "extensions/common/extension.h" |
| 16 #include "extensions/common/extensions_client.h" | 17 #include "extensions/common/extensions_client.h" |
| 17 #include "extensions/common/manifest.h" | 18 #include "extensions/common/manifest.h" |
| 18 #include "extensions/common/manifest_constants.h" | 19 #include "extensions/common/manifest_constants.h" |
| 19 #include "extensions/common/manifest_handlers/permissions_parser.h" | 20 #include "extensions/common/manifest_handlers/permissions_parser.h" |
| 20 #include "extensions/common/permissions/api_permission.h" | 21 #include "extensions/common/permissions/api_permission.h" |
| 21 #include "extensions/common/permissions/permission_message_provider.h" | 22 #include "extensions/common/permissions/permission_message_provider.h" |
| 22 #include "extensions/common/switches.h" | 23 #include "extensions/common/switches.h" |
| 23 #include "extensions/common/url_pattern_set.h" | 24 #include "extensions/common/url_pattern_set.h" |
| 24 #include "url/gurl.h" | 25 #include "url/gurl.h" |
| 25 #include "url/url_constants.h" | 26 #include "url/url_constants.h" |
| 26 | 27 |
| 27 namespace extensions { | 28 namespace extensions { |
| 28 | 29 |
| 29 namespace { | 30 namespace { |
| 30 | 31 |
| 31 PermissionsData::PolicyDelegate* g_policy_delegate = nullptr; | 32 PermissionsData::PolicyDelegate* g_policy_delegate = nullptr; |
| 32 | 33 |
| 34 struct DefaultRuntimePolicy { |
| 35 URLPatternSet blocked_hosts; |
| 36 URLPatternSet allowed_hosts; |
| 37 }; |
| 38 // URLs an extension can't interact with. An extension can override these |
| 39 // settings by declaring its own list of blocked and allowed hosts using |
| 40 // policy_blocked_hosts and policy_allowed_hosts. |
| 41 base::LazyInstance<DefaultRuntimePolicy>::Leaky default_runtime_policy = |
| 42 LAZY_INSTANCE_INITIALIZER; |
| 43 |
| 33 class AutoLockOnValidThread { | 44 class AutoLockOnValidThread { |
| 34 public: | 45 public: |
| 35 AutoLockOnValidThread(base::Lock& lock, base::ThreadChecker* thread_checker) | 46 AutoLockOnValidThread(base::Lock& lock, base::ThreadChecker* thread_checker) |
| 36 : auto_lock_(lock) { | 47 : auto_lock_(lock) { |
| 37 DCHECK(!thread_checker || thread_checker->CalledOnValidThread()); | 48 DCHECK(!thread_checker || thread_checker->CalledOnValidThread()); |
| 38 } | 49 } |
| 39 | 50 |
| 40 private: | 51 private: |
| 41 base::AutoLock auto_lock_; | 52 base::AutoLock auto_lock_; |
| 42 | 53 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 bool PermissionsData::ShouldSkipPermissionWarnings( | 91 bool PermissionsData::ShouldSkipPermissionWarnings( |
| 81 const std::string& extension_id) { | 92 const std::string& extension_id) { |
| 82 // See http://b/4946060 for more details. | 93 // See http://b/4946060 for more details. |
| 83 return extension_id == extension_misc::kProdHangoutsExtensionId; | 94 return extension_id == extension_misc::kProdHangoutsExtensionId; |
| 84 } | 95 } |
| 85 | 96 |
| 86 // static | 97 // static |
| 87 bool PermissionsData::IsRestrictedUrl(const GURL& document_url, | 98 bool PermissionsData::IsRestrictedUrl(const GURL& document_url, |
| 88 const Extension* extension, | 99 const Extension* extension, |
| 89 std::string* error) { | 100 std::string* error) { |
| 101 if (extension && |
| 102 extension->permissions_data()->IsRuntimeBlockedHost(document_url)) { |
| 103 *error = |
| 104 "This page cannot be scripted due to an ExtensionsSettings policy."; |
| 105 return true; |
| 106 } |
| 90 if (extension && CanExecuteScriptEverywhere(extension)) | 107 if (extension && CanExecuteScriptEverywhere(extension)) |
| 91 return false; | 108 return false; |
| 92 | 109 |
| 93 // Check if the scheme is valid for extensions. If not, return. | 110 // Check if the scheme is valid for extensions. If not, return. |
| 94 if (!URLPattern::IsValidSchemeForExtensions(document_url.scheme()) && | 111 if (!URLPattern::IsValidSchemeForExtensions(document_url.scheme()) && |
| 95 document_url.spec() != url::kAboutBlankURL) { | 112 document_url.spec() != url::kAboutBlankURL) { |
| 96 if (error) { | 113 if (error) { |
| 97 if (extension->permissions_data()->active_permissions().HasAPIPermission( | 114 if (extension->permissions_data()->active_permissions().HasAPIPermission( |
| 98 APIPermission::kTab)) { | 115 APIPermission::kTab)) { |
| 99 *error = ErrorUtils::FormatErrorMessage( | 116 *error = ErrorUtils::FormatErrorMessage( |
| (...skipping 20 matching lines...) Expand all Loading... |
| 120 if (extension && document_url.SchemeIs(kExtensionScheme) && | 137 if (extension && document_url.SchemeIs(kExtensionScheme) && |
| 121 document_url.host() != extension->id() && !allow_on_chrome_urls) { | 138 document_url.host() != extension->id() && !allow_on_chrome_urls) { |
| 122 if (error) | 139 if (error) |
| 123 *error = manifest_errors::kCannotAccessExtensionUrl; | 140 *error = manifest_errors::kCannotAccessExtensionUrl; |
| 124 return true; | 141 return true; |
| 125 } | 142 } |
| 126 | 143 |
| 127 return false; | 144 return false; |
| 128 } | 145 } |
| 129 | 146 |
| 147 bool PermissionsData::UsesDefaultPolicyHostRestrictions() const { |
| 148 DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread()); |
| 149 return uses_default_policy_host_restrictions; |
| 150 } |
| 151 |
| 152 const URLPatternSet& PermissionsData::default_policy_blocked_hosts() { |
| 153 return default_runtime_policy.Get().blocked_hosts; |
| 154 } |
| 155 |
| 156 const URLPatternSet& PermissionsData::default_policy_allowed_hosts() { |
| 157 return default_runtime_policy.Get().allowed_hosts; |
| 158 } |
| 159 |
| 160 const URLPatternSet& PermissionsData::policy_blocked_hosts() const { |
| 161 DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread()); |
| 162 if (uses_default_policy_host_restrictions) |
| 163 return default_policy_blocked_hosts(); |
| 164 return policy_blocked_hosts_unsafe_; |
| 165 } |
| 166 |
| 167 const URLPatternSet& PermissionsData::policy_allowed_hosts() const { |
| 168 DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread()); |
| 169 if (uses_default_policy_host_restrictions) |
| 170 return default_policy_allowed_hosts(); |
| 171 return policy_allowed_hosts_unsafe_; |
| 172 } |
| 173 |
| 130 void PermissionsData::BindToCurrentThread() const { | 174 void PermissionsData::BindToCurrentThread() const { |
| 131 DCHECK(!thread_checker_); | 175 DCHECK(!thread_checker_); |
| 132 thread_checker_.reset(new base::ThreadChecker()); | 176 thread_checker_.reset(new base::ThreadChecker()); |
| 133 } | 177 } |
| 134 | 178 |
| 135 void PermissionsData::SetPermissions( | 179 void PermissionsData::SetPermissions( |
| 136 std::unique_ptr<const PermissionSet> active, | 180 std::unique_ptr<const PermissionSet> active, |
| 137 std::unique_ptr<const PermissionSet> withheld) const { | 181 std::unique_ptr<const PermissionSet> withheld) const { |
| 138 AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); | 182 AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); |
| 139 active_permissions_unsafe_ = std::move(active); | 183 active_permissions_unsafe_ = std::move(active); |
| 140 withheld_permissions_unsafe_ = std::move(withheld); | 184 withheld_permissions_unsafe_ = std::move(withheld); |
| 141 } | 185 } |
| 142 | 186 |
| 187 void PermissionsData::SetPolicyHostRestrictions( |
| 188 const URLPatternSet& runtime_blocked_hosts, |
| 189 const URLPatternSet& runtime_allowed_hosts) const { |
| 190 AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); |
| 191 policy_blocked_hosts_unsafe_ = runtime_blocked_hosts; |
| 192 policy_allowed_hosts_unsafe_ = runtime_allowed_hosts; |
| 193 uses_default_policy_host_restrictions = false; |
| 194 } |
| 195 |
| 196 void PermissionsData::SetUsesDefaultHostRestrictions() const { |
| 197 AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); |
| 198 uses_default_policy_host_restrictions = true; |
| 199 } |
| 200 |
| 201 // static |
| 202 void PermissionsData::SetDefaultPolicyHostRestrictions( |
| 203 const URLPatternSet& default_runtime_blocked_hosts, |
| 204 const URLPatternSet& default_runtime_allowed_hosts) { |
| 205 default_runtime_policy.Get().blocked_hosts = default_runtime_blocked_hosts; |
| 206 default_runtime_policy.Get().allowed_hosts = default_runtime_allowed_hosts; |
| 207 } |
| 208 |
| 143 void PermissionsData::SetActivePermissions( | 209 void PermissionsData::SetActivePermissions( |
| 144 std::unique_ptr<const PermissionSet> active) const { | 210 std::unique_ptr<const PermissionSet> active) const { |
| 145 AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); | 211 AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); |
| 146 active_permissions_unsafe_ = std::move(active); | 212 active_permissions_unsafe_ = std::move(active); |
| 147 } | 213 } |
| 148 | 214 |
| 149 void PermissionsData::UpdateTabSpecificPermissions( | 215 void PermissionsData::UpdateTabSpecificPermissions( |
| 150 int tab_id, | 216 int tab_id, |
| 151 const PermissionSet& permissions) const { | 217 const PermissionSet& permissions) const { |
| 152 AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); | 218 AutoLockOnValidThread lock(runtime_lock_, thread_checker_.get()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 URLPatternSet PermissionsData::GetEffectiveHostPermissions() const { | 267 URLPatternSet PermissionsData::GetEffectiveHostPermissions() const { |
| 202 base::AutoLock auto_lock(runtime_lock_); | 268 base::AutoLock auto_lock(runtime_lock_); |
| 203 URLPatternSet effective_hosts = active_permissions_unsafe_->effective_hosts(); | 269 URLPatternSet effective_hosts = active_permissions_unsafe_->effective_hosts(); |
| 204 for (const auto& val : tab_specific_permissions_) | 270 for (const auto& val : tab_specific_permissions_) |
| 205 effective_hosts.AddPatterns(val.second->effective_hosts()); | 271 effective_hosts.AddPatterns(val.second->effective_hosts()); |
| 206 return effective_hosts; | 272 return effective_hosts; |
| 207 } | 273 } |
| 208 | 274 |
| 209 bool PermissionsData::HasHostPermission(const GURL& url) const { | 275 bool PermissionsData::HasHostPermission(const GURL& url) const { |
| 210 base::AutoLock auto_lock(runtime_lock_); | 276 base::AutoLock auto_lock(runtime_lock_); |
| 211 return active_permissions_unsafe_->HasExplicitAccessToOrigin(url); | 277 return active_permissions_unsafe_->HasExplicitAccessToOrigin(url) && |
| 278 !IsRuntimeBlockedHost(url); |
| 212 } | 279 } |
| 213 | 280 |
| 214 bool PermissionsData::HasEffectiveAccessToAllHosts() const { | 281 bool PermissionsData::HasEffectiveAccessToAllHosts() const { |
| 215 base::AutoLock auto_lock(runtime_lock_); | 282 base::AutoLock auto_lock(runtime_lock_); |
| 216 return active_permissions_unsafe_->HasEffectiveAccessToAllHosts(); | 283 return active_permissions_unsafe_->HasEffectiveAccessToAllHosts(); |
| 217 } | 284 } |
| 218 | 285 |
| 219 PermissionMessages PermissionsData::GetPermissionMessages() const { | 286 PermissionMessages PermissionsData::GetPermissionMessages() const { |
| 220 base::AutoLock auto_lock(runtime_lock_); | 287 base::AutoLock auto_lock(runtime_lock_); |
| 221 return PermissionMessageProvider::Get()->GetPermissionMessages( | 288 return PermissionMessageProvider::Get()->GetPermissionMessages( |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 if (tab_id >= 0) { | 387 if (tab_id >= 0) { |
| 321 const PermissionSet* tab_permissions = GetTabSpecificPermissions(tab_id); | 388 const PermissionSet* tab_permissions = GetTabSpecificPermissions(tab_id); |
| 322 if (tab_permissions && | 389 if (tab_permissions && |
| 323 tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) { | 390 tab_permissions->explicit_hosts().MatchesSecurityOrigin(url)) { |
| 324 return true; | 391 return true; |
| 325 } | 392 } |
| 326 } | 393 } |
| 327 return false; | 394 return false; |
| 328 } | 395 } |
| 329 | 396 |
| 397 bool PermissionsData::IsRuntimeBlockedHost(const GURL& url) const { |
| 398 runtime_lock_.AssertAcquired(); |
| 399 return policy_blocked_hosts().MatchesURL(url) && |
| 400 !policy_allowed_hosts().MatchesURL(url); |
| 401 } |
| 402 |
| 330 PermissionsData::AccessType PermissionsData::CanRunOnPage( | 403 PermissionsData::AccessType PermissionsData::CanRunOnPage( |
| 331 const Extension* extension, | 404 const Extension* extension, |
| 332 const GURL& document_url, | 405 const GURL& document_url, |
| 333 int tab_id, | 406 int tab_id, |
| 334 const URLPatternSet& permitted_url_patterns, | 407 const URLPatternSet& permitted_url_patterns, |
| 335 const URLPatternSet& withheld_url_patterns, | 408 const URLPatternSet& withheld_url_patterns, |
| 336 std::string* error) const { | 409 std::string* error) const { |
| 337 runtime_lock_.AssertAcquired(); | 410 runtime_lock_.AssertAcquired(); |
| 338 if (g_policy_delegate && | 411 if (g_policy_delegate && |
| 339 !g_policy_delegate->CanExecuteScriptOnPage(extension, document_url, | 412 !g_policy_delegate->CanExecuteScriptOnPage(extension, document_url, |
| 340 tab_id, error)) { | 413 tab_id, error)) |
| 341 return ACCESS_DENIED; | 414 return ACCESS_DENIED; |
| 342 } | |
| 343 | 415 |
| 344 if (IsRestrictedUrl(document_url, extension, error)) | 416 if (IsRestrictedUrl(document_url, extension, error)) |
| 345 return ACCESS_DENIED; | 417 return ACCESS_DENIED; |
| 346 | 418 |
| 347 if (HasTabSpecificPermissionToExecuteScript(tab_id, document_url)) | 419 if (HasTabSpecificPermissionToExecuteScript(tab_id, document_url)) |
| 348 return ACCESS_ALLOWED; | 420 return ACCESS_ALLOWED; |
| 349 | 421 |
| 350 if (permitted_url_patterns.MatchesURL(document_url)) | 422 if (permitted_url_patterns.MatchesURL(document_url)) |
| 351 return ACCESS_ALLOWED; | 423 return ACCESS_ALLOWED; |
| 352 | 424 |
| 353 if (withheld_url_patterns.MatchesURL(document_url)) | 425 if (withheld_url_patterns.MatchesURL(document_url)) |
| 354 return ACCESS_WITHHELD; | 426 return ACCESS_WITHHELD; |
| 355 | 427 |
| 356 if (error) { | 428 if (error) { |
| 357 if (extension->permissions_data()->active_permissions().HasAPIPermission( | 429 if (extension->permissions_data()->active_permissions().HasAPIPermission( |
| 358 APIPermission::kTab)) { | 430 APIPermission::kTab)) { |
| 359 *error = ErrorUtils::FormatErrorMessage( | 431 *error = ErrorUtils::FormatErrorMessage( |
| 360 manifest_errors::kCannotAccessPageWithUrl, document_url.spec()); | 432 manifest_errors::kCannotAccessPageWithUrl, document_url.spec()); |
| 361 } else { | 433 } else { |
| 362 *error = manifest_errors::kCannotAccessPage; | 434 *error = manifest_errors::kCannotAccessPage; |
| 363 } | 435 } |
| 364 } | 436 } |
| 365 | 437 |
| 366 return ACCESS_DENIED; | 438 return ACCESS_DENIED; |
| 367 } | 439 } |
| 368 | 440 |
| 369 } // namespace extensions | 441 } // namespace extensions |
| OLD | NEW |