Chromium 网络栈之初始化 URLRequestContext
发布于 2021-11-02
URLRequestContext
里面是网络栈的各种上下文信息,包含了各种网络栈涉及到的网络组件指针。
创建 URLRequestContext
scoped_refptr<base::SingleThreadTaskRunner> g_main_task_runner;
base::Closure g_main_quit_closure;
std::unique_ptr<base::Thread> g_network_thread;
std::unique_ptr<net::URLRequestContext> g_url_request_context;
void ShutdownOnMainThread() {
if (g_main_quit_closure) {
g_main_quit_closure.Run();
}
}
void ShutdownUrlRequestContextOnNetworkThread() {
g_url_request_context.reset();
g_main_task_runner->PostTask(FROM_HERE, base::BindOnce(ShutdownOnMainThread));
}
void InitUrlRequestContextOnNetworkThread() {
net::URLRequestContextBuilder context_builder;
g_url_request_context = context_builder.Build();
g_network_thread->task_runner()->PostDelayedTask(
FROM_HERE, base::BindOnce(ShutdownUrlRequestContextOnNetworkThread),
base::TimeDelta::FromSeconds(1));
}
int main(int argc, char* argv[]) {
base::AtExitManager exit_manager;
base::CommandLine::Init(0, 0);
logging::LoggingSettings settings;
settings.logging_dest = logging::LOG_TO_ALL;
settings.delete_old = logging::DELETE_OLD_LOG_FILE;
settings.log_file = L"learn_chromium_net_exe.log";
logging::InitLogging(settings);
base::ThreadPool::CreateAndStartWithDefaultParams("net");
base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
base::RunLoop run_loop;
g_main_quit_closure = run_loop.QuitClosure();
g_main_task_runner = message_loop.task_runner();
g_network_thread = std::make_unique<base::Thread>("network");
base::Thread::Options options;
options.message_loop_type = base::MessageLoop::TYPE_IO;
g_network_thread->StartWithOptions(options);
g_network_thread->task_runner()->PostTask(
FROM_HERE, base::BindOnce(InitUrlRequestContextOnNetworkThread));
run_loop.Run();
g_network_thread.reset();
g_main_task_runner = nullptr;
return 0;
}
URLRequestContext
需要运行在专有的网络线程里。因此我们创建一个类型为TYPE_IO
的 network 线程。
URLRequestContext
类里面的逻辑比较简单,它通过成员变量存放各种网络组件的指针。但是成员变量比较多,创建初始化比较复杂,因此我们通常借助URLRequestContextBuilder
类来创建URLRequestContext
。通过URLRequestContextBuilder
的接口可以配置URLRequestContext
所需要的网络组件。在InitUrlRequestContextOnNetworkThread
函数里,即使我们没有创建任何网络组件传递给URLRequestContextBuilder
,但是在URLRequestContextBuilder::Build
里面,它也会自动创建一些基础的网络组件,比如BasicNetworkDelegate
,让网络栈可以正常的运作起来。
对象生命周期的管理
URLRequestContext
仅仅是存放了各种网络组件的指针,并没有管理网络组件的生命周期。理论上一个网络组件可以在多个URLRequestContext
共享使用。
实际的情况是URLRequestContextBuilder
在URLRequestContextBuilder::Build
里面创建的是URLRequestContext
的子类ContainerURLRequestContext
。ContainerURLRequestContext
它通过成员变量URLRequestContextStorage
来管理大部分网络组件的生命周期。如下图所示:
Chromium 中的 URLRequestContext
在 Chromium 70 左右的版本,网络栈是运行在 browser 进程的。后来通过 Mojo 把网络能力改造成Network Service ,网络栈就运行在 Network Service 的 Utility 进程里。
整个网络栈被封装成NetworkService
提供给其他浏览器进程使用。NetworkContext
负责创建管理URLRequestContext
。
Chromium browser进程会创建多个NetworkContext
:
- SystemNetworkContextManager,用于跟某个 profile 无关的网络。它没有磁盘存储,因此每次 browser 进程退出之后丢弃所有的 cookie、cache等状态信息。
- 每个 profile 会创建一个专用
NetworkContext
,甚至包括隐身模式的 incognito profile 。 - 每个 app 都有自己专用的
NetworkContext