作者:Ken Rockot(技术团队成员),Ben Goodger(ChatGPT Atlas 工程主管)
原文链接:How we built OWL,the new architecture behind our ChatGPT-based browser,Atlas

上周,我们发布了 ChatGPT Atlas,这是一种全新的方式,让 ChatGPT 能够陪伴你浏览互联网。Atlas 不仅是一个功能强大的浏览器,更为大家描绘了未来的场景:在整个互联网世界中随时随地携带 ChatGPT,随时提问、获取建议、完成任务。在本文中,我们将深入介绍这个产品在工程方面的最大挑战之一:我们是如何让 ChatGPT 成为一个能随着使用不断进化的浏览器的。

要让 ChatGPT 真正成为浏览互联网的“副驾驶”,我们需要重新设计浏览器的整体架构,实现 Atlas 与 Chromium 运行时的分离。为此,我们开发了一种全新的集成 Chromium 的方式,以满足我们的产品目标——实现秒速启动,哪怕打开更多标签页依旧保持流畅响应,同时为智能体的应用场景打下坚实基础。

奠定基础

如何构建 OWL——ChatGPT 浏览器 Atlas 背后的新架构

Chromium 是天然的构建模块。它拥有先进的网络引擎,强大的安全模型,性能表现经过验证,网络兼容性无与伦比。此外,还有全球开发者社区持续改进它。因此,它成为现代桌面浏览器的首选基础。

重新思考浏览器体验

我们才华横溢的设计团队对用户体验设定了雄心勃勃的目标,例如为智能体模式等功能打造丰富的动画和视觉效果。为实现这些目标,我们的工程团队选择了最现代的原生框架(如 SwiftUI、AppKit 和 Metal)来构建 UI,而不是简单地为开源 Chromium 界面“换皮”。因此,Atlas 的 UI 实际上是对整个应用用户体验的彻底重塑。

我们还设定了其他目标,比如应用启动要足够快、能够支持上百个标签页而不会影响性能。但这些目标很难通过原生 Chromium 实现,因为 Chromium 在启动流程、线程模型、标签页模型等方面有既定的实现方式。我们曾考虑过对其进行大幅调整,但为了方便快速集成上游新版本,我们希望尽量减少对 Chromium 的补丁。为了加快开发速度,我们必须探索一种全新的集成和驱动 Chromium 的方式。

我们在技术上的投入不仅要加快实验、迭代和新功能的交付,还要保持 OpenAI 工程文化的核心——即“第一天就能交付”。每位新工程师在入职第一天下午都会提交并合并一个小改动。我们需要确保即便 Chromium 检出和编译需要数小时,新成员依然能做到这一点。

我们的解决方案:OWL

为应对这些挑战,我们构建了一个全新的架构层,称为 OWL:OpenAI 的 Web 层。OWL 实现了我们对 Chromium 的集成,也就是说,Chromium 的浏览器进程运行在 Atlas 主应用进程之外。

如何构建 OWL——ChatGPT 浏览器 Atlas 背后的新架构

可以这样理解:Chromium 通过将标签页独立为多个进程,彻底改变了浏览器架构。而我们更进一步,把 Chromium 本身也从主应用进程中剥离出来,放入一个独立的服务层。这种架构带来了许多好处:

  • 更简洁、更现代的应用:Atlas 几乎全部用 SwiftUI 和 AppKit 构建,统一语言、统一技术栈、代码库更干净。
  • 启动更快:Chromium 在后台异步启动,Atlas 无需等待,几乎能瞬间显示界面。
  • 更好地隔离卡顿和崩溃:Chromium 是功能强大的网络引擎,但即使它主线程挂起或崩溃,Atlas 也能继续运行。
  • 更少的合并麻烦:由于我们没有在 Chromium 的开源 UI 上堆叠大量代码,与上游保持同步更容易,维护成本更低。
  • 更高的迭代效率:大多数工程师无需在本地编译 Chromium,OWL 以预构建二进制形式在内部发布,Atlas 的构建仅需几分钟而非数小时。

由于大多数团队成员无需频繁从源码构建 Chromium,开发节奏大大加快。即便是新成员,也能在入职第一天下午合并简单的更改。

OWL 的工作原理

从高层来看,Atlas 浏览器是 OWL 客户端,而 Chromium 浏览器进程则是 OWL 主机。它们之间通过 IPC 通信,具体来说是采用 Chromium 自己的 Mojo 消息传递系统。我们为 Mojo 编写了专用的 Swift(甚至 TypeScript)绑定,这样 Swift 应用就能直接调用主机端接口。

OWL 客户端库对外暴露了简洁的 Swift API,抽象了主机服务层公开的几个重要概念:

  • 会话(Session):用于全局配置和控制主机
  • 配置文件(Profile):管理各用户配置的浏览器状态
  • WebView:用于控制和嵌入单独的网页内容(如渲染、输入、导航、缩放等)
  • WebContentRenderer:把输入事件转发给 Chromium 的渲染管线,并接收渲染器的反馈
  • LayerHost/Client:在 UI 与 Chromium 之间交换合成信息

如何构建 OWL——ChatGPT 浏览器 Atlas 背后的新架构

此外,还有一系列服务端点用于管理书签、下载、扩展程序和自动填充等高级功能。

渲染:跨进程边界传递像素

WebView 在客户端应用中共享一个显示空间,并在共享的合成容器中切换。例如,浏览器窗口通常只有一个可见的共享容器,切换标签时会把所选标签的 WebView 交换进来。在 Chromium 端,这个容器对应一个 gfx::AcceleratedWidget,最终由 CALayer 支持。我们将该层的上下文 ID 暴露给客户端,NSView 则通过私有的 CALayerHost API 嵌入该层。

对于像下拉菜单或颜色选择器这样的特殊情况,Chromium 会在单独的弹出窗口中渲染,采用同样的方式。这类弹窗没有 content::WebContents,但有各自的 content::RenderWidgetHostView 和 gfx::AcceleratedWidget,因此也适用同样的委托渲染模式。

OWL 会在内部实时同步视图几何信息到 Chromium 端,这样 GPU 合成器就能动态更新并始终输出正确大小和 DPI 的图层内容。

我们还借助这种机制,将 Chromium 的原生 Views UI 元素按需投射到 Atlas(例如权限提示等功能,无需在 SwiftUI 里重写)。这一技术受益于 Chromium 现有的 macOS 可安装 Web 应用基础设施。

输入事件:转换与转发

在 Chromium 的 UI 里,平台事件(如 macOS 的 NSEvents)会先被转换为 Blink 的 WebInputEvent 模型,然后再转发到渲染器。但由于 OWL 在隐藏进程中运行 Chromium,我们需要在 Swift 客户端库内自行将事件转换后,再转发给 Chromium。

在此之后,事件会进入网络内容常规的输入事件生命周期。如果页面没有处理事件,会把事件返回给客户端。此时我们会重新合成一个 NSEvent,让应用的其他部分有机会处理这些输入。

智能体模式:特殊场景

Atlas 的智能体浏览功能,对渲染、输入事件转发和数据存储等方面都提出了独特挑战。

我们的计算机模型需要整个屏幕的单一图像作为输入。但有些 UI 元素(如下拉菜单)会在与标签页分离的窗口渲染。因此在智能体模式下,我们会把这些弹窗合成回主页面图像的正确位置,确保模型一帧就能看到完整上下文。

对于输入事件,我们也遵循同样原则:智能体生成的事件会直接路由到渲染器,不会经过特权浏览器层。即使在自动控制模式下,这也能保持沙箱隔离。例如,我们不会允许合成的事件触发全局快捷键,避免浏览器执行与内容无关的操作。

智能体浏览还支持临时“未登录”上下文。我们不会直接复用用户的无痕配置文件(以防信息泄露),而是通过 Chromium 的 StoragePartition 基础设施,动态创建隔离的内存存储。每次智能体会话都是全新开始,结束后所有 Cookie 和站点数据都会被清除。你可以同时运行多个“未登录”会话,彼此完全隔离,分别在不同标签页中独立工作。

开启网络新体验

没有全球 Chromium 社区对现代网络基础设施的卓越贡献,就不会有今天的一切。OWL 以全新方式建立在这一基础之上:将引擎与应用解耦,把世界一流的网络平台与现代原生框架结合起来,带来更快、更灵活的架构。

通过重新思考浏览器与 Chromium 的关系,我们为新体验创造了空间:更快速的启动、更丰富的 UI、更紧密与操作系统集成,以及更高效的开发循环。如果你对这些挑战感兴趣,欢迎查看我们的招聘信息,加入我们成为 Atlas 软件工程师、iOS 工程师等。