blob: 180fa7de86b20084cd419f22e77af3ac7e369911 [file] [log] [blame]
// Copyright 2014 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/net/chrome_url_request_context_getter.h"
#include <utility>
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_io_data.h"
#include "chrome/browser/profiles/storage_partition_descriptor.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
using content::BrowserThread;
class ChromeURLRequestContextFactory {
public:
ChromeURLRequestContextFactory() {}
virtual ~ChromeURLRequestContextFactory() {}
// Called to create a new instance (will only be called once).
virtual net::URLRequestContext* Create() = 0;
protected:
DISALLOW_COPY_AND_ASSIGN(ChromeURLRequestContextFactory);
};
namespace {
// ----------------------------------------------------------------------------
// Helper factories
// ----------------------------------------------------------------------------
// Factory that creates the main URLRequestContext.
class FactoryForMain : public ChromeURLRequestContextFactory {
public:
FactoryForMain(
const ProfileIOData* profile_io_data,
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector request_interceptors)
: profile_io_data_(profile_io_data),
request_interceptors_(std::move(request_interceptors)) {
std::swap(protocol_handlers_, *protocol_handlers);
}
net::URLRequestContext* Create() override {
profile_io_data_->Init(&protocol_handlers_,
std::move(request_interceptors_));
return profile_io_data_->GetMainRequestContext();
}
private:
const ProfileIOData* const profile_io_data_;
content::ProtocolHandlerMap protocol_handlers_;
content::URLRequestInterceptorScopedVector request_interceptors_;
};
// Factory that creates the URLRequestContext for a given isolated app.
class FactoryForIsolatedApp : public ChromeURLRequestContextFactory {
public:
FactoryForIsolatedApp(
const ProfileIOData* profile_io_data,
const StoragePartitionDescriptor& partition_descriptor,
std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
protocol_handler_interceptor,
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector request_interceptors,
network::mojom::NetworkContextRequest network_context_request,
network::mojom::NetworkContextParamsPtr network_context_params)
: profile_io_data_(profile_io_data),
partition_descriptor_(partition_descriptor),
io_thread_(g_browser_process->io_thread()),
protocol_handler_interceptor_(std::move(protocol_handler_interceptor)),
request_interceptors_(std::move(request_interceptors)),
network_context_request_(std::move(network_context_request)),
network_context_params_(std::move(network_context_params)) {
std::swap(protocol_handlers_, *protocol_handlers);
}
net::URLRequestContext* Create() override {
// We will copy most of the state from the main request context.
//
// Note that this factory is one-shot. After Create() is called once, the
// factory is actually destroyed. Thus it is safe to destructively pass
// state onwards.
return profile_io_data_->GetIsolatedAppRequestContext(
io_thread_, partition_descriptor_,
std::move(protocol_handler_interceptor_), &protocol_handlers_,
std::move(request_interceptors_), std::move(network_context_request_),
std::move(network_context_params_));
}
private:
const ProfileIOData* const profile_io_data_;
const StoragePartitionDescriptor partition_descriptor_;
IOThread* io_thread_;
std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
protocol_handler_interceptor_;
content::ProtocolHandlerMap protocol_handlers_;
content::URLRequestInterceptorScopedVector request_interceptors_;
network::mojom::NetworkContextRequest network_context_request_;
network::mojom::NetworkContextParamsPtr network_context_params_;
};
// Factory that creates the media URLRequestContext for a given isolated
// app. The media context is based on the corresponding isolated app's context.
class FactoryForIsolatedMedia : public ChromeURLRequestContextFactory {
public:
FactoryForIsolatedMedia(
const ProfileIOData* profile_io_data,
const StoragePartitionDescriptor& partition_descriptor,
ChromeURLRequestContextGetter* app_context)
: profile_io_data_(profile_io_data),
partition_descriptor_(partition_descriptor),
app_context_getter_(app_context) {}
net::URLRequestContext* Create() override {
// We will copy most of the state from the corresopnding app's
// request context. We expect to have the same lifetime as
// the associated |app_context_getter_| so we can just reuse
// all its backing objects, including the
// |protocol_handler_interceptor|. This is why the API
// looks different from FactoryForIsolatedApp's.
return profile_io_data_->GetIsolatedMediaRequestContext(
app_context_getter_->GetURLRequestContext(), partition_descriptor_);
}
private:
const ProfileIOData* const profile_io_data_;
const StoragePartitionDescriptor partition_descriptor_;
scoped_refptr<ChromeURLRequestContextGetter> app_context_getter_;
};
// Factory that creates the URLRequestContext for media.
class FactoryForMedia : public ChromeURLRequestContextFactory {
public:
explicit FactoryForMedia(const ProfileIOData* profile_io_data)
: profile_io_data_(profile_io_data) {
}
net::URLRequestContext* Create() override {
return profile_io_data_->GetMediaRequestContext();
}
private:
const ProfileIOData* const profile_io_data_;
};
} // namespace
// ----------------------------------------------------------------------------
// ChromeURLRequestContextGetter
// ----------------------------------------------------------------------------
ChromeURLRequestContextGetter::ChromeURLRequestContextGetter()
: url_request_context_(nullptr) {}
ChromeURLRequestContextGetter::~ChromeURLRequestContextGetter() {
// NotifyContextShuttingDown() must have been called.
DCHECK(!url_request_context_);
}
scoped_refptr<ChromeURLRequestContextGetter>
ChromeURLRequestContextGetter::CreateAndInit(
std::unique_ptr<ChromeURLRequestContextFactory> factory) {
scoped_refptr<ChromeURLRequestContextGetter> url_request_context_getter(
new ChromeURLRequestContextGetter());
// This can't be done in the constructor because it's possible for the task to
// run and complete before the constructor returns, which would reduce the
// reference count from 1 to 0 on completion, and delete the object
// immediately.
base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&ChromeURLRequestContextGetter::Init,
url_request_context_getter,
base::Passed(std::move(factory))));
return url_request_context_getter;
}
void ChromeURLRequestContextGetter::Init(
std::unique_ptr<ChromeURLRequestContextFactory> factory) {
DCHECK(factory);
DCHECK(!url_request_context_);
url_request_context_ = factory->Create();
}
// Lazily create a URLRequestContext using our factory.
net::URLRequestContext*
ChromeURLRequestContextGetter::GetURLRequestContext() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return url_request_context_;
}
void ChromeURLRequestContextGetter::NotifyContextShuttingDown() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
url_request_context_ = nullptr;
URLRequestContextGetter::NotifyContextShuttingDown();
}
scoped_refptr<base::SingleThreadTaskRunner>
ChromeURLRequestContextGetter::GetNetworkTaskRunner() const {
return base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
}
// static
scoped_refptr<ChromeURLRequestContextGetter>
ChromeURLRequestContextGetter::Create(
Profile* profile,
const ProfileIOData* profile_io_data,
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector request_interceptors) {
return ChromeURLRequestContextGetter::CreateAndInit(
std::make_unique<FactoryForMain>(profile_io_data, protocol_handlers,
std::move(request_interceptors)));
}
// static
scoped_refptr<ChromeURLRequestContextGetter>
ChromeURLRequestContextGetter::CreateForMedia(
Profile* profile,
const ProfileIOData* profile_io_data) {
return ChromeURLRequestContextGetter::CreateAndInit(
std::make_unique<FactoryForMedia>(profile_io_data));
}
// static
scoped_refptr<ChromeURLRequestContextGetter>
ChromeURLRequestContextGetter::CreateForIsolatedApp(
Profile* profile,
const ProfileIOData* profile_io_data,
const StoragePartitionDescriptor& partition_descriptor,
std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
protocol_handler_interceptor,
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector request_interceptors,
network::mojom::NetworkContextRequest network_context_request,
network::mojom::NetworkContextParamsPtr network_context_params) {
return ChromeURLRequestContextGetter::CreateAndInit(
std::make_unique<FactoryForIsolatedApp>(
profile_io_data, partition_descriptor,
std::move(protocol_handler_interceptor), protocol_handlers,
std::move(request_interceptors), std::move(network_context_request),
std::move(network_context_params)));
}
// static
scoped_refptr<ChromeURLRequestContextGetter>
ChromeURLRequestContextGetter::CreateForIsolatedMedia(
Profile* profile,
ChromeURLRequestContextGetter* app_context,
const ProfileIOData* profile_io_data,
const StoragePartitionDescriptor& partition_descriptor) {
return ChromeURLRequestContextGetter::CreateAndInit(
std::make_unique<FactoryForIsolatedMedia>(
profile_io_data, partition_descriptor, app_context));
}