Chrome Extension Script World(ISOLATED / MAIN)原理与适用场景

Chrome Extension Script World(ISOLATED / MAIN)原理与适用场景

适用于 Chrome Manifest V3(MV3)扩展开发


一、概述

Chrome 为了保证网页与扩展之间的安全隔离,引入了 Execution World(执行世界) 的概念。

Content Script 并不是直接运行在网页 JavaScript 环境中,而是运行在不同的 World(世界)

目前主要有:

World 含义 是否默认
ISOLATED 隔离环境(Extension World) ✅ 默认
MAIN 页面环境(Page World) ❌ 需要主动指定

Manifest V3 中可以通过:

json 复制代码
{
    "content_scripts": [{
        "matches": ["<all_urls>"],
        "js": ["content.js"],
        "world": "MAIN"
    }]
}

或者

javascript 复制代码
chrome.scripting.executeScript({
    target: { tabId },
    files: ["inject.js"],
    world: "MAIN"
});

指定执行环境。


二、Chrome 的执行环境

浏览器打开一个网页以后,大致存在如下环境:

复制代码
Chrome Browser
│
├── Web Page(网页)
│      │
│      ├── Window
│      ├── Document
│      ├── 页面 JS
│      └── 第三方 JS
│
├── Extension World(ISOLATED)
│      │
│      ├── Content Script
│      ├── chrome.runtime
│      └── chrome.storage
│
└── Service Worker

可以看到:

网页 JS

Content Script

其实并不在同一个 JavaScript 环境。


三、ISOLATED(默认)

什么是 ISOLATED

ISOLATED 就是:

Chrome 给每个扩展创建一个独立 JavaScript 运行环境。

它共享:

  • DOM
  • Document
  • 页面元素

但是:

不共享 JavaScript 变量。


举个例子

网页:

javascript 复制代码
window.user = {
    name: "Tom"
};

Content Script:

javascript 复制代码
console.log(window.user);

输出:

复制代码
undefined

很多新人第一次都会觉得奇怪。

原因:

你的 window 并不是网页那个 window。

它只是:

复制代码
DOM 相同

JS Context 不同

为什么还能操作 DOM?

例如:

javascript 复制代码
document.body.style.background = "red";

可以成功。

因为:

DOM 是共享的。

复制代码
网页
      │
      ├───────────── DOM ─────────────┐
      │                               │
ISOLATED World                 MAIN World

两个 JS Context

操作的是同一棵 DOM Tree。


JS Context 隔离

举例:

网页:

javascript 复制代码
let count = 100;

Content Script:

javascript 复制代码
console.log(count);

结果:

复制代码
ReferenceError

再比如:

网页:

javascript 复制代码
window.fetch = function(){
    console.log("page");
}

Content Script:

javascript 复制代码
fetch("...");

调用的是:

浏览器原始 fetch。

不是页面修改后的 fetch。


为什么这么设计?

为了防止网页:

修改扩展。

例如:

恶意网页:

javascript 复制代码
chrome.runtime.sendMessage = function(){
    stealData();
}

如果没有隔离:

扩展就危险了。

Chrome 所以:

把 JS Context 完全隔离。


ISOLATED 可以访问哪些 API?

可以。

例如:

javascript 复制代码
chrome.runtime.sendMessage(...)

可以。

复制代码
chrome.storage

chrome.runtime

chrome.i18n

chrome.tabs(部分)

都是扩展能力。

这是 MAIN 没有的。


ISOLATED 优点

✅ 安全

不会污染网页。


不会被网页污染。


可以直接使用:

复制代码
chrome.runtime

chrome.storage

chrome.cookies

message

适合:

90% 插件开发。


ISOLATED 缺点

不能:

复制代码
window.React

window.Vue

window.jQuery

webpackChunk

__NEXT_DATA__

这些页面变量。


也不能 Hook:

复制代码
fetch

XMLHttpRequest

history.pushState

因为不是一个 JS Context。


四、MAIN

什么是 MAIN

MAIN:

就是:

让 Content Script

真正运行到:

复制代码
网页 JS 环境

也就是:

和网页自己的 JS

属于同一个 Context。


执行结构:

复制代码
网页 JS
        │
        ├──── inject.js(MAIN)

此时:

复制代码
window

this

globalThis

完全一致。


举例

网页:

javascript 复制代码
window.user = {
    name:"Tom"
}

MAIN:

javascript 复制代码
console.log(window.user);

输出:

复制代码
{name:"Tom"}

可以访问。


Hook fetch

MAIN:

javascript 复制代码
const oldFetch = window.fetch;

window.fetch = function(...args){
    console.log(args);

    return oldFetch.apply(this,args);
}

以后:

页面:

javascript 复制代码
fetch(...)

都会经过:

你的 Hook。

ISOLATED 做不到。


Hook XHR

javascript 复制代码
const open = XMLHttpRequest.prototype.open;

XMLHttpRequest.prototype.open = function(){

    console.log(arguments);

    return open.apply(this,arguments);
}

页面所有 Ajax

都会经过。


Hook History

例如:

React:

Vue:

SPA:

javascript 复制代码
history.pushState = ...

只能:

MAIN。


修改页面变量

例如:

javascript 复制代码
window.token = "abc";

MAIN:

可以。

ISOLATED:

不可以。


调用 React

例如:

javascript 复制代码
window.React

MAIN:

可以。


调用 Vue

例如:

javascript 复制代码
window.__VUE__

MAIN:

可以。


MAIN 的限制

MAIN:

没有:

复制代码
chrome.runtime

例如:

javascript 复制代码
chrome.runtime.sendMessage()

报错:

复制代码
chrome is undefined

因为:

MAIN

已经变成:

网页 JS。

不是扩展环境。


因此:

如果:

MAIN

想调用:

Extension API。

需要:

postMessage

或者

CustomEvent

通知:

ISOLATED。


五、MAIN 与 ISOLATED 通信

最常见:

复制代码
MAIN
   │
postMessage
   │
ISOLATED
   │
chrome.runtime.sendMessage
   │
Service Worker

例如:

MAIN:

javascript 复制代码
window.postMessage({
    type: "GET_TOKEN"
});

ISOLATED:

javascript 复制代码
window.addEventListener("message", (e) => {
    if (e.data.type === "GET_TOKEN") {
        chrome.runtime.sendMessage({
            type: "GET_TOKEN"
        });
    }
});

六、两者对比

对比项 ISOLATED MAIN
默认环境 ✅ 是 ❌ 否
JS Context 独立 与页面相同
DOM 共享 共享
页面变量
修改页面 JS
Hook fetch
Hook XHR
Hook History
React/Vue 全局变量
chrome.runtime
chrome.storage
安全性 较低
推荐程度 ⭐⭐⭐⭐⭐ ⭐⭐⭐

七、典型应用场景

场景一:页面美化(推荐 ISOLATED)

例如:

  • 修改 CSS
  • 添加按钮
  • 添加侧边栏
  • 阅读模式
  • 广告屏蔽

原因:

只需要操作 DOM,不需要访问页面 JS。


场景二:网页自动化(推荐 ISOLATED)

例如:

javascript 复制代码
document.querySelector(...)
button.click()

适用于:

  • 自动签到
  • 自动填写表单
  • 自动点击按钮

场景三:抓取页面数据(推荐 ISOLATED)

例如:

javascript 复制代码
document.querySelectorAll(...)

读取:

  • 文本
  • 图片
  • 表格
  • DOM 信息

场景四:Hook 网络请求(推荐 MAIN)

例如:

监控:

复制代码
fetch()

XMLHttpRequest

WebSocket

适用于:

  • 网络调试
  • 数据采集
  • API 分析

场景五:读取前端框架状态(推荐 MAIN)

例如:

读取:

javascript 复制代码
window.React
window.__NEXT_DATA__
window.__INITIAL_STATE__
window.__NUXT__

适用于:

  • React DevTools 类工具
  • Vue 调试工具
  • 数据分析插件

场景六:修改网页运行逻辑(推荐 MAIN)

例如:

重写:

javascript 复制代码
window.fetch

history.pushState

console.log

alert

适用于:

  • APM
  • 性能监控
  • 调试工具
  • 自动测试

八、最佳实践

推荐原则

能用 ISOLATED,就不要用 MAIN。

原因:

  • 更安全
  • 能直接访问扩展 API
  • 不容易受到网页脚本影响
  • 更符合 Chrome 扩展的设计理念

推荐架构

对于复杂插件,推荐采用双 World 架构:

复制代码
                Chrome Extension

                Service Worker
                       ▲
                       │ chrome.runtime
                       │
             ┌─────────┴─────────┐
             │                   │
      ISOLATED World      MAIN World
             │                   │
             │ postMessage       │
             └─────────┬─────────┘
                       │
                    Web Page

职责划分如下:

MAIN

负责:

  • Hook fetch
  • Hook XHR
  • Hook WebSocket
  • 读取页面变量
  • 修改页面 JavaScript 行为

ISOLATED

负责:

  • DOM 操作
  • 与 Service Worker 通信
  • 使用 chrome.* API
  • 数据存储
  • 权限管理
  • 消息转发

Service Worker

负责:

  • 网络请求
  • 插件后台逻辑
  • 持久化存储
  • 标签页管理
  • 生命周期管理

这种分层方式是目前多数大型 Chrome 扩展(如开发者工具、网络抓包、自动化工具等)常见的实现模式,兼顾了安全性、可维护性和扩展能力。

相关推荐
腻害兔2 分钟前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:CRM 客户关系模块深度解析——从线索到回款,一套完整的 B2B 销售闭环是怎么搭的?
java·前端·javascript·vue.js·产品经理·ai编程
whyfail10 分钟前
前端学 Spring Boot(2):一次点击,如何穿过整个后端?
前端·spring boot·后端
AI多Agent协作实战派41 分钟前
AI多Agent协作系统实战(二十三):Agent读HEARTBEAT.md不读AGENTS.md——openclaw的文件加载之谜
前端·数据库·人工智能·uni-app
gis开发之家1 小时前
《Vue3 从入门到大神37篇》Vue3 源码详解(七):watch 与 watchEffect 源码对比——副作用是如何被追踪的?
javascript·前端框架·vue3·vue3源码
2601_955760072 小时前
如何用 Claude Opus 5 API 批量扩展长尾关键词和文章选题
前端·python·搜索引擎
KaMeidebaby2 小时前
卡梅德生物技术快报|bli亲和力检测gst:告别批量跑胶:BLI实时酶切监测技术加速GST融合蛋白下游流程优化
前端·网络·数据库·人工智能·算法
bloglin999992 小时前
langchain 和 langgraph 和 react
javascript·react.js·langchain
触底反弹2 小时前
🚀 删了数据刷新又回来?3 组件 × 4 回调 × 3 坑讲透 React 父子通信
前端·javascript·react.js
耳东小鹿3 小时前
对象常用方法
前端
程序员海军3 小时前
一个 AI 应用开发程序员的一天,都在屏幕前忙些什么?
前端·后端·程序员