| // Copyright 2021 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 "chrome/browser/webshare/safe_browsing_request.h" |
| |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/location.h" |
| #include "base/task/task_traits.h" |
| #include "base/task_runner.h" |
| #include "base/threading/sequenced_task_runner_handle.h" |
| #include "base/timer/timer.h" |
| #include "components/safe_browsing/core/browser/db/database_manager.h" |
| #include "content/public/browser/browser_task_traits.h" |
| #include "url/gurl.h" |
| |
| namespace { |
| |
| // The maximum amount of time to wait for the Safe Browsing response. |
| constexpr base::TimeDelta kSafeBrowsingCheckTimeout = base::Seconds(2); |
| |
| } // namespace |
| |
| // SafeBrowsingRequest::SafeBrowsingClient -------------------------- |
| |
| class SafeBrowsingRequest::SafeBrowsingClient |
| : public safe_browsing::SafeBrowsingDatabaseManager::Client { |
| public: |
| SafeBrowsingClient(scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> |
| database_manager, |
| base::WeakPtr<SafeBrowsingRequest> handler, |
| scoped_refptr<base::TaskRunner> handler_task_runner) |
| : database_manager_(database_manager), |
| handler_(handler), |
| handler_task_runner_(handler_task_runner) {} |
| |
| ~SafeBrowsingClient() override { |
| if (timeout_.IsRunning()) |
| database_manager_->CancelApiCheck(this); |
| } |
| |
| void CheckUrl(const GURL& url) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| |
| // Start the timer before the call to CheckDownloadUrl(), as it may |
| // call back into CheckDownloadUrl() synchronously. |
| timeout_.Start(FROM_HERE, kSafeBrowsingCheckTimeout, this, |
| &SafeBrowsingClient::OnTimeout); |
| |
| if (!database_manager_->IsSupported() || |
| database_manager_->CheckDownloadUrl({url}, this)) { |
| timeout_.AbandonAndStop(); |
| SendResultToHandler(/*is_url_safe=*/true); |
| } |
| } |
| |
| private: |
| SafeBrowsingClient(const SafeBrowsingClient&) = delete; |
| SafeBrowsingClient& operator=(const SafeBrowsingClient&) = delete; |
| |
| void OnTimeout() { |
| database_manager_->CancelApiCheck(this); |
| SendResultToHandler(/*is_url_safe=*/true); |
| } |
| |
| void SendResultToHandler(bool is_url_safe) { |
| handler_task_runner_->PostTask( |
| FROM_HERE, base::BindOnce(&SafeBrowsingRequest::OnResultReceived, |
| handler_, is_url_safe)); |
| } |
| |
| // SafeBrowsingDatabaseManager::Client: |
| void OnCheckDownloadUrlResult( |
| const std::vector<GURL>& url_chain, |
| safe_browsing::SBThreatType threat_type) override { |
| timeout_.AbandonAndStop(); |
| bool is_url_safe = threat_type == safe_browsing::SB_THREAT_TYPE_SAFE; |
| SendResultToHandler(is_url_safe); |
| } |
| |
| base::OneShotTimer timeout_; |
| scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager_; |
| base::WeakPtr<SafeBrowsingRequest> handler_; |
| scoped_refptr<base::TaskRunner> handler_task_runner_; |
| }; |
| |
| // SafeBrowsingRequest ---------------------------------------------- |
| |
| SafeBrowsingRequest::SafeBrowsingRequest( |
| scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager, |
| const GURL& url, |
| base::OnceCallback<void(bool)> callback) |
| : callback_(std::move(callback)) { |
| client_ = std::make_unique<SafeBrowsingClient>( |
| database_manager, weak_factory_.GetWeakPtr(), |
| base::SequencedTaskRunnerHandle::Get()); |
| content::GetIOThreadTaskRunner({})->PostTask( |
| FROM_HERE, base::BindOnce(&SafeBrowsingClient::CheckUrl, |
| base::Unretained(client_.get()), url)); |
| } |
| |
| SafeBrowsingRequest::~SafeBrowsingRequest() { |
| content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, |
| client_.release()); |
| } |
| |
| void SafeBrowsingRequest::OnResultReceived(bool is_url_safe) { |
| DCHECK(callback_); |
| std::move(callback_).Run(is_url_safe); |
| } |