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