| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/safe_browsing/content/browser/url_checker_holder.h" |
| |
| #include "base/check_op.h" |
| #include "base/functional/bind.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "components/safe_browsing/content/browser/web_ui/safe_browsing_ui.h" |
| #include "components/safe_browsing/core/browser/hashprefix_realtime/hash_realtime_service.h" |
| #include "components/safe_browsing/core/browser/realtime/url_lookup_service_base.h" |
| #include "components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h" |
| #include "components/safe_browsing/core/browser/url_checker_delegate.h" |
| #include "components/safe_browsing/core/common/features.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/web_contents.h" |
| #include "net/base/load_flags.h" |
| #include "services/network/public/mojom/url_response_head.mojom.h" |
| |
| namespace safe_browsing { |
| |
| UrlCheckerHolder::OnCompleteCheckResult::OnCompleteCheckResult( |
| bool proceed, |
| bool showed_interstitial, |
| bool has_post_commit_interstitial_skipped, |
| SafeBrowsingUrlCheckerImpl::PerformedCheck performed_check, |
| bool all_checks_completed) |
| : proceed(proceed), |
| showed_interstitial(showed_interstitial), |
| has_post_commit_interstitial_skipped( |
| has_post_commit_interstitial_skipped), |
| performed_check(performed_check), |
| all_checks_completed(all_checks_completed) {} |
| |
| UrlCheckerHolder::StartParams::StartParams( |
| net::HttpRequestHeaders headers, |
| int load_flags, |
| bool has_user_gesture, |
| GURL url, |
| std::string method) |
| : headers(headers), |
| load_flags(load_flags), |
| has_user_gesture(has_user_gesture), |
| url(url), |
| method(method) {} |
| |
| UrlCheckerHolder::StartParams::StartParams(const StartParams& other) = default; |
| |
| UrlCheckerHolder::StartParams::~StartParams() = default; |
| |
| UrlCheckerHolder::UrlCheckerHolder( |
| GetDelegateCallback delegate_getter, |
| content::FrameTreeNodeId frame_tree_node_id, |
| std::optional<int64_t> navigation_id, |
| base::RepeatingCallback<content::WebContents*()> web_contents_getter, |
| OnCompleteCheckCallback complete_callback, |
| bool url_real_time_lookup_enabled, |
| bool can_check_db, |
| bool can_check_high_confidence_allowlist, |
| std::string url_lookup_service_metric_suffix, |
| base::WeakPtr<RealTimeUrlLookupServiceBase> url_lookup_service, |
| base::WeakPtr<HashRealTimeService> hash_realtime_service, |
| hash_realtime_utils::HashRealTimeSelection hash_realtime_selection, |
| bool is_async_check, |
| bool check_allowlist_before_hash_database, |
| SessionID tab_id, |
| std::optional<internal::ReferringAppInfo> referring_app_info) |
| : delegate_getter_(std::move(delegate_getter)), |
| frame_tree_node_id_(frame_tree_node_id), |
| navigation_id_(navigation_id), |
| web_contents_getter_(web_contents_getter), |
| complete_callback_(std::move(complete_callback)), |
| url_real_time_lookup_enabled_(url_real_time_lookup_enabled), |
| can_check_db_(can_check_db), |
| can_check_high_confidence_allowlist_(can_check_high_confidence_allowlist), |
| url_lookup_service_metric_suffix_(url_lookup_service_metric_suffix), |
| url_lookup_service_(url_lookup_service), |
| hash_realtime_service_(hash_realtime_service), |
| hash_realtime_selection_(hash_realtime_selection), |
| is_async_check_(is_async_check), |
| check_allowlist_before_hash_database_( |
| check_allowlist_before_hash_database), |
| tab_id_(tab_id), |
| referring_app_info_(referring_app_info) {} |
| |
| UrlCheckerHolder::~UrlCheckerHolder() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| } |
| |
| void UrlCheckerHolder::Start(const StartParams& params) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| scoped_refptr<UrlCheckerDelegate> url_checker_delegate = |
| std::move(delegate_getter_).Run(); |
| |
| if (url_checker_for_testing_) { |
| url_checker_ = std::move(url_checker_for_testing_); |
| } else { |
| url_checker_ = std::make_unique<SafeBrowsingUrlCheckerImpl>( |
| params.headers, params.load_flags, params.has_user_gesture, |
| url_checker_delegate, web_contents_getter_, nullptr, |
| content::ChildProcessHost::kInvalidUniqueID, std::nullopt, |
| frame_tree_node_id_.value(), navigation_id_, |
| url_real_time_lookup_enabled_, can_check_db_, |
| can_check_high_confidence_allowlist_, url_lookup_service_metric_suffix_, |
| content::GetUIThreadTaskRunner({}), url_lookup_service_, |
| hash_realtime_service_, hash_realtime_selection_, is_async_check_, |
| check_allowlist_before_hash_database_, tab_id_, referring_app_info_); |
| } |
| |
| CheckUrl(params.url, params.method); |
| } |
| |
| void UrlCheckerHolder::CheckUrl(const GURL& url, const std::string& method) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| DCHECK(url_checker_); |
| pending_checks_++; |
| redirect_chain_.push_back(url); |
| url_checker_->CheckUrl(url, method, |
| base::BindOnce(&UrlCheckerHolder::OnCheckUrlResult, |
| base::Unretained(this))); |
| } |
| |
| void UrlCheckerHolder::SwapCompleteCallback(OnCompleteCheckCallback callback) { |
| complete_callback_ = std::move(callback); |
| } |
| |
| const std::vector<GURL>& UrlCheckerHolder::GetRedirectChain() { |
| return redirect_chain_; |
| } |
| |
| void UrlCheckerHolder::SetUrlCheckerForTesting( |
| std::unique_ptr<SafeBrowsingUrlCheckerImpl> checker) { |
| url_checker_for_testing_ = std::move(checker); |
| } |
| |
| bool UrlCheckerHolder::IsRealTimeCheckForTesting() { |
| return url_real_time_lookup_enabled_ || |
| hash_realtime_selection_ != |
| hash_realtime_utils::HashRealTimeSelection::kNone; |
| } |
| |
| bool UrlCheckerHolder::IsAsyncCheckForTesting() { |
| return is_async_check_; |
| } |
| |
| bool UrlCheckerHolder::IsCheckAllowlistBeforeHashDatabaseForTesting() { |
| return check_allowlist_before_hash_database_; |
| } |
| |
| void UrlCheckerHolder::AddUrlInRedirectChainForTesting(const GURL& url) { |
| redirect_chain_.push_back(url); |
| } |
| |
| void UrlCheckerHolder::OnCheckUrlResult( |
| bool proceed, |
| bool showed_interstitial, |
| bool has_post_commit_interstitial_skipped, |
| SafeBrowsingUrlCheckerImpl::PerformedCheck performed_check) { |
| pending_checks_--; |
| bool all_checks_completed = pending_checks_ == 0; |
| OnCompleteCheckResult result(proceed, showed_interstitial, |
| has_post_commit_interstitial_skipped, |
| performed_check, all_checks_completed); |
| complete_callback_.Run(result); |
| } |
| |
| } // namespace safe_browsing |