Chrome内核中NET_EXPORT_PRIVATE Delegate 作用及实现方式解析(源码见附件)
在 HttpStreamFactory::Job 类中,Delegate 是一个抽象接口(Delegate 类),用于处理 Job 执行过程中发生的各种事件,例如:
- 连接成功,流已准备好。
- 连接失败,发生错误。
- 代理需要身份验证。
- SSL 证书错误。
这个 Delegate 设计模式的核心思想是回调机制,让 Job 运行时能够异步通知外部调用方(通常是 HttpStreamFactory),从而解耦 Job 的执行逻辑和外部的控制逻辑。
1. NET_EXPORT_PRIVATE Delegate 的作用
NET_EXPORT_PRIVATE 是用于符号导出的宏,保证 Delegate 这个类在动态链接库(DLL)或者共享库中能够被外部使用。
class NET_EXPORT_PRIVATE Delegate { public: virtual void OnStreamReady(const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, std::unique_ptr<HttpStream> stream) = 0; virtual void OnBidirectionalStreamImplReady( const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, std::unique_ptr<BidirectionalStreamImpl> stream) = 0; virtual void OnWebSocketHandshakeStreamReady( const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, std::unique_ptr<WebSocketHandshakeStream> stream) = 0; virtual void OnStreamFailed(int result, const NetErrorDetails& net_error_details, int resolve_error_info, const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info) = 0; virtual void OnNeedsProxyAuth( const HttpResponseInfo& proxy_response, HttpAuthController* auth_controller) = 0; virtual void OnNeedsClientAuth(const SSLInfo& ssl_info) = 0; virtual void OnHttpsProxyTunnelResponseRedirect( const HttpResponseInfo& response_info, std::unique_ptr<HttpStream> stream) = 0; protected: virtual ~Delegate() = default; };
2. 设计思想
Delegate 采用的是回调接口模式(Callback Interface Pattern),即:
Job在执行过程中,遇到关键事件时,调用Delegate的方法,将事件通知给HttpStreamFactory(或其他Delegate实现)。Job本身不需要知道具体的处理逻辑,而是由Delegate实现类(通常是HttpStreamFactoryImpl)决定如何处理这些事件。
这种设计模式的主要思想是解耦:
Job只负责建立 HTTP 连接,并通知Delegate结果,而不用关心调用方是谁或如何处理连接。HttpStreamFactory通过实现Delegate,接收Job的事件,并采取相应的操作(如创建HttpStream,处理认证,或者重试连接)。
3. 运行机制
整个流程如下:
HttpStreamFactoryImpl创建Job对象,并将自身作为Delegate传递:auto job = std::make_unique<HttpStreamFactory::Job>(/* 传递 this 作为 Delegate */);Job运行过程中,遇到某些事件时,调用Delegate方法:delegate_->OnStreamReady(used_ssl_config, used_proxy_info, std::move(stream));HttpStreamFactoryImpl作为Delegate实现类,定义如何处理这些回调:void HttpStreamFactoryImpl::OnStreamReady(const SSLConfig& used_ssl_config, const ProxyInfo& used_proxy_info, std::unique_ptr<HttpStream> stream) { // 处理已建立的流,例如通知请求者 }
4. Delegate 回调的具体情况
(1) 成功创建 HTTP 连接
Job创建HttpStream后,调用:delegate_->OnStreamReady(used_ssl_config, used_proxy_info, std::move(stream));HttpStreamFactoryImpl处理此回调,向上层应用提供 HTTP 流。
(2) 连接失败
Job连接失败时,调用:delegate_->OnStreamFailed(error_code, net_error_details, resolve_error_info, used_ssl_config, used_proxy_info);HttpStreamFactoryImpl处理失败情况,可能重试或通知应用层失败。
(3) 需要代理身份验证
- 如果代理需要身份验证,
Job调用:delegate_->OnNeedsProxyAuth(proxy_response, auth_controller); HttpStreamFactoryImpl可能会请求用户输入凭据。
(4) 需要客户端证书
- 若服务器要求客户端提供 SSL 证书,调用:
delegate_->OnNeedsClientAuth(ssl_info); HttpStreamFactoryImpl处理客户端证书选择逻辑。
5. 这种实现方式的优点
1. 解耦(Decoupling):职责单一,代码更清晰
如果直接在 Job 里处理连接成功、失败、代理认证等逻辑,那么 Job 需要:
- 负责连接建立。
- 处理 HTTP/HTTPS/WebSocket 连接逻辑。
- 处理代理认证。
- 处理 SSL 证书问题。
- 处理连接失败重试策略。
这样会导致 Job 变得复杂且难以维护。
使用 Delegate 方式,把 Job 的职责限制在: ✅ 只负责执行网络连接任务,并通知 Delegate。
❌ 不负责决定如何处理连接结果(这个交由 Delegate 处理)。
2. 代码可复用(Reusability):支持多种 Delegate 实现
Delegate 只是一组接口,可以有不同的实现,例如:
- 标准 HTTP 连接(
HttpStreamFactoryImpl实现Delegate) - WebSocket 连接(
WebSocketStreamFactory也可以实现Delegate) - 双向流(
BidirectionalStreamFactory也可以实现Delegate)
这样,同一个 Job 逻辑可以被不同类型的 Delegate 复用,而不需要为每种 HTTP 连接类型都重新写一套 Job 逻辑。
示例: 如果直接在 Job 里处理 WebSocket 连接,则:if (is_websocket) { // WebSocket 处理逻辑 } else { // 普通 HTTP 处理逻辑 }
这样 Job 代码会越来越复杂。使用 Delegate,不同类型的 Delegate 处理不同情况,Job 代码保持精简:delegate_->OnWebSocketHandshakeStreamReady(...);
3. 便于扩展(Extensibility):新增功能更简单
假设未来需要增加一个新的功能,比如HTTP/3 支持:
- 如果
Job直接处理,就需要修改Job代码,增加大量if-else逻辑。 - 如果使用
Delegate,只需要创建一个新的Delegate实现,比如Http3StreamFactoryImpl,而不需要修改Job。
这样能避免修改已有代码,减少风险(符合**“开闭原则”**:对扩展开放,对修改封闭)。
4. 便于测试(Testability):可以Mock Delegate
在测试 Job 时,可以使用一个Mock Delegate,让 Job 只负责执行 HTTP 连接任务,而 Mock Delegate 负责检查回调是否正确触发。
示例:
class MockDelegate : public HttpStreamFactory::Job::Delegate { public: MOCK_METHOD(void, OnStreamReady, (const SSLConfig&, const ProxyInfo&, std::unique_ptr<HttpStream>), (override)); MOCK_METHOD(void, OnStreamFailed, (int, const NetErrorDetails&, int, const SSLConfig&, const ProxyInfo&), (override)); };
这样可以单独测试 Job 的逻辑,而不需要依赖 HttpStreamFactoryImpl,提高单元测试的独立性。
5. 适用于异步回调(Asynchronous Callbacks)
网络请求通常是异步的(不会立即返回结果),而 Delegate 方式支持:
Job运行时不需要等待,而是在连接完成后回调Delegate。HttpStreamFactoryImpl通过Delegate方式接收结果,而不影响Job的执行。
这比直接在 Job 内部阻塞等待(同步处理)更高效,适用于大规模并发 HTTP 连接管理。
6. 支持多线程(Thread Safety)
如果 HttpStreamFactoryImpl 运行在不同的线程,使用 Delegate 让 Job 运行在一个线程,而 HttpStreamFactoryImpl 运行在另一个线程,并通过异步回调传递数据,避免多线程竞争问题。
示例:
// Job 运行在 IO 线程 job->Start(); // 连接完成后,回调 Delegate,通知主线程 delegate_->OnStreamReady(...);
而如果直接在 Job 里处理,就需要额外的线程同步机制,增加代码复杂度。
结论
| 方式 | Delegate 方式 | 直接在 Job 内部处理 |
|---|---|---|
| 耦合度 | 低(解耦 Job 和外部处理逻辑) | 高(Job 既负责连接,又处理各种事件) |
| 代码复用 | 高(不同 Delegate 处理不同逻辑) | 低(所有逻辑都写死在 Job 里) |
| 扩展性 | 好(新增 Delegate 实现即可) | 差(需要修改 Job 代码) |
| 可测试性 | 好(可以 Mock Delegate 进行单测) | 差(难以单独测试 Job) |
| 适用于异步 | 是(回调机制,适用于非阻塞 IO) | 否(可能需要同步等待) |
| 多线程支持 | 好(可以异步通知 Delegate 处理) | 难(需要额外的线程同步机制) |
综合来看,使用 Delegate 的方式更适合大规模、高并发、可扩展的 HTTP 连接管理,而直接在 Job 里处理虽然简单,但会导致代码复杂度增加、复用性降低,不适用于长期维护的项目。
6. 其他类似的设计模式
-
观察者模式(Observer Pattern):
- 观察者监听
Job状态变化,Job在事件发生时通知所有观察者。 Delegate方式可以看作一种简化的观察者模式。
- 观察者监听
-
策略模式(Strategy Pattern):
Delegate也类似策略模式,Job调用Delegate但不关心其具体实现,允许不同策略处理 HTTP 连接。
7. 总结
NET_EXPORT_PRIVATE Delegate作用:
提供Job事件通知机制,使HttpStreamFactory能异步处理流的创建、失败、认证等情况。- 实现方式:
采用回调接口模式(Callback Interface Pattern),解耦Job和HttpStreamFactoryImpl。 - 核心机制:
Job只负责连接建立,Delegate负责处理业务逻辑。- 通过虚函数(纯虚方法
= 0),让Job仅需知道Delegate接口,而不关心具体实现。 - 运行时,
HttpStreamFactoryImpl通过实现Delegate来处理 HTTP 连接结果。
- 优点:
- 解耦、低耦合、异步回调、提高代码复用性。
- 适用于高并发 HTTP 连接管理。
这种模式是网络编程中非常常见的设计,可以适用于 HTTP 连接池、WebSocket 连接管理等场景。
1273

被折叠的 条评论
为什么被折叠?



