浏览器插件向指定的框架中运行js方案

动作开发 · 941 次浏览
涛涛涛 创建于 2天13小时前

通过(Runtime.ExecutionContextId)执行上下文ID(contextId)就可以获取主文档的js运行环境或框架js运行环境, 方案不只一种

async function 运行js代码及上传文件 (e) {
            let { tabId: t, iframeselector: r, fileInputselector: o, jsdm: h ,files:g } = e
            var n={tabId: t}
            let a= await chrome.debugger.attach(n, "1.3");
            let l = await chrome.debugger.sendCommand(n, "DOM.getDocument", {});
            l = await chrome.debugger.sendCommand(n,"DOM.querySelector", {"nodeId": l.root.nodeId,"selector":r});
            l = await chrome.debugger.sendCommand(n,"DOM.querySelector", {"nodeId": l.nodeId+1,"selector":o});     //跨框架nodeId=nodeId+1
            a= await chrome.debugger.sendCommand(n, 'DOM.resolveNode',{ nodeId :l.nodeId });
            a=a.object.objectId.split(".")[1];      //找到跨框架运行js代码(Runtime.evaluate)的上下文ID
            await chrome.debugger.sendCommand(n, 'Runtime.evaluate', {expression: h,contextId : a });   //在框架里运行js代码
            await chrome.debugger.sendCommand(n, "DOM.setFileInputFiles", {"nodeId":l.nodeId,"files":g});   //上传文件路径
}

//参数说明
tabId:  调试目标
iframeselector:  iframe框架的css选择器
fileInputselector:  文件框的css选择器
jsdm: js代码
files:  需要上传文件的路径数组


//参数示例
{
tabId: 123
iframeselector:"#iframe"
fileInputselector:"#fileInput"
jsdm:"document.querySelector('#textInput').value='世界'; console.log('测试'); "
files:["C:/Users/Administrator/Desktop/11.png"]
}

原理说明:

1.通过DOM.getDocument
   chrome.debugger.sendCommand({tabId: tabId}, 'DOM.getDocument',{},(result) => {console.log(result);})----->获取顶层框架(tab页)的nodeId

2.通过DOM.querySelector(第1次用)
   例如iframeCSS选择器(#iframe)   
     chrome.debugger.sendCommand({tabId: tabId}, 'DOM.querySelector',{nodeId: nodeId,selector:"#iframe"},(result) => {console.log(result);})--->>获取到iframe的CSS选择器的nodeId,再nodeId=nodeId+1这样就获取跨框架的nodeId

3.通过DOM.querySelector(第2次用)
     例如文件框CSS选择器(#fileInput)   注意这个是重点(跨框架的nodeId):nodeId=nodeId+1
     chrome.debugger.sendCommand({tabId: tabId}, 'DOM.querySelector',{nodeId: nodeId,selector:"#fileInput"},(result) => {console.log(result);}) --->>获取到文件框CSS选择器的nodeId

4.通过DOM.resolveNode   (DOM.resolveNod 与  DOM.requestNode 它们可以将其参数值相互转换[这个是一个关键的步骤])
    chrome.debugger.sendCommand({tabId: tabId}, 'DOM.resolveNode',{ nodeId :nodeId },(result) => {console.log(result);})-------->获取到RemoteObject对象 
    其RemoteObject 对象中的objectId可以解析出一些东西 其中中间的这个数值(例如:5)就是需要找到的执行上下文ID的值(Runtime.ExecutionContextId),通过执行上下文ID(Runtime.ExecutionContextId)在运行js时,有重要作用,它可以直接指向框架的js运行环境,它与浏览器控制台的相通的,可以通过浏览器控制台相对应的框架中查到变量,函数等
   RemoteObject 对象格式如下:

{
    "className": "HTMLInputElement",
    "description": "input#fileInput",
    "objectId": "-6568665852511506130.5.5",这个中间值是非常有用  5  为执行上下文ID  executionContextId   Runtime.ExecutionContextId
    "subtype": "node",
    "type": "object"
 }

5.Runtime.evaluate
    chrome.debugger.sendCommand({ tabId: tabId }, 'Runtime.evaluate', {expression: "document.querySelector('#fileInput')",contextId : 5 (这里使用了那个中间值)},  function(response) {console.log(response);});
        // js代码使用CSS选择器元素本身(如:document.querySelector('#fileInput')  )------>可以返回RemoteObject——>执行上下文ID
        // js代码使用CSS选择器元素属性值(如:document.querySelector('#fileInput').value  )------>返回属性值的数据   这点需要注意很重要
       

 

 

涛涛涛 最后更新于 2025/6/3

回复内容
暂无回复
回复主贴