0
浏览器插件注入-拦截页面对应请求
黄粱一梦2024-08-210
浏览器插件注入拦截页面请求
拦截效果
通过content-script.js
注入通过content.js
在宿主页面进行修改宿主页面的fetch
或者XHR
请求然后进行拦截
injected.js
文件
(function (xhr) {
var XHR = XMLHttpRequest.prototype;
var open = XHR.open;
var send = XHR.send;
let interceptList = [
// {
// url:'/getDouyinReverseNotify',eventName:'findDouyinOrder'
// },
{
url:'/getDispatchOrderCount',eventName: 'dispatchOrderCount'
}] // 需要拦截的请求路径
XHR.open = function (method, url) {
this._method = method;
this._url = url;
return open.apply(this, arguments);
};
XHR.send = function (postData) {
// console.log('xhr request:', this._method, this._url, postData);
let method = this._method
let url = this._url
// 适合的请求拦截 并发送给content.js
let intercept = interceptList.find(intercep => url.includes(intercep.url))
// console.log('intercept',intercept)
if (intercept) {
// 符合拦截情况的请求
// console.log('符合拦截列表的XHR请求 xhr request:', method, url, postData);
this.addEventListener('load', function () {
// sessionStorage['key'] = JSON.stringify(response); // 插件需要添加'storage'权限
// document.cookie
// localStorage['key']
// 将url和method传递给content.js然后进行判断是否是要进行相应的逻辑
window.postMessage({ type: 'xhr', data: this.response,url,method,eventName:intercept.eventName }, '*'); // 将响应发送到 content script
});
}
return send.apply(this, arguments);
};
})(XMLHttpRequest);
(function () {
let origFetch = window.fetch;
window.fetch = async function (...args) {
const response = await origFetch(...args);
console.log('fetch request:', args);
response
.clone()
.blob() // 此处需要根据不同数据调用不同方法,这里演示的是二进制大文件,比如音频
.then(data => {
// 对于二进制大文件可以创建为URL(blob:开头),供其它脚本访问
//sessionStorage['wave'] = URL.createObjectURL(data); // 插件需要添加'storage'权限
window.postMessage({ type: 'fetch', data: URL.createObjectURL(data) }, '*'); // send to content script
})
.catch(err => console.error(err));
return response;
}
})();
content-script.js
/**
* 需要拦截请求地址
* xhr request: POST http://c.eastisred.top/api/dispatchprocess/getDouyinReverseNotify
* */
console.log('content script start');
let pageConfig = {
voicePath:""
}
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log('接受到参数', request);
// 修改颜色
if (request.name == 'changeBg') {
changBg(request.url, request.opc)
}
else if (request.name == 'changeFont') {
setFontWeight(request.weight)
}else if (request.name == 'changeVoice') {
let { path } = request
pageConfig.voicePath = path
console.log('当前播放的音色地址',pageConfig.voicePath)
// setPlayVoice()
}
});
function changBg(url, opc) {
console.log('当前需要更改的地址', url);
let appmain = document.querySelector('.app-main')
console.log(appmain)
appmain.style.backgroundImage = `url('${url}')`
appmain.style.backgroundRepeat = 'no-repeat'
appmain.style.backgroundSize = 'cover'
let opcityDom = document.querySelector('.app-main>.w-full')
opcityDom.style.opacity = opc ? opc : 0.9
}
function setFontWeight(weight) {
document.querySelector('html').style.fontWeight = weight
}
/**
* inject injected script
*
* 开始拦截注入
*
* */
/**
*
* 抖音订单来了时候处理函数
*
* 抖音返回信息格式
*
* {
* "data": {
* "result": [],
* "count": 0
* },
* "success": true,
* "code": 0,
* "msg": "success",
* "timestamp": 1724039906925
* }
*
* */
let audio = null
function createAudio(src){
audio = new Audio()
audio.src = chrome.runtime.getURL(src || 'static/source/defaultvoice.WAV')
audio.addEventListener('canplaythrough', () => {
// 音频文件已经加载完毕,准备播放
audio.play().catch(error => {
console.error('播放音频时出错:', error);
});
});
audio.addEventListener('error', (event) => {
console.error('音频加载出错:', event);
});
}
function playAudio(src){
if(audio){
audio.src = chrome.runtime.getURL(src || 'static/source/defaultvoice.WAV')
audio.play()
}else {
createAudio(src)
}
}
function findDouyinOrderHandler(responseData){
let { data } = responseData
console.log('data_count----',data.data.count)
if(data && data.success && data.data.count > 0){
console.log('Blocked Order 需要播报音乐', '事件名称:',data.eventName,'method:', data.method,'请求地址:', data.url,)
playAudio()
return
}
playAudio()
}
/**
* @name dispatchOrderCountHandler
* @description 拦截分配订单的数量
*
* */
function dispatchOrderCountHandler(responseData){
let { data } = responseData
console.log('待处理订单数量',data.data,'\n播放订单音乐地址',pageConfig.voicePath || 'static/source/defaultvoice.WAV')
if(data && data.success && data.data > 0){
console.log('Blocked Order 需要播报音乐', '事件名称:',data.eventName,'method:', data.method,'请求地址:', data.url,)
playAudio(pageConfig.voicePath || 'static/source/defaultvoice.WAV')
return
}
// playAudio(pageConfig.voicePath || 'static/source/defaultvoice.WAV')
}
var s = document.createElement('script');
s.src = chrome.runtime.getURL('injected.js');
s.onload = function () {
this.remove();
};
(document.head || document.documentElement).appendChild(s);
// receive message from injected script
window.addEventListener('message', function (e) {
console.log('content script received:', e.data);
let { eventName } = e.data
switch (eventName) {
case 'findDouyinOrder':
findDouyinOrderHandler(e.data)
break;
case 'dispatchOrderCount':
dispatchOrderCountHandler(e.data)
}
});
manifest.json
配置文件
{
"name": "XFPlugin",
"version": "1.0.0",
"manifest_version": 3,
"author": "XF",
"description": "XFPlugin -- 5.25",
"icons": {
"16": "static/img/default-icon.png",
"19": "static/img/default-icon.png",
"38": "static/img/default-icon.png",
"48": "static/img/default-icon.png",
"128": "static/img/default-icon.png"
},
"background": {
"service_worker": "background.js",
"type": "module"
},
"action": {
"default_icon": {
"19": "static/img/default-icon.png"
},
"default_title": "XFPlugin",
"default_popup": "page/popup.html"
},
"content_scripts": [
{
"run_at": "document_start",
"all_frames": true,
"matches": [
"http://*/*",
"https://*/*"
],
"js": [
"content-script.js"
]
}
],
"web_accessible_resources": [
{
"resources": [
"static/source/defaultvoice.WAV",
"static/source/tianmeinvhai.WAV",
"static/source/labixiaoxin.WAV",
"static/source/keaiyangyang.WAV",
"static/source/koushao.mp3",
"static/source/dingdong.mp3",
"static/source/dingdong2.mp3",
"static/source/Freesound.wav",
"static/source/freesound.wav",
"static/source/caixukun.mp3",
"static/source/newSound.mp3",
"injected.js"
],
"matches": [
"http://*/*",
"https://*/*",
"<all_urls>"
],
"use_dynamic_url": true
}
],
"permissions": [
"tabs",
"webRequest",
"cookies",
"storage",
"<all_urls>"
],
"host_permissions": [
"http://*/*",
"https://*/*"
]
}
注意引入的静态资源文件需要在web_accessible_resources
字段的resource
字段中进行声明不然无法使用.
版权声明
本文系作者 @黄粱一梦 转载请注明出处,文中若有转载的以及参考文章地址也需注明。\(^o^)/~
Preview