is there a way to stop chrome.scripting.executeScript
?
I have this code
const onClick = () => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const activeTabId = tabs[0].id;
chrome.scripting.executeScript({
target: { tabId: activeTabId },
args: [DURATION],
func: script,
});
});
// some code...
}
I was searching since 2 days all over the web and I am not able to find a way to stop this script on user interaction.
One way I found is by passing the state on user interaction but it is triggering the script once again. please see the below code
function Popup() {
const [isActive, setActive] = useState(false);
const [timer, setTimer] = useState(0);
const [stop, setStop] = useState(false);
const buttonRef = useRef();
const onClick = () => {
setStop((x) => !x); // change
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const activeTabId = tabs[0].id;
chrome.scripting.executeScript({
target: { tabId: activeTabId },
args: [DURATION, stop], // passing the state here
func: script,
});
});
....
onClick
is from the popup which changes the state stop
from false
to true
. But the problem is this toggling is calling the script again, please see onClick
(start/stop connecting) button below
When this button is clicked to stop, I need to find a way to stop executing the script. Any hints or ideas on this are appreciated.
Content of the script.js
function script(duration) {
setTimeout(() => {
const buttons = document.querySelectorAll('[aria-label^="Invite"]');
chrome.storage.local.set({ timer: buttons.length });
buttons.forEach((btn, idx) => {
setTimeout(() => {
const button = btn;
button.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' });
button.style.backgroundColor = 'red';
}, duration * 1000 * (idx + 1));
});
}, 200);
}
export default script;
When using executeScript
the code that was injected is running as an independent content script inside the page and no longer depends on executeScript, so you can't just "stop" it.
What you can stop is the loop in your injected code e.g. by checking a global variable before proceeding to the next iteration of a loop or in your case setTimeout
:
function injected() {
window.stopped = false;
document.querySelectorAll('button').forEach(el => {
setTimeout(() => {
// must be a literal value like `true`,
// otherwise it'll find an element with id="stopped"
if (window.stopped === true) return;
el.click();
}, 1000);
});
}
To set this variable you can call executeScript like this:
chrome.scripting.executeScript({
target: {tabId: .........},
func: () => { window.stopped = true },
});
A variation of this approach is to store all timers in an array:
function injected() {
if (!Array.isArray(window.timers)) window.timers = [];
document.querySelectorAll('button').forEach(el => {
window.timers.push(setTimeout(() => { el.click(); }, 1000));
});
}
...and then cancel them:
chrome.scripting.executeScript({
target: {tabId: .........},
func: () => {
window.timers.forEach(clearTimeout);
window.timers.length = 0;
}
});