I'm struggling with this for hours now..
I'm currently writing a Chrome Extensions, its goal is to automate click on a website.
Since the website is checking for the isTrusted
property, I have to emulate the click from chrome.debugger
(Or at least, that the only way I found).
I have actually no one, but two problems.
1st one: If I set opts.x / opts.y "dynamically", it results in this error:
Uncaught (in promise) Error: {"code":-32602,"data":"Failed to deserialize params.x - BINDINGS: mandatory field missing at position 55","message":"Invalid parameters"}
2nd one: Tried putting the value directly, it's working, but it is not clicking on the provided coordinates, it's actually clicking lower.
This is my code:
background.js
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
if (msg.text == "click that button please") {
let infos = []
chrome.debugger.attach({tabId: sender.tab.id}, "1.2", function() {
let clicked = false
let x = Math.floor(msg.button.offsetLeft msg.button.offsetWidth / 2)
let y = Math.floor(msg.button.offsetTop msg.button.offsetHeight / 2)
opts = {type: "mousePressed", button: "left", x: x, y: y, clickCount: 1}
chrome.debugger.sendCommand({tabId: sender.tab.id}, "Input.dispatchMouseEvent", opts)
.then((e) => {
infos.push(e)
});
opts.type = "mouseReleased"
chrome.debugger.sendCommand({tabId: sender.tab.id}, "Input.dispatchMouseEvent", opts)
.then((e) => {
infos.push(e)
});
})
sendResponse({clicked: infos});
} else {
sendResponse({error: 404});
}
return true;
});
content.js
var buttons = {
"market": "#app > div > div.mt-3 > div.d-flex.justify-content-between.align-items-baseline > div:nth-child(2) > button"
}
}
!async function() {
window.onclick = function(e) {
console.log(e.target, e)
}
let target = document.querySelector(buttons['market']); // Working
console.log(target);
chrome.runtime.sendMessage({text: "click that button please", button: target})
.then((result) => {
console.log('Did it clicked?', result); // result = []
});
}();
manifest.json
{
"name": "xxx",
"description": "xxx",
"version": "0.0.1",
"manifest_version": 3,
"author": "Me",
"host_permissions": [
"https://*.xxx.xxx/*"
],
"permissions": [
"debugger",
"activeTab",
"tabs",
"scripting"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"matches": ["https://*.xxx.xxx/*"],
"js": ["content.js"]
}]
}
CodePudding user response:
You can't send DOM elements via messages. It's not serializable, so an empty object arrives and your formula results in a NaN
, i.e. not a number.
Solution: send an object/array with the element's coordinates.
Your use of offsetXXX props is incorrect, AFAICT, as the documentation for dispatchMouseEvent says x/y are relative to the viewport.
Solution: getBoundingClientRect().
const bb = elem.getBoundingClientRect();
chrome.runtime.sendMessage({x: bb.left, y: bb.top});
P.S. An alternative solution is to replace EventTarget.prototype.addEventListener or onclick
setter of Document.prototype in the MAIN world of the page, so that your listener will call the site's listener passing a Proxy(event, handler) where handler returns true for isTrusted
.