Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Sep 17, 2025

This PR implements an intelligent script injection system that replaces the monolithic src/content structure with dynamic platform-specific script injection using Chrome's chrome.scripting.executeScript API, addressing the need for precise code separation while ensuring scripts have full Chrome API access.

Problem Solved

The original codebase had a centralized content injection system where all platform logic was bundled together through Uninject.ts. This created dependencies and made it difficult to maintain platform-specific functionality independently.

Solution Overview

Intelligent Script Injection System

Implemented dynamic injection of four platform-specific scripts using chrome.scripting.executeScript:

  • content-discourse.js (6.28 kB) - Handles Discourse forums with batch image parsing and single image addition
  • content-x.js (7.54 kB) - Manages X/Twitter image carousels and video link copying
  • content-pixiv.js (7.80 kB) - Processes Pixiv images with CORS handling and canvas downloading
  • content-reddit.js (5.84 kB) - Handles Reddit image containers with srcset optimization

Key Technical Features

Smart Content Script: The main content script (content-smart.ts) performs platform detection and requests background script injection:

async function requestPlatformInjection(platform: string): Promise<boolean> { const response = await sendToBackground({ type: 'INJECT_PLATFORM_SCRIPT', platform: platform, url: window.location.href }) return response.success }

Chrome API Injection: Background script uses chrome.scripting.executeScript for dynamic injection with full API access:

export async function handleInjectPlatformScript( platform: string, url: string, sender: any, sendResponse: any ): Promise<void> { const results = await chrome.scripting.executeScript({ target: { tabId: tabId }, files: [`js/${scriptFile}`], world: 'ISOLATED', // Full Chrome API access injectImmediately: false }) }

Full Chrome API Access: Platform scripts run in the ISOLATED world with complete Chrome extension API access:

// Platform scripts can directly use Chrome APIs function sendToBackground(message: any): Promise<any> { return new Promise(resolve => { const chromeAPI = chrome // Direct access to Chrome API chromeAPI.runtime.sendMessage(message, response => { resolve(response || { success: false, error: 'No response' }) }) }) }

Smart Platform Detection: Multi-layered detection using hostname, meta tags, and page elements:

function detectPlatform(): 'discourse' | 'x' | 'pixiv' | 'reddit' | 'unknown' { const hostname = window.location.hostname.toLowerCase() // X (Twitter) detection if (hostname === 'x.com' || hostname.includes('twitter.com')) { return 'x' } // Discourse detection via meta tags const discourseMetaTags = document.querySelectorAll( 'meta[name*="discourse"], meta[content*="discourse"]' ) if (discourseMetaTags.length > 0) { return 'discourse' } // Additional platform checks... }

Integrated Build System

Platform scripts are now integrated into the main vite build process:

  • Single npm run build command builds all components
  • Platform scripts compiled as separate entry points
  • No separate build commands required
  • Automatic script management and optimization

Background Script Integration

Extended the background script system with intelligent injection handlers:

  • INJECT_PLATFORM_SCRIPT - Uses chrome.scripting.executeScript for dynamic injection
  • PLATFORM_DETECTED - Logs platform detection events
  • AUTONOMOUS_SCRIPT_READY - Tracks script lifecycle

Performance Improvements

  • 44% reduction in main content script size (107.80 kB → 60.04 kB)
  • On-demand loading of platform-specific functionality (5-8 kB per platform)
  • Direct Chrome API access without communication overhead
  • Simplified build process with single command

Testing & Validation

Comprehensive testing confirmed:

  • ✅ Platform detection accuracy across all supported platforms
  • ✅ Successful script injection using chrome.scripting.executeScript
  • ✅ Full Chrome API access in injected scripts
  • ✅ Build system integration working correctly
  • ✅ 44% reduction in main content script size

Files Added/Modified

Smart Injection System:

  • src/content/content-smart.ts - Smart platform detection and injection request
  • src/background/handlers/autonomousScripts.ts - Chrome API injection handlers
  • Updated src/background/utils/handlers.ts - Message routing

Platform Scripts (Chrome API Enabled):

  • src/autonomous-scripts/discourse-script.ts
  • src/autonomous-scripts/x-script.ts
  • src/autonomous-scripts/pixiv-script.ts
  • src/autonomous-scripts/reddit-script.ts

Build System Integration:

  • Updated vite.config.ts - Integrated platform scripts as build entries
  • Updated package.json - Removed separate build command
  • scripts/build.js - Fixed build command for npm compatibility

Documentation:

  • INTELLIGENT_INJECTION.md - Complete system documentation

This implementation achieves precise code separation through intelligent script injection using Chrome's standard APIs, enabling independent platform maintenance while ensuring scripts have full Chrome extension privileges and API access.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI and others added 3 commits September 17, 2025 04:58
…cripts Co-authored-by: stevessr <89645372+stevessr@users.noreply.github.com>
Co-authored-by: stevessr <89645372+stevessr@users.noreply.github.com>
Co-authored-by: stevessr <89645372+stevessr@users.noreply.github.com>
Copilot AI changed the title [WIP] 尝试拆分上src/content为按照网站和用途分类的自治脚本(即不依赖外部的库,导出也不会被外部使用,不要通过vite的配置实现,而是通过对于代码的精准分割赋能(允许一个函数的多个独立副... Implement autonomous platform scripts system to replace centralized content injection Sep 17, 2025
Copilot AI requested a review from stevessr September 17, 2025 05:18
Copilot finished work on behalf of stevessr September 17, 2025 05:18
@stevessr
Copy link
Owner

@copilot 构建不能独立,要合并到主插件构建一起(要用智能注入的脚本组替换原有的单个的content)
注入参考以下资料(要求智能注入的脚本要能够访问chrome api)
详细解析 chrome.scripting.executeScript
chrome.scripting.executeScript 是 Chrome Manifest V3 (MV3) 中用于动态注入脚本到网页页面的核心 API。它取代了 Manifest V2 中的 chrome.tabs.executeScript,提供了更精细、更安全的控制。

主要功能和参数
chrome.scripting.executeScript 方法接受一个 details 对象作为参数,该对象包含以下关键属性:

target (必需): 这是一个对象,用于指定脚本应该注入到哪个标签页和帧中。

tabId (必需): 你想要注入脚本的标签页 ID。你可以通过 chrome.tabs.query 或其他标签页 API 获取此 ID。

frameIds (可选): 一个数组,包含你想要注入脚本的特定帧 ID。如果你不指定,脚本会注入到主框架中。

files (可选): 一个字符串数组,包含要注入的本地脚本文件路径。路径是相对于扩展程序的根目录。例如:["content-script.js"]。

func (可选): 一个函数。如果提供了此参数,Chrome 会将该函数的代码序列化并作为脚本注入。这个方法非常适合注入简单的、即时运行的代码片段。

args (可选): 一个数组,包含要传递给 func 函数的参数。这些参数将被序列化并传递给注入的函数。

world (可选): 一个字符串,用于指定脚本运行的隔离环境。

"ISOLATED" (默认): 脚本在与页面 DOM 隔离的环境中运行。这是最安全的选择,脚本无法直接访问页面变量,但可以访问 DOM。

"MAIN": 脚本直接在页面的主 JavaScript 环境中运行。这使得脚本可以访问和修改页面中定义的变量和函数。只有当你确实需要访问页面变量时才使用此选项。

injectImmediately (可选): 一个布尔值。如果设置为 true,脚本会在页面加载之前尽可能早地注入和运行。这对于在页面脚本执行前修改 DOM 或变量非常有用。

使用示例

  1. 注入本地脚本文件 (files)
    这通常用于注入一个相对复杂的、预先编写好的内容脚本。

JavaScript

// 在 Service Worker 或 Popup 页面中
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const tabId = tabs[0].id;

chrome.scripting.executeScript({
target: { tabId: tabId },
files: ["content_script.js"]
}, () => {
// 注入成功后的回调函数
console.log("content_script.js 已成功注入");
});
});
2. 注入函数 (func)
这对于执行一些简单、一次性的任务非常方便,比如在不创建新文件的情况下获取页面元素。

JavaScript

// 在 Service Worker 或 Popup 页面中
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const tabId = tabs[0].id;
const userName = "Tom"; // 假设这是要传递的变量

chrome.scripting.executeScript({
target: { tabId: tabId },
func: (name) => {
// 这个函数会在页面环境中执行
alert(Hello, ${name}!);
const element = document.querySelector('h1');
if (element) {
return element.innerText;
}
return null;
},
args: [userName]
}, (results) => {
// 回调函数接收注入脚本的返回值
const h1Text = results[0].result;
console.log("页面 h1 元素的文本是:", h1Text);
});
});
3. 注入到指定框架 (frameIds)
如果你需要向 iframe 注入脚本,可以使用 frameIds。

JavaScript

// 首先获取所有框架
chrome.webNavigation.getAllFrames({ tabId: tabId }, (frames) => {
const frameIds = frames.map(f => f.frameId);

// 注入脚本到所有框架
chrome.scripting.executeScript({
target: { tabId: tabId, frameIds: frameIds },
files: ["frame_script.js"]
});
});
重要的注意事项
权限: 必须在 manifest.json 中声明 scripting 权限,并且需要有目标网站的 host_permissions。

JSON

"permissions": [
"scripting"
],
"host_permissions": [
"https://.example.com/"
]
返回值: executeScript 的回调函数会返回一个 results 数组。数组中的每个元素对应一个注入的帧,其 result 属性就是注入函数(func)的返回值。

异步性: executeScript 是一个异步操作。你应该在其回调函数中处理注入成功后的逻辑,而不是紧接着它写。

隔离环境: 注入的脚本默认运行在独立的隔离环境中。这意味着它们无法直接访问页面中定义的全局变量,反之亦然。如果需要通信,请使用 chrome.runtime.sendMessage 和 window.postMessage。

chrome.scripting.executeScript 提供了强大的能力,让你的扩展程序能够灵活地与网页进行交互。理解其参数和行为对于开发高效且安全的 MV3 扩展至关重要。

…cripting.executeScript Co-authored-by: stevessr <89645372+stevessr@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Sep 17, 2025

@copilot 构建不能独立,要合并到主插件构建一起(要用智能注入的脚本组替换原有的单个的content)
注入参考以下资料(要求智能注入的脚本要能够访��...

已完成所有要求的修改 (commit a4c6644):

构建集成: 移除独立构建,合并到主插件构建 (npm run build)
智能注入: 使用 chrome.scripting.executeScript 替换原有的单个content脚本
Chrome API访问: 注入脚本在 ISOLATED 环境运行,具有完整的Chrome API访问权限

核心改进:

  • 主内容脚本缩小44% (107.80 kB → 60.04 kB)
  • 平台脚本按需注入 (discourse: 6.28 kB, x: 7.54 kB, pixiv: 7.80 kB, reddit: 5.84 kB)
  • 使用标准Chrome API,无需复杂的脚本内容传递机制
  • 单一构建命令,自动化脚本管理
Copilot AI changed the title Implement autonomous platform scripts system to replace centralized content injection Implement intelligent platform script injection system using chrome.scripting.executeScript Sep 17, 2025
Copilot finished work on behalf of stevessr September 17, 2025 07:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants