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 扩展(如开发者工具、网络抓包、自动化工具等)常见的实现模式,兼顾了安全性、可维护性和扩展能力。

相关推荐
微信开发api-视频号协议1 小时前
Codex++安全边界探秘:从模型能力到风险防御
前端·安全·微信·企业微信
想你依然心痛2 小时前
AtomCode 在前端开发中的实战体验:React + TypeScript 项目开发实录
前端·react.js·typescript
疯狂的魔鬼2 小时前
精确计算容器剩余视口高度:useAutoContainerFullHeight 的工程实践
前端·css·typescript
Esaka_Forever2 小时前
Python 与 JS (V8) 垃圾回收核心区别 + 底层根源分析
开发语言·javascript·jvm
用户059540174462 小时前
用了 3 个月 ChatGPT,才发现它一直在遗忘——用 Playwright 自动化验证记忆存储一致性
前端·css
玄玄子2 小时前
xss前端解决方案
前端·浏览器·xss
林希_Rachel_傻希希2 小时前
web性能优化之——AI总结视频
前端·javascript·面试
前端炒粉2 小时前
个人简历面经总结二
前端·网络·vue.js·react.js·面试
binbin_522 小时前
UIAbility 与 WindowStage:窗口创建、加载、销毁的完整链路
开发语言·javascript·深度学习·华为·harmonyos