first commit

This commit is contained in:
2026-01-29 12:03:28 +08:00
commit 3ecfab1212
18 changed files with 34678 additions and 0 deletions

873
content-script.js Normal file
View File

@@ -0,0 +1,873 @@
/**
* Content Script - 使用 DevTools Network API 获取 XHR 请求
*
* 注意:这个脚本只在 DevTools 面板中使用
* 实际的请求捕获通过 chrome.devtools.network.onRequestFinished 实现
*/
// 这个文件现在已经不需要了,因为请求捕获在 DevTools 面板中完成
// 但保留文件以避免错误
// 将完整的拦截脚本注入到页面上下文
const script = document.createElement('script');
script.textContent = `
(function() {
'use strict';
console.log('🔧 [页面上下文] 拦截脚本已执行');
console.log('🔧 [页面上下文] XMLHttpRequest 类型:', typeof XMLHttpRequest);
console.log('🔧 [页面上下文] fetch 类型:', typeof fetch);
// 在页面上下文中存储解密记录
if (!window.__XHR_DECRYPT_DATA__) {
window.__XHR_DECRYPT_DATA__ = {
requests: [],
addRequest: function(record) {
this.requests.push(record);
if (this.requests.length > 100) {
this.requests.shift();
}
// 通知 content script
window.dispatchEvent(new CustomEvent('__XHR_DECRYPTED__', { detail: record }));
},
getRequests: function() {
return this.requests;
},
clear: function() {
this.requests = [];
}
};
}
const decryptedData = window.__XHR_DECRYPT_DATA__;
const requestHeadersMap = new Map();
const skipDecryptPaths = ['v1/picture/upload'];
// ========== 密钥获取策略管理器 ==========
const KeyGetStrategies = {
strategies: [],
// 注册密钥获取策略
register: function(strategy) {
if (strategy && typeof strategy.getName === 'function' && typeof strategy.getKey === 'function') {
this.strategies.push({
name: strategy.getName(),
priority: strategy.priority || 100,
getKey: strategy.getKey,
canHandle: strategy.canHandle || (() => true)
});
// 按优先级排序(数字越小优先级越高)
this.strategies.sort((a, b) => a.priority - b.priority);
}
},
// 获取密钥(按优先级尝试所有策略)
getKey: function(url, uuid, requestHeaders) {
for (const strategy of this.strategies) {
try {
if (strategy.canHandle(url, uuid, requestHeaders)) {
const key = strategy.getKey(url, uuid, requestHeaders);
if (key) {
console.log('🔑 [密钥策略] 使用策略:', strategy.name, '获取密钥成功');
return { key: key, strategy: strategy.name };
}
}
} catch (error) {
console.warn('🔑 [密钥策略] 策略', strategy.name, '执行失败:', error);
continue;
}
}
console.warn('🔑 [密钥策略] 所有策略都无法获取密钥');
return null;
},
// 初始化默认策略
init: function() {
// 策略1: 从页面工具获取密钥(优先级最高)
this.register({
name: '页面工具获取',
priority: 10,
canHandle: function(url, uuid, requestHeaders) {
return window.__DECRYPT_TOOLS__ && window.__DECRYPT_TOOLS__.getKey;
},
getKey: function(url, uuid, requestHeaders) {
const tools = window.__DECRYPT_TOOLS__;
if (tools && tools.getKey) {
return tools.getKey(url, uuid);
}
return null;
}
});
// 策略2: 从请求头计算密钥timestamp + TraceId
this.register({
name: '请求头计算',
priority: 20,
canHandle: function(url, uuid, requestHeaders) {
const timestamp = requestHeaders?.time || requestHeaders?.Time || '';
const traceId = requestHeaders?.TraceId || requestHeaders?.['trace-id'] || '';
return !!(timestamp && traceId);
},
getKey: function(url, uuid, requestHeaders) {
const timestamp = requestHeaders?.time || requestHeaders?.Time || '';
const traceId = requestHeaders?.TraceId || requestHeaders?.['trace-id'] || '';
if (timestamp && traceId) {
return String(timestamp + traceId).slice(0, 16);
}
return null;
}
});
// 可以在这里添加更多密钥获取策略
// 例如:从 localStorage 获取、从 URL 参数获取、从 Cookie 获取等
}
};
// ========== 解密策略管理器 ==========
const DecryptStrategies = {
strategies: [],
// 注册解密策略
register: function(strategy) {
if (strategy && typeof strategy.getName === 'function' && typeof strategy.decrypt === 'function') {
this.strategies.push({
name: strategy.getName(),
priority: strategy.priority || 100,
decrypt: strategy.decrypt,
canHandle: strategy.canHandle || (() => true)
});
// 按优先级排序
this.strategies.sort((a, b) => a.priority - b.priority);
}
},
// 解密数据(按优先级尝试所有策略)
decrypt: function(encryptedData, key, isRequest = false) {
for (const strategy of this.strategies) {
try {
if (strategy.canHandle(encryptedData, key, isRequest)) {
const decrypted = strategy.decrypt(encryptedData, key, isRequest);
if (decrypted !== null && decrypted !== undefined && decrypted !== encryptedData) {
console.log('🔓 [解密策略] 使用策略:', strategy.name, '解密成功');
return { data: decrypted, strategy: strategy.name };
}
}
} catch (error) {
console.warn('🔓 [解密策略] 策略', strategy.name, '执行失败:', error);
continue;
}
}
console.warn('🔓 [解密策略] 所有策略都无法解密数据');
return { data: encryptedData, strategy: null };
},
// 初始化默认策略
init: function() {
// 策略1: 使用页面工具解密(优先级最高)
this.register({
name: '页面工具解密',
priority: 10,
canHandle: function(encryptedData, key, isRequest) {
return window.__DECRYPT_TOOLS__ && window.__DECRYPT_TOOLS__.Decrypt;
},
decrypt: function(encryptedData, key, isRequest) {
const tools = window.__DECRYPT_TOOLS__;
if (!tools || !tools.Decrypt) {
return null;
}
try {
if (isRequest) {
// 请求数据格式:{ data: "base64String" }
if (encryptedData && encryptedData.data && typeof encryptedData.data === 'string') {
const decrypted = tools.Decrypt(encryptedData.data, key);
if (decrypted) {
return JSON.parse(decrypted);
}
}
} else {
// 响应数据格式:字符串或对象
if (typeof encryptedData === 'string') {
const decrypted = tools.Decrypt(encryptedData, key);
if (decrypted) {
try {
return JSON.parse(decrypted);
} catch (e) {
if (window.JSON5) {
return window.JSON5.parse(decrypted);
}
return decrypted;
}
}
}
}
} catch (error) {
console.error('解密失败:', error);
}
return null;
}
});
// 策略2: 使用 CryptoJS 直接解密(如果可用)
this.register({
name: 'CryptoJS 解密',
priority: 20,
canHandle: function(encryptedData, key, isRequest) {
return typeof CryptoJS !== 'undefined' && key;
},
decrypt: function(encryptedData, key, isRequest) {
try {
if (typeof CryptoJS === 'undefined') {
return null;
}
let dataToDecrypt = null;
if (isRequest) {
if (encryptedData && encryptedData.data && typeof encryptedData.data === 'string') {
dataToDecrypt = encryptedData.data;
} else {
return null;
}
} else {
if (typeof encryptedData === 'string') {
dataToDecrypt = encryptedData;
} else {
return null;
}
}
if (!dataToDecrypt) {
return null;
}
// 清理数据
const cleanData = dataToDecrypt.replace(/\s/g, '').replace(/"/g, '');
const cleanKey = key.replace(/\s/g, '').replace(/"/g, '');
// AES 解密
const decrypt = CryptoJS.AES.decrypt(
cleanData,
CryptoJS.enc.Utf8.parse(cleanKey),
{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}
);
const decrypted = decrypt.toString(CryptoJS.enc.Utf8);
if (!decrypted) {
return null;
}
// 尝试解析 JSON
try {
return JSON.parse(decrypted);
} catch (e) {
if (window.JSON5) {
return window.JSON5.parse(decrypted);
}
return decrypted;
}
} catch (error) {
return null;
}
}
});
// 可以在这里添加更多解密策略
// 例如:其他加密算法、不同的填充方式等
}
};
// 初始化策略管理器
KeyGetStrategies.init();
DecryptStrategies.init();
// ========== 便捷函数 ==========
// 获取密钥
function getTimestampKey(url, uuid, requestHeaders) {
const result = KeyGetStrategies.getKey(url, uuid, requestHeaders);
return result ? result.key : null;
}
// 解密请求数据
function decryptRequestData(encryptedData, timestampKey) {
if (!timestampKey) {
return encryptedData;
}
const result = DecryptStrategies.decrypt(encryptedData, timestampKey, true);
return result.data;
}
// 解密响应数据
function decryptResponseData(encryptedData, timestampKey) {
if (!timestampKey) {
return encryptedData;
}
const result = DecryptStrategies.decrypt(encryptedData, timestampKey, false);
return result.data;
}
// 暴露策略管理器,允许外部注册新策略
window.__XHR_DECRYPT_STRATEGIES__ = {
keyGetStrategies: KeyGetStrategies,
decryptStrategies: DecryptStrategies
};
// ========== 拦截 XMLHttpRequest ==========
// 必须在页面脚本运行前拦截,否则会被覆盖
(function() {
if (typeof XMLHttpRequest === 'undefined') {
console.warn('⚠️ [页面上下文] XMLHttpRequest 未定义');
return;
}
// 保存原始函数(必须在任何其他脚本运行前保存)
const originalXHR = window.XMLHttpRequest;
const originalOpen = XMLHttpRequest.prototype.open;
const originalSend = XMLHttpRequest.prototype.send;
const originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
// 检查是否已经被拦截过
const openStr = originalOpen.toString();
if (openStr.includes('_method') || openStr.includes('__XHR_DECRYPT')) {
console.log('⚠️ [页面上下文] XHR 可能已被其他脚本拦截');
}
XMLHttpRequest.prototype.open = function(method, url, ...args) {
this._method = method;
this._url = url;
this._requestHeaders = {};
requestHeadersMap.set(this, {});
console.log('🔍 [页面上下文] 拦截 XHR open:', method, url);
// 确保返回正确的结果
const result = originalOpen.apply(this, [method, url, ...args]);
return result;
};
XMLHttpRequest.prototype.setRequestHeader = function(name, value) {
if (!this._requestHeaders) {
this._requestHeaders = {};
}
this._requestHeaders[name] = value;
const headers = requestHeadersMap.get(this) || {};
headers[name] = value;
requestHeadersMap.set(this, headers);
return originalSetRequestHeader.apply(this, [name, value]);
};
XMLHttpRequest.prototype.send = function(body) {
const url = this._url;
const method = this._method;
const requestId = Date.now() + Math.random();
const shouldSkip = skipDecryptPaths.some(path => url.includes(path));
// 监听响应
this.addEventListener('loadend', function() {
if (shouldSkip) return;
try {
const headers = requestHeadersMap.get(this) || {};
const uuid = this.getResponseHeader('uuid');
if (!uuid) {
return;
}
// 获取密钥(包含策略信息)
const keyResult = KeyGetStrategies.getKey(url, uuid, headers);
if (!keyResult || !keyResult.key) {
console.warn('无法获取密钥', { url, uuid, headers });
return;
}
const timestampKey = keyResult.key;
const keyStrategy = keyResult.strategy;
// 解密请求数据(包含策略信息)
let requestBody = null;
let requestDecryptStrategy = null;
if (body) {
try {
const parsed = typeof body === 'string' ? JSON.parse(body) : body;
const decryptResult = DecryptStrategies.decrypt(parsed, timestampKey, true);
requestBody = decryptResult.data;
requestDecryptStrategy = decryptResult.strategy;
} catch (e) {
requestBody = body;
}
}
// 解密响应数据(包含策略信息)
let responseData = null;
try {
if (this.responseText) {
responseData = JSON.parse(this.responseText);
}
} catch (e) {
responseData = this.responseText || this.response;
}
const decryptResult = DecryptStrategies.decrypt(responseData, timestampKey, false);
const decryptedResponse = decryptResult.data;
const responseDecryptStrategy = decryptResult.strategy;
// 记录解密结果
const decryptedRecord = {
id: requestId,
url: url,
method: method,
uuid: uuid,
timestampKey: timestampKey,
keyStrategy: keyStrategy,
request: requestBody,
requestDecryptStrategy: requestDecryptStrategy,
response: decryptedResponse,
responseDecryptStrategy: responseDecryptStrategy,
timestamp: new Date().toISOString()
};
// 存储到页面上下文
decryptedData.addRequest(decryptedRecord);
// 输出到控制台
console.group('🔓 XHR 解密 [' + method + '] ' + url);
console.log('🔑 密钥:', timestampKey, '(策略: ' + keyStrategy + ')');
if (requestDecryptStrategy) {
console.log('📤 请求:', requestBody, '(解密策略: ' + requestDecryptStrategy + ')');
} else {
console.log('📤 请求:', requestBody);
}
if (responseDecryptStrategy) {
console.log('📥 响应:', decryptedResponse, '(解密策略: ' + responseDecryptStrategy + ')');
} else {
console.log('📥 响应:', decryptedResponse);
}
console.log('📍 UUID:', uuid);
console.groupEnd();
} catch (error) {
console.error('❌ 解密过程出错:', error);
}
});
return originalSend.apply(this, [body]);
};
console.log('✅ [页面上下文] XHR 拦截已设置');
console.log('✅ [页面上下文] originalOpen 类型:', typeof originalOpen);
console.log('✅ [页面上下文] XMLHttpRequest.prototype.open:', typeof XMLHttpRequest.prototype.open);
// 验证拦截是否真的生效
setTimeout(function() {
const testXhr = new XMLHttpRequest();
const testOpenStr = testXhr.open.toString();
if (testOpenStr.includes('_method')) {
console.log('✅ [页面上下文] XHR 拦截验证成功');
} else {
console.error('❌ [页面上下文] XHR 拦截验证失败,可能被覆盖');
console.error(' 当前 open 函数:', testOpenStr.substring(0, 100));
}
}, 500);
})();
// ========== 拦截 Fetch ==========
// 必须在页面脚本运行前拦截
(function() {
if (typeof fetch === 'undefined' || !window.fetch) {
console.warn('⚠️ [页面上下文] fetch 未定义');
return;
}
// 保存原始函数
const originalFetch = window.fetch;
// 检查是否已经被拦截过
const fetchStr = originalFetch.toString();
if (fetchStr.includes('clonedResponse') || fetchStr.includes('__XHR_DECRYPT')) {
console.log('⚠️ [页面上下文] Fetch 可能已被其他脚本拦截');
}
window.fetch = function(...args) {
const [url, options = {}] = args;
const method = options.method || 'GET';
const requestId = Date.now() + Math.random();
const shouldSkip = skipDecryptPaths.some(path => url.includes(path));
const originalBody = options.body;
console.log('🔍 [页面上下文] 拦截 Fetch:', method, url);
return originalFetch.apply(this, args).then(async (response) => {
if (shouldSkip) return response;
try {
const clonedResponse = response.clone();
const uuid = clonedResponse.headers.get('uuid');
if (!uuid) {
return response;
}
const headers = options.headers || {};
const timestamp = headers.time || headers.Time || '';
const traceId = headers.TraceId || headers['trace-id'] || '';
// 获取密钥(包含策略信息)
const keyResult = KeyGetStrategies.getKey(url, uuid, { time: timestamp, TraceId: traceId });
if (!keyResult || !keyResult.key) {
console.warn('无法获取密钥 (Fetch)', { url, uuid });
return response;
}
const timestampKey = keyResult.key;
const keyStrategy = keyResult.strategy;
// 解密请求数据(包含策略信息)
let requestBody = null;
let requestDecryptStrategy = null;
if (originalBody) {
try {
if (typeof originalBody === 'string') {
const parsed = JSON.parse(originalBody);
const decryptResult = DecryptStrategies.decrypt(parsed, timestampKey, true);
requestBody = decryptResult.data;
requestDecryptStrategy = decryptResult.strategy;
} else {
requestBody = originalBody;
}
} catch (e) {
requestBody = originalBody;
}
}
// 解密响应数据(包含策略信息)
let responseData = null;
try {
const text = await clonedResponse.text();
if (text) {
try {
responseData = JSON.parse(text);
} catch (e) {
responseData = text;
}
}
} catch (e) {
console.error('读取响应数据失败:', e);
}
const decryptResult = DecryptStrategies.decrypt(responseData, timestampKey, false);
const decryptedResponse = decryptResult.data;
const responseDecryptStrategy = decryptResult.strategy;
// 记录解密结果
const decryptedRecord = {
id: requestId,
url: url,
method: method,
uuid: uuid,
timestampKey: timestampKey,
keyStrategy: keyStrategy,
request: requestBody,
requestDecryptStrategy: requestDecryptStrategy,
response: decryptedResponse,
responseDecryptStrategy: responseDecryptStrategy,
timestamp: new Date().toISOString()
};
// 存储到页面上下文
decryptedData.addRequest(decryptedRecord);
// 输出到控制台
console.group('🔓 Fetch 解密 [' + method + '] ' + url);
console.log('🔑 密钥:', timestampKey, '(策略: ' + keyStrategy + ')');
if (requestDecryptStrategy) {
console.log('📤 请求:', requestBody, '(解密策略: ' + requestDecryptStrategy + ')');
} else {
console.log('📤 请求:', requestBody);
}
if (responseDecryptStrategy) {
console.log('📥 响应:', decryptedResponse, '(解密策略: ' + responseDecryptStrategy + ')');
} else {
console.log('📥 响应:', decryptedResponse);
}
console.log('📍 UUID:', uuid);
console.groupEnd();
} catch (error) {
console.error('❌ Fetch 解密过程出错:', error);
}
return response;
}).catch((error) => {
console.error('❌ Fetch 请求失败:', error);
return Promise.reject(error);
});
};
console.log('✅ [页面上下文] Fetch 拦截已设置');
console.log('✅ [页面上下文] originalFetch 类型:', typeof originalFetch);
console.log('✅ [页面上下文] window.fetch:', typeof window.fetch);
// 验证拦截是否真的生效
setTimeout(function() {
const fetchStr = window.fetch.toString();
if (fetchStr.includes('clonedResponse') || fetchStr.includes('requestId')) {
console.log('✅ [页面上下文] Fetch 拦截验证成功');
} else {
console.error('❌ [页面上下文] Fetch 拦截验证失败,可能被覆盖');
console.error(' 当前 fetch 函数:', fetchStr.substring(0, 100));
}
}, 500);
})();
// 暴露 API 供 DevTools 面板使用
window.__XHR_DECRYPT_EXTENSION__ = {
getDecryptedRequests: function() {
return decryptedData.getRequests();
},
clearDecryptedRequests: function() {
decryptedData.clear();
console.log('✅ 已清空解密记录');
}
};
console.log('✅ [页面上下文] 拦截脚本初始化完成');
console.log('✅ [页面上下文] 已拦截 XHR:', typeof XMLHttpRequest !== 'undefined');
console.log('✅ [页面上下文] 已拦截 Fetch:', typeof fetch !== 'undefined');
// 测试一下拦截是否真的工作
setTimeout(function() {
console.log('🧪 [页面上下文] 测试:检查拦截状态');
console.log('🧪 [页面上下文] XMLHttpRequest.prototype.open:', typeof XMLHttpRequest.prototype.open);
console.log('🧪 [页面上下文] window.fetch:', typeof window.fetch);
// 尝试创建一个测试请求(仅用于验证)
try {
const testXhr = new XMLHttpRequest();
console.log('🧪 [页面上下文] 测试:可以创建 XMLHttpRequest 实例');
} catch (e) {
console.error('🧪 [页面上下文] 测试:无法创建 XMLHttpRequest:', e);
}
}, 1000);
})();
`;
// 注入到页面上下文
// 必须在页面脚本运行之前注入,否则无法拦截
function injectToPage() {
try {
// 方式1尝试注入到 head
if (document.head) {
document.head.appendChild(script.cloneNode(true));
console.log('✅ 拦截脚本已注入到 head');
return;
}
// 方式2注入到 documentElement
if (document.documentElement) {
document.documentElement.appendChild(script.cloneNode(true));
console.log('✅ 拦截脚本已注入到 documentElement');
return;
}
// 方式3如果都不行等待 DOM 加载
console.warn('⚠️ DOM 未准备好,等待加载...');
const checkInterval = setInterval(function () {
if (document.head || document.documentElement) {
clearInterval(checkInterval);
injectToPage();
}
}, 50);
// 超时保护
setTimeout(function () {
clearInterval(checkInterval);
console.error('❌ 注入超时DOM 可能无法加载');
}, 5000);
} catch (e) {
console.error('❌ 注入脚本失败:', e);
}
}
// 立即尝试注入(不等待)
try {
// 如果 DOM 已准备好,立即注入
if (document.head || document.documentElement) {
injectToPage();
} else {
// 如果还没准备好,使用多种方式等待
console.log('⏳ DOM 未准备好,准备注入...');
// 方式1等待 DOMContentLoaded
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function () {
console.log('📄 DOMContentLoaded 触发,开始注入');
injectToPage();
}, { once: true });
}
// 方式2也尝试立即注入某些浏览器允许
setTimeout(function () {
if (document.head || document.documentElement) {
console.log('⏱️ 延迟注入尝试');
injectToPage();
}
}, 0);
// 方式3监听 readystatechange
document.addEventListener('readystatechange', function () {
if (document.readyState !== 'loading') {
console.log('📄 readystatechange 触发readyState:', document.readyState);
injectToPage();
}
}, { once: true });
}
} catch (e) {
console.error('❌ 注入过程出错:', e);
}
// 在 Content Script 中监听来自页面上下文的事件
window.addEventListener('__XHR_DECRYPTED__', function (event) {
if (event.detail) {
decryptedRequests.push(event.detail);
if (decryptedRequests.length > 100) {
decryptedRequests.shift();
}
// 发送到 background
if (typeof chrome !== 'undefined' && chrome.runtime) {
chrome.runtime.sendMessage({
type: 'DECRYPTED_REQUEST',
data: event.detail
});
}
}
});
// 监听来自 popup 的消息
if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.onMessage) {
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
if (message.action === 'getDecryptedRequests') {
// 直接返回 content script 中存储的数据
// content script 会从页面事件中接收更新
sendResponse({ data: decryptedRequests });
return true;
} else if (message.action === 'clearDecryptedRequests') {
decryptedRequests = [];
// 清除页面上下文的记录
const clearScript = document.createElement('script');
clearScript.textContent = `
(function() {
if (window.__XHR_DECRYPT_EXTENSION__) {
window.__XHR_DECRYPT_EXTENSION__.clearDecryptedRequests();
}
})();
`;
document.documentElement.appendChild(clearScript);
clearScript.remove();
sendResponse({ success: true });
}
});
}
// 暴露 API 供 popup 使用Content Script 上下文)
window.__XHR_DECRYPT_EXTENSION__ = {
getDecryptedRequests: function () {
// 返回 content script 中存储的数据
return decryptedRequests;
},
clearDecryptedRequests: function () {
decryptedRequests = [];
// 清除页面上下文的记录
const clearScript = document.createElement('script');
clearScript.textContent = `
(function() {
if (window.__XHR_DECRYPT_EXTENSION__) {
window.__XHR_DECRYPT_EXTENSION__.clearDecryptedRequests();
}
})();
`;
document.documentElement.appendChild(clearScript);
clearScript.remove();
}
};
console.log('✅ Content Script 已启动');
console.log('📊 Content Script 当前记录数:', decryptedRequests.length);
console.log('📊 Content Script document.readyState:', document.readyState);
console.log('📊 Content Script 准备注入拦截脚本...');
console.log('📊 Content Script window.location:', window.location.href);
// 立即检查是否已经注入成功(某些情况下可能已经注入)
try {
const testScript = document.createElement('script');
testScript.textContent = `
(function() {
if (window.__XHR_DECRYPT_EXTENSION__) {
console.log('✅ [页面上下文] 拦截对象已存在');
} else {
console.warn('⚠️ [页面上下文] 拦截对象不存在');
}
if (window.__XHR_DECRYPT_DATA__) {
console.log('✅ [页面上下文] 数据对象已存在');
} else {
console.warn('⚠️ [页面上下文] 数据对象不存在');
}
})();
`;
if (document.head || document.documentElement) {
(document.head || document.documentElement).appendChild(testScript);
testScript.remove();
}
} catch (e) {
console.error('❌ 检查注入状态失败:', e);
}
// 延迟检查注入是否成功
setTimeout(function () {
// 通过 DevTools API 检查
if (typeof chrome !== 'undefined' && chrome.devtools && chrome.devtools.inspectedWindow) {
chrome.devtools.inspectedWindow.eval('typeof window.__XHR_DECRYPT_EXTENSION__', function (result, isException) {
if (isException) {
console.warn('⚠️ 无法访问页面上下文,可能注入失败。错误:', result);
} else {
if (result === 'object') {
console.log('✅ 拦截脚本注入成功,页面上下文对象存在');
} else {
console.warn('⚠️ 拦截脚本可能未注入成功,页面上下文对象类型:', result);
}
}
});
} else {
// 如果没有 DevTools使用其他方式检查
const checkScript = document.createElement('script');
checkScript.textContent = `
(function() {
console.log('🔍 [页面上下文] 检查拦截状态...');
console.log('🔍 [页面上下文] __XHR_DECRYPT_EXTENSION__:', typeof window.__XHR_DECRYPT_EXTENSION__);
console.log('🔍 [页面上下文] __XHR_DECRYPT_DATA__:', typeof window.__XHR_DECRYPT_DATA__);
console.log('🔍 [页面上下文] XMLHttpRequest:', typeof XMLHttpRequest);
console.log('🔍 [页面上下文] fetch:', typeof fetch);
// 检查拦截是否真的工作
if (XMLHttpRequest.prototype.open.toString().includes('_method')) {
console.log('✅ [页面上下文] XHR 拦截已生效');
} else {
console.warn('⚠️ [页面上下文] XHR 拦截可能未生效');
}
if (window.fetch.toString().includes('clonedResponse') || window.fetch.toString().includes('requestId')) {
console.log('✅ [页面上下文] Fetch 拦截已生效');
} else {
console.warn('⚠️ [页面上下文] Fetch 拦截可能未生效');
}
})();
`;
if (document.head || document.documentElement) {
(document.head || document.documentElement).appendChild(checkScript);
checkScript.remove();
}
}
}, 3000);
}) ();