| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/webui/webui_allowlist.h" |
| |
| #include <memory> |
| |
| #include "base/memory/scoped_refptr.h" |
| #include "base/sequence_checker.h" |
| #include "base/supports_user_data.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/common/url_constants.h" |
| #include "content/public/common/url_utils.h" |
| #include "ui/webui/webui_allowlist_provider.h" |
| #include "url/gurl.h" |
| |
| const char kWebUIAllowlistKeyName[] = "WebUIAllowlist"; |
| |
| namespace { |
| struct WebUIAllowlistHolder : base::SupportsUserData::Data { |
| explicit WebUIAllowlistHolder(scoped_refptr<WebUIAllowlist> list) |
| : allow_list(std::move(list)) {} |
| const scoped_refptr<WebUIAllowlist> allow_list; |
| }; |
| |
| } // namespace |
| |
| // static |
| WebUIAllowlist* WebUIAllowlist::GetOrCreate( |
| content::BrowserContext* browser_context) { |
| if (!browser_context->GetUserData(kWebUIAllowlistKeyName)) { |
| auto list = base::MakeRefCounted<WebUIAllowlist>(); |
| browser_context->SetUserData( |
| kWebUIAllowlistKeyName, |
| std::make_unique<WebUIAllowlistHolder>(std::move(list))); |
| } |
| return static_cast<WebUIAllowlistHolder*>( |
| browser_context->GetUserData(kWebUIAllowlistKeyName)) |
| ->allow_list.get(); |
| } |
| |
| WebUIAllowlist::WebUIAllowlist() = default; |
| |
| WebUIAllowlist::~WebUIAllowlist() = default; |
| |
| void WebUIAllowlist::RegisterAutoGrantedPermission(const url::Origin& origin, |
| ContentSettingsType type, |
| ContentSetting setting) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| |
| DCHECK(content::HasWebUIOrigin(origin)); |
| |
| // It doesn't make sense to grant a default content setting. |
| DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); |
| |
| SetContentSettingsAndNotifyProvider( |
| ContentSettingsPattern::FromURLNoWildcard(origin.GetURL()), |
| ContentSettingsPattern::Wildcard(), type, setting); |
| } |
| |
| void WebUIAllowlist::RegisterAutoGrantedPermissions( |
| const url::Origin& origin, |
| std::initializer_list<ContentSettingsType> types) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| |
| for (const ContentSettingsType& type : types) |
| RegisterAutoGrantedPermission(origin, type); |
| } |
| |
| void WebUIAllowlist::RegisterAutoGrantedThirdPartyCookies( |
| const url::Origin& top_level_origin, |
| const std::vector<ContentSettingsPattern>& origin_patterns) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| |
| DCHECK(content::HasWebUIOrigin(top_level_origin)); |
| |
| const auto top_level_origin_pattern = |
| ContentSettingsPattern::FromURLNoWildcard(top_level_origin.GetURL()); |
| for (const auto& pattern : origin_patterns) { |
| // For COOKIES content setting, |primary_pattern| is the origin setting the |
| // cookie, |secondary_pattern| is the top-level document's origin. |
| SetContentSettingsAndNotifyProvider(pattern, top_level_origin_pattern, |
| ContentSettingsType::COOKIES, |
| CONTENT_SETTING_ALLOW); |
| } |
| } |
| |
| void WebUIAllowlist::SetWebUIAllowlistProvider( |
| WebUIAllowlistProvider* provider) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| |
| provider_ = provider; |
| } |
| |
| void WebUIAllowlist::ResetWebUIAllowlistProvider() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| |
| provider_ = nullptr; |
| } |
| |
| std::unique_ptr<content_settings::RuleIterator> WebUIAllowlist::GetRuleIterator( |
| ContentSettingsType content_type) const NO_THREAD_SAFETY_ANALYSIS { |
| // NO_THREAD_SAFETY_ANALYSIS: GetRuleIterator immediately locks the lock. |
| return value_map_.GetRuleIterator(content_type, &lock_); |
| } |
| |
| void WebUIAllowlist::SetContentSettingsAndNotifyProvider( |
| const ContentSettingsPattern& primary_pattern, |
| const ContentSettingsPattern& secondary_pattern, |
| ContentSettingsType type, |
| ContentSetting setting) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| |
| { |
| base::AutoLock auto_lock(lock_); |
| value_map_.SetValue(primary_pattern, secondary_pattern, type, base::Time(), |
| base::Value(setting), |
| /* constraints */ {}); |
| } |
| |
| // Notify the provider. |provider_| can be nullptr if |
| // HostContentSettingsRegistry is shutting down i.e. when Chrome shuts down. |
| // |
| // It's okay to notify the provider multiple times even if the setting isn't |
| // changed. |
| if (provider_) { |
| provider_->NotifyContentSettingChange(primary_pattern, secondary_pattern, |
| type); |
| } |
| } |