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; | |
|
Devlin
2017/02/14 23:17:10
I think I'd prefer these to be stored in a struct
Devlin
2017/02/14 23:17:10
the trailing _ is used for member variables; this
nrpeter
2017/03/22 23:47:39
Done.
nrpeter
2017/03/22 23:47:39
Done.
| |
| 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 { | |
|
Devlin
2017/02/14 23:17:10
We should check thread access here.
nrpeter
2017/03/22 23:47:39
Done.
| |
| 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, | |
| 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 URLPatternSet* old_blocked = default_runtime_blocked_hosts_unsafe_; | |
| 200 default_runtime_blocked_hosts_unsafe_ = | |
| 201 new URLPatternSet(default_runtime_blocked_hosts); | |
| 202 delete old_blocked; | |
| 203 URLPatternSet* old_allowed = default_runtime_allowed_hosts_unsafe_; | |
| 204 default_runtime_allowed_hosts_unsafe_ = | |
| 205 new URLPatternSet(default_runtime_allowed_hosts); | |
| 206 delete old_allowed; | |
| 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 return runtime_blocked_hosts().MatchesURL(url) && | |
|
Devlin
2017/02/14 23:17:10
we can use the sets directly here.
nrpeter
2017/03/22 23:47:39
If we did, we'd end up duplicating the code to che
| |
| 399 !runtime_allowed_hosts().MatchesURL(url); | |
| 400 } | |
| 401 | |
| 330 PermissionsData::AccessType PermissionsData::CanRunOnPage( | 402 PermissionsData::AccessType PermissionsData::CanRunOnPage( |
| 331 const Extension* extension, | 403 const Extension* extension, |
| 332 const GURL& document_url, | 404 const GURL& document_url, |
| 333 int tab_id, | 405 int tab_id, |
| 334 const URLPatternSet& permitted_url_patterns, | 406 const URLPatternSet& permitted_url_patterns, |
| 335 const URLPatternSet& withheld_url_patterns, | 407 const URLPatternSet& withheld_url_patterns, |
| 336 std::string* error) const { | 408 std::string* error) const { |
| 337 runtime_lock_.AssertAcquired(); | 409 runtime_lock_.AssertAcquired(); |
| 338 if (g_policy_delegate && | 410 if (g_policy_delegate && |
| 339 !g_policy_delegate->CanExecuteScriptOnPage(extension, document_url, | 411 !g_policy_delegate->CanExecuteScriptOnPage(extension, document_url, |
| 340 tab_id, error)) { | 412 tab_id, error)) |
| 413 return ACCESS_DENIED; | |
| 414 | |
| 415 if (IsRuntimeBlockedHost(document_url)) { | |
| 416 if (error) | |
| 417 *error = | |
| 418 "This page cannot be scripted due to an ExtensionsSettings policy."; | |
| 341 return ACCESS_DENIED; | 419 return ACCESS_DENIED; |
| 342 } | 420 } |
| 343 | 421 |
| 344 if (IsRestrictedUrl(document_url, extension, error)) | 422 if (IsRestrictedUrl(document_url, extension, error)) |
| 345 return ACCESS_DENIED; | 423 return ACCESS_DENIED; |
| 346 | 424 |
| 347 if (HasTabSpecificPermissionToExecuteScript(tab_id, document_url)) | 425 if (HasTabSpecificPermissionToExecuteScript(tab_id, document_url)) |
| 348 return ACCESS_ALLOWED; | 426 return ACCESS_ALLOWED; |
| 349 | 427 |
| 350 if (permitted_url_patterns.MatchesURL(document_url)) | 428 if (permitted_url_patterns.MatchesURL(document_url)) |
| 351 return ACCESS_ALLOWED; | 429 return ACCESS_ALLOWED; |
| 352 | 430 |
| 353 if (withheld_url_patterns.MatchesURL(document_url)) | 431 if (withheld_url_patterns.MatchesURL(document_url)) |
| 354 return ACCESS_WITHHELD; | 432 return ACCESS_WITHHELD; |
| 355 | 433 |
| 356 if (error) { | 434 if (error) { |
| 357 if (extension->permissions_data()->active_permissions().HasAPIPermission( | 435 if (extension->permissions_data()->active_permissions().HasAPIPermission( |
| 358 APIPermission::kTab)) { | 436 APIPermission::kTab)) { |
| 359 *error = ErrorUtils::FormatErrorMessage( | 437 *error = ErrorUtils::FormatErrorMessage( |
| 360 manifest_errors::kCannotAccessPageWithUrl, document_url.spec()); | 438 manifest_errors::kCannotAccessPageWithUrl, document_url.spec()); |
| 361 } else { | 439 } else { |
| 362 *error = manifest_errors::kCannotAccessPage; | 440 *error = manifest_errors::kCannotAccessPage; |
| 363 } | 441 } |
| 364 } | 442 } |
| 365 | 443 |
| 366 return ACCESS_DENIED; | 444 return ACCESS_DENIED; |
| 367 } | 445 } |
| 368 | 446 |
| 369 } // namespace extensions | 447 } // namespace extensions |
| OLD | NEW |