作者:Ken Rockot (技術人員) 和 Ben Goodger (ChatGPT Atlas 工程主管)
我們上週推出 ChatGPT Atlas,這是一種由 ChatGPT 全程伴隨的全新網頁瀏覽方式。Atlas 除了是一款功能齊全的網頁瀏覽器之外,也能讓人一探未來究竟:一個你可以隨時隨地透過網際網路使用 ChatGPT 來為你提問、提出建議並完成任務的世界。在本文中,我們將深入剖析產品中極其複雜的一個工程層面:我們如何將 ChatGPT 變成一款越用越好用的瀏覽器。
要讓 ChatGPT 真正為你所用,成為翱翔網路的副手,就需要重新構想瀏覽器的整個架構:將 Atlas 與 Chromium 執行時間彼此分開。這表示我們需要開發一種新的 Chromium 整合方式,以實現我們的產品目標:即時啟動,即使開啟很多分頁也能迅速回應,並為自主代理用例奠定穩固的基礎。

Chromium 是一種天然的建構模塊。這種最先進的網路引擎具備強大的安全性模型、成熟的效能憑證和無與倫比的網路相容性。而且還是由全球社區共同開發並且持續改進的。它是一種十分常見的現代桌面網頁瀏覽器選擇。
我們才華橫溢的設計團隊為使用者體驗設定了雄心勃勃的目標,包括為「自主代理模式」等功能增添豐富的動畫和視覺效果。這就需要我們的工程團隊利用最先進的原生架構 (SwiftUI、AppKit 和 Metal)來建立使用者介面,而不是簡單地重新設計開放原始碼的 Chromium 使用者體驗介面。因此,Atlas 的使用者介面無疑是全面重建整個應用程式使用者體驗。
我們還有其他目標,例如快速啟動時間和支援數百個瀏覽分頁而分毫不影響效能。使用現成的 Chromium 預設設定很難實現這些目標,因為 Chromium 對啟動順序、執行緒模型和分頁模型等許多細節都有自己的看法。我們曾考慮在此做出重大改變,但我們希望保持針對 Chromium 修補程式集的明確目標,以便能夠快速整合新版本。為了確保最充分地提升我們的開發速度,我們需要想出另一種方法來整合與驅動 Chromium 執行時間。
我們技術投資的試金石不僅在於它能否加快新功能的實驗、迭代和交付速度,還在於它能否讓我們保持 OpenAI 工程文化的核心部分:首日交付。新的工程師每個人都在第一天下午做點小變更再併入程式碼中。我們需要確保即使 Chromium 需要幾個小時才能完成檢查和建構,也能辦得到這一點。
我們應對這些挑戰的方法是建構一個新的架構層,我們把它稱為 OWL:OpenAI 的智慧疊加層。OWL 是我們對 Chromium 的整合,意味著在 Atlas 主應用程式流程之外執行 Chromium 的瀏覽器流程。
你可以這樣理解:Chromium 將分頁移至分開的流程中而徹底改變了瀏覽器。我們進一步延伸這個想法,將 Chromium 本身從主應用程式流程中移除,然後放到一個獨立的服務層。這個轉變可以產生一連串的好處:
- 一款更簡潔、更現代化的應用程式:Atlas 幾乎完全是用 SwiftUI 和 AppKit 建立。只有一種語言,一套技術堆疊,一套簡潔的程式碼庫,乾淨俐落。
- 啟動速度更快:Chromium 在背景中非同步啟動。Atlas 不知等待為何物——像素幾乎瞬間就能呈現在螢幕上。
- 避免卡頓和當機:Chromium 是一款功能強大且複雜的網路引擎。即使主執行緒故障,Atlas 也絲毫不受影響。即使系統當機,Atlas 也能繼續運作。
- 減少合併難題:由於沒有大量使用 Chromium 開放原始碼使用者介面,因此我們與上游 Chromium 的差異要小得多,也更容易維護。
- 迭代速度更快:大多數工程師不需要本機組建 Chromium。OWL 在內部以預編譯二進位檔案的形式發佈,因此只需要幾分鐘而非幾個小時即可組建 Atlas。
由於團隊的大多數工程師不會經常從原始程式碼組建 Chromium,因此開發速度要快得多——即使是新團隊成員也可以在第一天下午就合併簡單的變更。
從較高層面來看,Atlas 瀏覽器是 OWL 用戶端,而 Chromium 瀏覽器流程則是 OWL 主機。兩者透過 IPC 通訊,具體而言是 Mojo(在新視窗中開啟),即 Chromium 自己的訊息傳遞系統。我們為 Mojo 編寫自訂 Swift (甚至是 TypeScript) 繫結功能,這樣我們的 Swift 應用程式就可以直接呼叫主機端介面。
OWL 用戶端程式庫公開一個簡單的公共 Swift API,其中概括主機服務層公開的幾個關鍵概念:
- 工作階段:全域設定與控制主機
- 設定檔:管理特定使用者設定檔的瀏覽器狀態
- WebView:控制和嵌入單一網頁內容 (例如:呈現、輸入、導航、縮放等)
- WebContentRenderer:將輸入事件轉遞到 Chromium 的呈現管道,並接收來自轉譯器的回饋。
- LayerHost/用戶端:在使用者介面和 Chromium 之間交換組合資訊
此外,還有用於管理書籤、下載、擴充功能和自動填充等高級功能的各種服務端點。
在用戶端應用程式中共用互斥展示空間的 WebView 會輪換進出一個共用的組合容器。例如,瀏覽器視窗通常只有一個可見的共用容器,選擇分頁欄中的分頁會將那個分頁的 WebView 切換到容器中。在 Chromium 端,這個容器對應於 gfx::AcceleratedWidget,而它最終又是由 CALayer 支援。我們將該層的情境 ID 透露給客戶端,其中的 NSView 使用私有 CALayerHost API 將其嵌入。
對於 Chromium 在分開的彈出視窗小工具中呈現的 下拉式功能表或色彩挑選器等特殊情況,也採用相同的方法。雖然沒有 content::WebContents,但它們有 content::RenderWidgetHostView 和它們自己的 gfx::AcceleratedWidget,因此適用相同的委託呈現模型。OWL 內部保持視圖幾何體與 Chromium 端同步,這樣一來,GPU 合成器就可以相應地更新,並且總是產生大小和裝置比例正確的圖層內容。我們也重複使用這項技術來將 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 以一種全新的方式構建在這個基礎上:將引擎與應用程式解耦,將世界一流的 Web 平台與現代化原生架構互相結合,因而解鎖更快、更靈活的架構。
我們正在藉由重新思考瀏覽器如何容納 Chromium,為新型體驗創造空間:更順暢的啟動流程、更豐富的使用者介面、與作業系統其他部分更緊密的整合以及以創意速度推進的開發循環。如果您認為這正是您所需的挑戰,請查看我們目前在 Atlas 專案中招聘的軟體工程師、Atlas 、軟體工程師、iOS 開發人員等職缺。
請造訪 chatgpt.com/atlas(在新視窗中開啟) 體驗 Atlas。


