在浏览器发展的历史长河中,插件曾经是网页功能扩展的重要手段,从早期的 NPAPI,到后来的 PPAPI,再到现代的 Extension 和 Mojo,浏览器生态经历了翻天覆地的变化。而 Google Chromium 坚决取消插件支持的决策,并非出于一时偏好,而是从安全、性能、跨平台、开发复杂度等多维度权衡的必然结果。本篇文章将从技术角度深入解析 Chromium 插件的演进历程、架构设计、源码实现细节及工程实践经验,带你进入浏览器内核的深水区。
一、插件时代的历史回顾
1.1 NPAPI 的诞生与辉煌
NPAPI(Netscape Plugin API)诞生于 1995 年,初衷是让浏览器能够加载第三方二进制插件,从而扩展浏览器功能。早期的 Internet Explorer、Netscape Navigator 都支持 NPAPI 插件,如 Flash、Java Applet、Silverlight 等,它们曾经是网页交互、视频播放、富客户端应用的主力军。
NPAPI 的核心特征是:
-
插件运行在浏览器进程内
-
插件是完全不受控的 native 代码,可以任意系统调用
-
API 简单但原始,典型接口包括
NPP_New、NPP_Destroy、NPP_HandleEvent,以及NPObject用于 JS ↔ Native 交互
虽然 NPAPI 灵活,但也带来了巨大的安全风险:
-
插件崩溃 = 浏览器崩溃
-
任意 native 代码执行 = 远程代码执行风险
-
阻塞主线程 = 用户体验极差
-
跨平台困难 = 每个操作系统都需要单独维护
这些问题为后来的 PPAPI 埋下了技术动因。
1.2 PPAPI:沙箱化插件的时代
Google 在开发 Chrome 多进程架构时发现,NPAPI 由于设计缺陷,几乎无法在保证安全的前提下运行。因此,Chromium 在 2011 年左右引入了 PPAPI(Pepper Plugin API)。
PPAPI 的设计理念是:
-
插件独立进程运行:避免浏览器主进程被 native 插件直接危害
-
接口受控:插件只能调用浏览器提供的 API
-
异步通信:所有调用通过 IPC 机制转发
核心架构如下:
JS
↓
Renderer Process
↓ (IPC)
PPAPI Proxy
↓
Plugin Process
↓ (IPC)
Browser Process
PPAPI 最大的成功案例是 Flash,在 Chrome 内置 PPAPI Flash,使得 Flash 插件能够安全运行在沙箱内,但仍然依赖复杂的 IPC 和插件 API。
1.3 Extension 与 Web API 的崛起
随着 HTML5、WebGL、WebRTC、WASM 等技术的成熟,浏览器插件逐渐失去了存在意义。Chrome 推出了 Extension 和 Native Messaging 机制,让开发者可以用 JS + Web API 完成之前必须依赖插件的功能:
-
Extension API:权限声明式访问资源
-
Native Messaging:安全地调用本地程序
-
WebAssembly:在沙箱内运行高性能二进制代码
这一阶段,浏览器彻底剥离了插件对浏览器进程的直接访问能力,实现了安全和可控。
1.4 Mojo:现代 IPC 的终极形态
Mojo 是 Chromium 自研的 IPC 框架,从 PPAPI 的 Proxy / IPC 演进而来。相比 PPAPI,Mojo 提供:
-
最小权限 IPC / FIDL 接口
-
进程间安全调用
-
高性能与沙箱隔离
-
用于系统核心功能的能力封装
Mojo 的出现意味着插件时代彻底终结,现代 Chrome 的能力完全由 Web API + Extension + Mojo IPC 提供。
二、Chromium 插件架构深度剖析
2.1 NPAPI 架构剖析
NPAPI 插件直接加载 DLL / SO,在浏览器进程中运行,JS 调用通过 NPObject 转发到 native 代码,native 代码再操作操作系统资源。典型调用链:
JS 调用 window.PluginObject.method() ↓ NPObject Invoke ↓ NPP_Invoke / NPP_HandleEvent ↓ Native 代码执行
这种设计的危险性在于:
-
崩溃无法隔离
-
任意系统调用完全不受控
-
主线程阻塞,UI 无响应
NPAPI 的安全问题和跨平台维护成本,最终导致 Chromium 2015 年彻底移除 NPAPI 支持。
2.2 PPAPI 架构剖析
PPAPI 在 Chromium 中是沙箱化插件的典型实现,流程如下:
-
Renderer Process:JS 与网页交互的沙箱
-
PPAPI Proxy:Renderer 侧代理,所有调用封装 IPC
-
Plugin Process:插件独立进程,只能通过 PPAPI 提供的接口访问资源
-
Browser Process:核心权限集中处理,IPC 转发
调用链示意:
网页 JS 调用 Extension / Plugin API ↓ Renderer Process PPAPI Proxy ↓ (IPC) Plugin Process ↓ (IPC) Browser Process 执行受控操作
特点:
-
独立进程沙箱化
-
API 控制访问能力
-
IPC 异步调用
-
插件崩溃不会影响主进程
在源码中,核心类包括:
-
PepperPluginInstance:插件实例封装 -
PepperPluginModule:插件模块管理 -
PluginDispatcher:Renderer ↔ Plugin Process 的 IPC 通道 -
PluginProcessHost:Browser Process 管理 Plugin Process
在 Chromium 源码中,Renderer 侧通过 PepperPluginInstance::HandleMessage 接收 IPC 消息,再调用 PluginDispatcher 转发至 Plugin Process,形成完全受控的通信链路。
2.3 Extension 架构剖析
Extension 是 Chromium 推出的现代插件替代方案,其核心设计理念:
-
权限声明式:在 manifest 中声明权限
-
JS + Web API:不允许直接 native 调用
-
Browser Process 控制资源访问
扩展的 Renderer 调用 Browser API 通过 Mojo 或 IPC,确保安全性和稳定性。相比 PPAPI,扩展大幅降低开发复杂度,同时支持跨平台。
2.4 Mojo 架构剖析
Mojo 是 Chromium 内部统一的 IPC / Interface 框架,替代了 PPAPI 的 Proxy / IPC 模式,优势:
-
FIDL 定义接口:保证接口安全与类型安全
-
沙箱内运行:渲染进程无法直接操作系统资源
-
异步调用支持:提升性能
-
可扩展到系统核心功能:如 PDFium、Audio、GPU 资源访问
Mojo 的核心类包括:
-
mojo::MessagePipe:IPC 消息管道 -
mojo::InterfacePtr/InterfaceRequest:接口绑定 -
mojo::SimpleWatcher:事件监听
通过 Mojo,Renderer 可以调用 Browser Process 的受控接口,实现现代浏览器所有插件功能替代方案。
三、Chromium 源码深水区解析:PPAPI Proxy / IPC 实现
3.1 Renderer 侧 Proxy
-
PepperPluginInstance在 Renderer 侧封装 JS 调用 -
PluginDispatcher负责将调用封装成 IPC 消息 -
IPC 类型:同步(Sync)与异步(Async)
-
核心函数:
-
Send(new PpapiMsg_Call(...)) -
OnMessageReceived(const IPC::Message& msg)
-
3.2 Plugin Process 处理
-
插件独立进程,通过
PluginProcessHost注册 -
接收 IPC 消息后调用
PepperPluginInstance对应方法 -
插件实例状态通过消息反馈给 Renderer
3.3 IPC 安全性与沙箱
-
渲染进程沙箱禁止访问文件系统、注册表
-
Plugin Process 在沙箱中运行
-
Browser Process 提供核心能力接口
-
IPC 消息通过 序列化 / 类型检查 防止恶意调用
3.4 调用链示例
JS: plugin.foo() ↓ Renderer: PepperPluginInstance::CallFoo ↓ PluginDispatcher::Send(PpapiMsg_Call) ↓ Plugin Process: HandleMessage -> 实际方法执行 ↓ 结果返回 Renderer -> JS 回调
通过 Proxy / IPC,Chromium 完全隔离了插件执行环境,保证主进程安全。
四、工程实践与迁移策略
-
NPAPI 迁移
-
所有 NPAPI 插件必须迁移至 Extension / Native Messaging
-
Flash 使用 PPAPI 沙箱化
-
-
PPAPI 插件维护成本高
-
多进程管理复杂
-
IPC 调试困难
-
Chrome 2015 后逐步淘汰
-
-
现代 Web 替代方案
-
HTML5 视频、Canvas、WebGL、WebRTC
-
WebAssembly 替代高性能插件
-
Extension + Mojo 替代插件核心功能
-
-
安全工程实践
-
所有外部二进制模块必须沙箱
-
权限细化到接口级别
-
IPC 消息强类型约束
-
五、总结
Chromium 坚决不再支持插件,是浏览器安全、性能、跨平台能力发展的必然结果。通过历史回顾和源码解析,我们可以看到:
-
NPAPI:灵活但极不安全
-
PPAPI:沙箱化但复杂
-
Extension:安全可控,跨平台
-
Mojo:现代 IPC 框架,安全高效
现代 Chrome 已彻底摆脱插件时代,通过 Web API + Extension + Mojo 提供安全、稳定、高性能的浏览体验。这一演进路线,对内核工程师理解浏览器架构、插件演进、IPC 安全机制具有极高价值,也为浏览器未来的高性能、跨平台发展奠定基础。

684

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



