Reputation: 567
I'm currently working on a chrome extension that uses a PageAction
. I want the PageAction
to inject a script and show a popup when clicked. I'm using the following code:
// Called when the user clicks on the page action.
chrome.pageAction.onClicked.addListener(function (tab) {
chrome.pageAction.setPopup({ tabId: tab.id, popup: "popup.html" });
chrome.pageAction.show(tab.id);
// No tabs or host permissions needed!
console.log(`We're on fire! Injecting script for ${tab.url}`);
chrome.tabs.executeScript({
file: 'js-libs/uuidv4.min.js'
});
chrome.tabs.executeScript({
file: 'js-libs/loglevel.min.js'
});
chrome.tabs.executeScript({
file: 'contentScript.js'
});
});
However, I am facing the following problem: Upon the first click, the scripts are injected (as confirmed by contentScript
-logs), but the popup doesn't show. Every following click then shows the popup.html
and the scripts don't seem to be injected again.
I would like to have the scripts injected and the popup show on the first click. Why is this not happening? Am I missing something obvious here?
Upvotes: 1
Views: 425
Reputation: 567
With the help of wOxxOm, I have been able to figure out a solution. Most importantly to note, pageAction.onClicked
only fires when no default_popup
is specified in the manifest.json
file or set through the pageAction.setPopup
function (thanks wOxxOm!).
The solution to having popup.html
pop up and the content script(s) injected, is to inject the content script(s) from within the popup.js
file. There's a caveat though: popup.js
executes every time the popup is opened, whereas the content script is persistent (for the current tab's window context). In order to avoid having popup.js
execute the content script every time popup.html
is opened, one may stick to the following pattern:
if (typeof scriptAlreadyExecuted === 'undefined') {
// scriptAlreadyExecuted is undefined, therefore let's execute our content script
var scriptAlreadyExecuted = true; // let's define this variable in window context to avoid re-executing the content script
executeContentScript();
else {
// scriptAlreadyExecuted in window range -> let's skip injecting script again.
console.log("No need to execute script again. Skipping script execution.")
}
An alternative would be to have the extension send a message that the background script listens to, but this would leave the problem of having to make sure that the content script doesn't execute twice.
A good alternative might be to use the webNavigation.onCompleted
-API in combination with event filters - I haven't tried this yet, as I haven't found out how to use CSS filters with this yet (which is easy with the PageStateMatcher
-API).
Hope this helps somebody!
Upvotes: 2