v_jstools/background.js
2022-12-01 02:10:21 +08:00

226 lines
8.9 KiB
JavaScript

// importScripts("./tools/babel_asttool.js", "./tools/cheerio.js", "./tools/replacer.js", "./tools/error_front.js")
// chrome.contextMenus.create({
// id: "v_menu",
// title: "打开 v_jstools 动态调试",
// contexts: ['all']
// });
// chrome.contextMenus.onClicked.addListener(function(info, tab) {
// if (info.menuItemId == "v_menu") {
// AttachDebugger();
// }
// });
// background.js
chrome.contextMenus.create({
title: "打开 ast 动态挂钩",
contexts: ['all'],
onclick: function(){
ast_dyn_hook = true
AttachDebugger();
}
});
chrome.contextMenus.create({
title: "打开 html 调试拷贝",
contexts: ['all'],
onclick: function(){
html_copy = true
AttachDebugger();
}
});
chrome.contextMenus.create({
title: "修改发送请求",
contexts: ['all'],
onclick: function(){
init_edit_function()
edit_request = true
AttachDebugger();
}
});
function init_edit_function(){
chrome.storage.local.get(["config-request_hook"], function (res) {
try{
window.eval(res["config-request_hook"])
}catch(e){
change_request = undefined;
console.log('evaluate code init change_request func err.', e)
}
})
}
var ast_dyn_hook = false
var html_copy = false
var edit_request = false
function close_debugger(){
attached = false
ast_dyn_hook = false
html_copy = false
edit_request = false
}
function sendCommand(method, params, source, chainfun){
chrome.debugger.sendCommand(source, method, params, function(result){
if (chrome.runtime.lastError) {
console.error('chrome.runtime.lastError', chrome.runtime.lastError)
if (chrome.runtime.lastError.message.indexOf('Cannot access a chrome://') != -1){ close_debugger() }
} else { if (chainfun){ chainfun(result) } }
});
}
function fillresponse(params, source, body){
sendCommand("Fetch.fulfillRequest", {
requestId: params.requestId, responseCode: params.responseStatusCode, responseHeaders: params.responseHeaders,
body: body, // body 只能传 base64(指定代码)
}, source);
}
var save_cache = {}
chrome.debugger.onEvent.addListener(function (source, method, params){
switch(method){
case "Fetch.requestPaused":
var itheaders = params.responseHeaders;
if (itheaders && itheaders.find(function(v){return v.name == "Location"})) {
sendCommand("Fetch.continueRequest", { requestId: params.requestId, url: itheaders.value }, source);
break; }
if ((params.responseStatusCode || params.responseErrorReason)) {
if (params.responseErrorReason) {
sendCommand("Fetch.failRequest", { requestId: params.requestId, errorReason: params.responseErrorReason }, source);
break; }
sendCommand("Fetch.getResponseBody", { requestId: params.requestId }, source, function(result){
var fillfunc = fillresponse.bind(null, params, source)
chrome.storage.local.get(["config-fetch_hook"], function (res) {
if (!result.body){ fillfunc(result.body); return }
// save html
if (html_copy){
if ( params.resourceType == 'Script'
|| params.resourceType == 'Document'
|| params.resourceType == 'Stylesheet'
|| params.resourceType == 'Image'
|| params.resourceType == 'Font'
|| params.resourceType == 'Other'
){
if (params.resourceType == 'Script'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
if (params.resourceType == 'Document'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
if (params.resourceType == 'Stylesheet'){ var save_info = decodeURIComponent(escape(atob(result.body))) }
if (params.resourceType == 'Image'){ var save_info = result.body }
if (params.resourceType == 'Font'){ var save_info = result.body }
if (params.resourceType == 'Other'){ var save_info = result.body }
function save_html_info(save_info, type, url){
save_cache[url] = {data: save_info, type: type}
}
save_html_info(save_info, params.resourceType, params.request.url)
console.log(params.resourceType, params.request.url)
}
}
// ast hook
if (ast_dyn_hook){
if ( params.resourceType == 'Script'
|| params.resourceType == 'Document'
){
try{
var respboby = decodeURIComponent(escape(atob(result.body)))
var replacer = eval((res["config-fetch_hook"]||'')+';fetch_hook')
if (params.resourceType == 'Script'){ var replbody = (replacer(respboby, params.request.url)) }
if (params.resourceType == 'Document'){ var replbody = (html_script_replacer(respboby, replacer, params.request.url)) }
fillfunc(btoa(unescape(encodeURIComponent(replbody))))
return }
catch(e){
send_error_info_to_front(e.stack, currtab.tabId, params.request.url) }
}
}
fillfunc(result.body) // body 只能传 base64(指定代码)
})
return
});
break;
}else{
var options = { requestId: params.requestId }
if (edit_request){
var { url, method, postData, headers } = params.request
var config = { url, method, postData, headers }
if (typeof change_request != 'undefined'){
try{
change_request(config)
}catch(e){
console.log('run change_request err.', e)
}
}
var { url, method, postData, headers } = config
function base64(str){
return CryptoJS.enc.Utf8.parse(str).toString(CryptoJS.enc.Base64)
}
// 这里处理更新操作
try{
if (url){
options.url = url
}
if (method){
options.method = method
}
if (postData){
options.postData = base64(postData)
}
if (headers){
var keys = Object.keys(headers)
var headers_list = []
for (var i = 0; i < keys.length; i++) {
headers_list.push({name:keys[i], value:headers[keys[i]]})
}
options.headers = headers_list
}
}catch(e){
console.log('set change request err.', e)
}
console.log('change request options:', options)
}
sendCommand("Fetch.continueRequest", options, source);
break;
}
}
})
chrome.debugger.onDetach.addListener(function(){
close_debugger()
})
var attached = false
var currtab;
function AttachDebugger() {
if (attached){ return }
save_cache = {};
attached = true
chrome.tabs.query(
{ active: true, currentWindow: true },
function (tabs) {
currtab = { tabId: tabs[0].id };
chrome.debugger.attach(currtab, "1.2", function () {
sendCommand("Network.enable", {}, currtab, function(){ sendCommand("Network.setCacheDisabled", {cacheDisabled: true}, currtab)} ) // 确保 Fetch.getResponseBody 一定能收到东西
sendCommand("Fetch.enable", { patterns: [
// Document, Stylesheet, Image, Media, Font, Script, TextTrack, XHR, Fetch, EventSource, WebSocket, Manifest, SignedExchange, Ping, CSPViolationReport, Preflight, Other
{urlPattern:"*",resourceType:"Script",requestStage:"Response"}, // 暂时先只 hook 少量携带 js 数据类型的请求
{urlPattern:"*",resourceType:"Document",requestStage:"Response"},
{urlPattern:"*",resourceType:"Stylesheet",requestStage:"Response"},
{urlPattern:"*",resourceType:"Image",requestStage:"Response"},
{urlPattern:"*",resourceType:"Font",requestStage:"Response"},
{urlPattern:"*",resourceType:"Other",requestStage:"Response"},
//
// {urlPattern:"*",resourceType:"XHR",requestStage:"Response"},
// {urlPattern:"*",resourceType:"Fetch",requestStage:"Response"},
// {urlPattern:"*",resourceType:"WebSocket",requestStage:"Response"},
{urlPattern:"*",resourceType:"Media",requestStage:"Response"},
{urlPattern:"*",resourceType:"Ping",requestStage:"Response"},
{urlPattern:"*",resourceType:"CSPViolationReport",requestStage:"Response"},
// {urlPattern:"*",resourceType:"TextTrack",requestStage:"Response"},
// {urlPattern:"*",resourceType:"EventSource",requestStage:"Response"},
// {urlPattern:"*",resourceType:"Manifest",requestStage:"Response"},
// {urlPattern:"*",resourceType:"SignedExchange",requestStage:"Response"},
// {urlPattern:"*",resourceType:"Preflight",requestStage:"Response"},
{urlPattern:"*",requestStage:"request"},
] }, currtab);
});
}
);
}
sub_logger()