问题
I inject content scripts into websites programmatically using browser.tabs.executeScript
. This will return a Promise, but in case of its rejection there seems to be no way of differentiating between the following 2 cases:
- The content script couldn't be injected (i.e. for missing host permission)
- An error occured on script updateparsingend:update(but the script was being injected)
I'm only interested in whether the script was being injected or not.
The argument passed to the catch
is an Error object.
catch(e => console.log(e.toString())
will output the error message, which can either be a reason for an injection failure (i.e. Missing host permission
) or an error that occurred updatereading the scriptend:update.
browser.tabs.executeScript(tabId, {
file: '../path/to/content-script.js',
frameId: 0,
runAt: 'document_idle'
})
.catch(e => console.log(e.toString()));
So, for example if the content script is as follows:
window.document.body.addEventListener('click', e => console.log('clicked body'), false);
bla.bla();
then the Promise is being rejected, since bla.bla
is undefined - but the script was being injected successfully.
In case the content script couldn't be injected I'd like to notify the user with the corresponding error message. But when an error occurred updatethat is unrelated to whether the script could be injectedend:update, while the script was being injected, I don't want to notify the user, but handle it silently. Is there a way to differentiate between those 2 cases?
EDIT: I came up with an indirect solution: In case the returned Promise was rejected I try to send a message to the content script. If this fails then the background script "knows" that no content script was being injected -> notify user.
回答1:
This is how the Promise works....
browser.tabs.executeScript(tabId, {
file: '../path/to/content-script.js',
frameId: 0,
runAt: 'document_idle'
})
.catch(e => console.log(e.toString()));
catch
in above will catch errors if the tabs.executeScript
failed to inject. It may also show some errors when parsing the file in order to inject, if the JS file has parsing errors (invalid JS). It has nothing to do with what '../path/to/content-script.js' will be doing afterwards.
So once it was injected, then above Promise is fulfilled.
If the injected script has a sync return, then it can be received by the tabs.executeScript
via then()
e.g.
browser.tabs.executeScript(tabId, {
file: '../path/to/content-script.js',
frameId: 0,
runAt: 'document_idle'
})
.then(result => {})
.catch(e => console.log(e.toString()));
In case of async functions such as .addEventListener
which will happen later, then is nothing returned to tabs.executeScript
To catch errors in the content scripts, you can generate the error message within the content script or send a message to background script i.e. sendMessage
& onMessage.addListener
tabs.executeScript()
A Promise that will be fulfilled with an array of objects, representing the result of the script in every injected frame.
The result of the script is the last evaluated statement, which is similar to what would be output (the results, not any console.log() output) if you executed the script in the Web Console. For example, consider a script like this:var foo='my result';foo;
browser.tabs.executeScript(tabId, {
file: '../path/to/content-script.js',
frameId: 0,
runAt: 'document_idle'
})
.then(result => {
// result is returned by the Promise
if (result === []) {
// it was fine but there was nothing to return
}
else if (result[0]) {
// result[0] is return from the promise
}
})
.catch(e => console.log(e.toString()));
Now if you want a return (it must be sync or else you have to tie it to another Promise), return something from '../path/to/content-script.js'
来源:https://stackoverflow.com/questions/56913671/tabs-executescript-how-can-i-tell-if-content-script-was-being-injected