blob: ed5476eb3403610e2d7a6e98e71b44968263b5a7 [file] [log] [blame]
// Copyright 2018 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 "components/safe_browsing/browser/safe_browsing_network_context.h"
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/task/post_task.h"
#include "components/safe_browsing/common/safebrowsing_constants.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
#include "net/net_buildflags.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/network_context.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace safe_browsing {
namespace {
void DeleteChannelIDFiles(base::FilePath channel_id_path) {
base::DeleteFile(channel_id_path, false);
base::DeleteFile(
base::FilePath(channel_id_path.value() + FILE_PATH_LITERAL("-journal")),
false);
}
} // namespace
class SafeBrowsingNetworkContext::SharedURLLoaderFactory
: public network::SharedURLLoaderFactory {
public:
SharedURLLoaderFactory(
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
const base::FilePath& user_data_dir,
NetworkContextParamsFactory network_context_params_factory)
: request_context_getter_(request_context_getter),
user_data_dir_(user_data_dir),
network_context_params_factory_(
std::move(network_context_params_factory)) {}
void Reset() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
url_loader_factory_.reset();
network_context_.reset();
request_context_getter_ = nullptr;
if (internal_state_) {
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&InternalState::Reset, internal_state_));
}
}
network::mojom::NetworkContext* GetNetworkContext() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (!network_context_ || network_context_.encountered_error()) {
if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
content::GetNetworkService()->CreateNetworkContext(
MakeRequest(&network_context_), CreateNetworkContextParams());
} else {
internal_state_ = base::MakeRefCounted<InternalState>();
internal_state_->Initialize(request_context_getter_,
MakeRequest(&network_context_));
}
}
return network_context_.get();
}
void FlushForTesting() {
if (network_context_)
network_context_.FlushForTesting();
if (url_loader_factory_)
url_loader_factory_.FlushForTesting();
}
protected:
// network::URLLoaderFactory implementation:
void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& request,
network::mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
GetURLLoaderFactory()->CreateLoaderAndStart(
std::move(loader), routing_id, request_id, options, request,
std::move(client), traffic_annotation);
}
void Clone(network::mojom::URLLoaderFactoryRequest request) override {
GetURLLoaderFactory()->Clone(std::move(request));
}
// network::SharedURLLoaderFactory implementation:
std::unique_ptr<network::SharedURLLoaderFactoryInfo> Clone() override {
NOTREACHED();
return nullptr;
}
network::mojom::URLLoaderFactory* GetURLLoaderFactory() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (!url_loader_factory_ || url_loader_factory_.encountered_error()) {
network::mojom::URLLoaderFactoryParamsPtr params =
network::mojom::URLLoaderFactoryParams::New();
params->process_id = network::mojom::kBrowserProcessId;
params->is_corb_enabled = false;
GetNetworkContext()->CreateURLLoaderFactory(
MakeRequest(&url_loader_factory_), std::move(params));
}
return url_loader_factory_.get();
}
private:
// This class holds on to the network::NetworkContext object on the IO thread.
class InternalState : public base::RefCountedThreadSafe<InternalState> {
public:
InternalState() = default;
void Initialize(
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
network::mojom::NetworkContextRequest network_context_request) {
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&InternalState::InitOnIO, this, request_context_getter,
std::move(network_context_request)));
}
void Reset() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
network_context_impl_.reset();
request_context_getter_ = nullptr;
}
private:
friend class base::RefCountedThreadSafe<InternalState>;
virtual ~InternalState() {}
void InitOnIO(
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
network::mojom::NetworkContextRequest network_context_request) {
request_context_getter_ = std::move(request_context_getter);
network_context_impl_ = std::make_unique<network::NetworkContext>(
content::GetNetworkServiceImpl(), std::move(network_context_request),
request_context_getter_->GetURLRequestContext(),
/*cors_exempt_header_list=*/std::vector<std::string>());
}
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
std::unique_ptr<network::NetworkContext> network_context_impl_;
DISALLOW_COPY_AND_ASSIGN(InternalState);
};
friend class base::RefCounted<SharedURLLoaderFactory>;
~SharedURLLoaderFactory() override = default;
network::mojom::NetworkContextParamsPtr CreateNetworkContextParams() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
network::mojom::NetworkContextParamsPtr network_context_params =
network_context_params_factory_.Run();
network_context_params->context_name = std::string("safe_browsing");
network_context_params->http_cache_enabled = false;
// These are needed for PAC scripts that use FTP URLs.
#if !BUILDFLAG(DISABLE_FTP_SUPPORT)
network_context_params->enable_ftp_url_support = true;
#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT)
base::FilePath cookie_path = user_data_dir_.Append(
base::FilePath::StringType(kSafeBrowsingBaseFilename) + kCookiesFile);
network_context_params->cookie_path = cookie_path;
network_context_params->enable_encrypted_cookies = false;
// TODO(nharper): Remove the following when no longer needed - see
// crbug.com/903642.
base::FilePath::StringType channel_id_path =
base::FilePath::StringType(kSafeBrowsingBaseFilename) + kChannelIDFile;
base::PostTaskWithTraits(
FROM_HERE,
{base::TaskPriority::BEST_EFFORT, base::MayBlock(),
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(DeleteChannelIDFiles, base::FilePath(channel_id_path)));
return network_context_params;
}
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
base::FilePath user_data_dir_;
NetworkContextParamsFactory network_context_params_factory_;
network::mojom::NetworkContextPtr network_context_;
network::mojom::URLLoaderFactoryPtr url_loader_factory_;
scoped_refptr<InternalState> internal_state_;
DISALLOW_COPY_AND_ASSIGN(SharedURLLoaderFactory);
};
SafeBrowsingNetworkContext::SafeBrowsingNetworkContext(
scoped_refptr<net::URLRequestContextGetter> request_context_getter,
const base::FilePath& user_data_dir,
NetworkContextParamsFactory network_context_params_factory) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
url_loader_factory_ = base::MakeRefCounted<SharedURLLoaderFactory>(
request_context_getter, user_data_dir,
std::move(network_context_params_factory));
}
SafeBrowsingNetworkContext::~SafeBrowsingNetworkContext() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
}
scoped_refptr<network::SharedURLLoaderFactory>
SafeBrowsingNetworkContext::GetURLLoaderFactory() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
return url_loader_factory_;
}
network::mojom::NetworkContext*
SafeBrowsingNetworkContext::GetNetworkContext() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
return url_loader_factory_->GetNetworkContext();
}
void SafeBrowsingNetworkContext::FlushForTesting() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
url_loader_factory_->FlushForTesting();
}
void SafeBrowsingNetworkContext::ServiceShuttingDown() {
url_loader_factory_->Reset();
}
} // namespace safe_browsing