Chrome插件获取页面请求内容
2024-01-10 22:51:16 868
先代理xhr/fetch对象
common.js
const shopee_get_product_10045487 = "/api/v4/pdp/get_pc";
const api_category_34a10fd6 = {};
api_category_34a10fd6[shopee_get_product_10045487] = "getProduct";
const rule_api_3ea67778 = {
shopee: [shopee_get_product_10045487],
};
const site_map_e68a0688 = {
"shopee.sg": "shopee",
"shopee.tw": "shopee",
"shopee.com.my": "shopee",
"shopee.ph": "shopee",
"shopee.co.th": "shopee",
"shopee.vn": "shopee",
"shopee.com.br": "shopee",
"shopee.co.id": "shopee",
"shopee.com.mx": "shopee",
};
page/interceptor.js
let config_2550ac5d = {
proxy_url: [],
setUrl: function (site) {
this.proxy_url = rule_api_3ea67778[site];
},
match: function (url) {
return this.proxy_url.filter((n) => url.indexOf(n) > -1).length > 0;
},
get: function (url) {},
};
config_2550ac5d.setUrl(site_map_e68a0688[window.location.hostname]);
function sendEvent(_type, _url, _data) {
window.postMessage(
{
type: "proxy-response",
text: {
site: site_map_e68a0688[window.location.hostname],
data: _data,
url: _url,
},
},
"*"
);
}
let proxy_interceptor = {
originalXHR: window.XMLHttpRequest,
pluginXHR: function () {
const xhr = new proxy_interceptor.originalXHR();
for (let attr in xhr) {
if (attr === "onreadystatechange") {
xhr.onreadystatechange = (...args) => {
this.onreadystatechange && this.onreadystatechange.apply(this, args);
};
this.onreadystatechange = null;
continue;
} else if (attr === " (...args) => {
if (config_2550ac5d.match(this.responseURL)) {
sendEvent("xhr", this.responseURL, this.responseText);
}
this. null;
continue;
} else if (attr === "open") {
this.open = (...args) => {
xhr.open && xhr.open.apply(xhr, args);
};
continue;
} else if (attr === "setRequestHeader") {
this.setRequestHeader = (...args) => {
xhr.setRequestHeader && xhr.setRequestHeader.apply(xhr, args);
};
continue;
} else if (attr === "send") {
this.send = (...args) => {
xhr.send && xhr.send.apply(xhr, args);
};
continue;
}
if (typeof xhr[attr] === "function") {
this[attr] = xhr[attr].bind(xhr);
} else {
Object.defineProperty(this, attr, {
get: () => xhr[attr],
set: (val) => (xhr[attr] = val),
enumerable: true,
});
}
}
},
originalFetch: window.fetch.bind(window),
pluginFetch: (url, t) =>
proxy_interceptor.originalFetch(url, t).then(async (response) => {
if (config_2550ac5d.match(url)) {
const data = await response.clone().json();
sendEvent("fetch", url, data);
}
return response;
}),
};
window.XMLHttpRequest = proxy_interceptor.pluginXHR;
window.fetch = proxy_interceptor.pluginFetch;
content-script.js
const common_script = document.createElement("script");
common_script.setAttribute("type", "text/javascript");
common_script.setAttribute("src", chrome.runtime.getURL("common.js"));
// 注意不能异步加载, 否则interceptor.js注入到页面时, 可能加载不到common.js
common_script.async = false;
document.documentElement.appendChild(common_script);
const interceptor_script = document.createElement("script");
interceptor_script.setAttribute("type", "text/javascript");
interceptor_script.setAttribute(
"src",
chrome.runtime.getURL("page/interceptor.js")
);
interceptor_script.async = false;
document.documentElement.appendChild(interceptor_script);
var data_cache = {};
window.addEventListener(
"message",
(event) => {
if (event.source !== window) {
return;
}
if (event.data.type && event.data.type === "proxy-response") {
let temp;
if (typeof event.data.text === "string") {
temp = JSON.parse(event.data.text);
} else {
temp = event.data.text;
}
let key = Object.keys(api_category_34a10fd6).filter((url) => temp.url.indexOf(url) > -1);
data_cache[api_category_34a10fd6[key]] = event.data.text;
}
},
false
);
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.action === "get_title_description") {
sendResponse(data_cache);
}
});
service-worker.js
chrome.scripting.getRegisteredContentScripts(
{ ids: ["testing-scripts-gen"] },
async (scripts) => {
if (scripts && scripts.length) {
await chrome.scripting.unregisterContentScripts({
ids: ["testing-scripts-gen"],
});
}
chrome.scripting.registerContentScripts([
{
id: "testing-scripts-gen",
// 如content-script依赖其他js, 则需要在此写明, 不能使用import等模块关键字
js: ["./content-script.js", "./common.js"],
matches: [
"*://shopee.sg/*",
"*://shopee.tw/*",
"*://shopee.com.my/*",
"*://shopee.ph/*",
"*://shopee.co.th/*",
"*://shopee.vn/*",
"*://shopee.com.br/*",
"*://shopee.co.id/*",
"*://shopee.com.mx/*"
],
runAt: "document_start",
allFrames: true,
},
]);
}
);
popup.js
chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
chrome.tabs.sendMessage(
tabs[0].id,
{action: "get_title_description"},
function (data) {
if (data?.getProduct) {
parseGetProduct(data.getProduct)
}
}
);
});
流程
- xhr代理对象拦截到指定url的请求后, 将请求内容发送到
content-script
content-script
接收到内容, 将其缓存起来popup
向content-script
发送消息content-script
响应消息, 将缓存的请求内容返回给popup