How to determine if there is a Chrome extension in the popup from the content script?
Background
I have a Chrome extension with a browser action to launch index.html
in a new tab.
I would like to first update the extension to open index.html
in a popup and then enable a button that users can click to choose to open the application in a new tab.
I don't want this button to show when it was not a popup (since that doesn't make sense), which means the content script needs to know if it is a popup in order to show the button.
Questions
This is a two-part question:
- How does a chrome extension popup know its popup?
- How do I pass this information to the content script before the popup is displayed?
What i tried
I tried to use chrome.extension.getViews
in background.js
to determine if the popup is open. Then I post a message to the content script, which then shows the button. However, I didn't get it to work - views
it is always an empty array and the message never seems to be accepted by the content of the script.
Here are the relevant parts of my file manifest.json
:
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": {
"19": "img/icon19.png",
"38": "img/icon38.png"
},
"default_title": "Super Simple Tasks",
"default_popup": "index.html"
}
And here's what I tried in background.js
:
// Get all popups
var views = chrome.extension.getViews({ type: "popup" });
// Send a message if there is a popup
if (views.length > 0){
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
chrome.tabs.sendMessage(tabs[0].id, {action: "popup_open"}, function(response) {});
});
};
And then in my content script, I listen to the message and then add the class to the body:
// Listen for the message
chrome.extension.onMessage.addListener(function(msg, sender, sendResponse) {
if (msg.action === 'popup_open') {
// My code here to show the button
}
});
source to share
After talking with a friend, I came across an elegant solution that doesn't involve messaging or even a background.js
script at all.
I can point ?popup=true
to manifest.json
and check this parameter in my extension script. Here's the code:
manifest.json
now looks like this:
"browser_action": {
"default_icon": {
"19": "img/icon19.png",
"38": "img/icon38.png"
},
"default_title": "Super Simple Tasks",
"default_popup": "index.html?popup=true"
}
The following code in my content script (taken from this answer ) checks for ?popup=true
. It's worth noting that this function can handle multiple URL parameters separated by a character &
.
function getUrlParameter(sParam) {
var sPageURL = window.location.search.substring(1);
var sURLVariables = sPageURL.split('&');
for (var i = 0; i < sURLVariables.length; i++) {
var sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] == sParam) {
return sParameterName[1];
}
}
}
var isPopup;
isPopup = getUrlParameter('popup') === 'true';
Finally, add a class to the body if it pops up:
$('body').toggleClass('popup', isPopup)
source to share
I needed something like this as I wanted to create some cross-compatible code for all script types.
I found this worked pretty well.
const SCRIPT_TYPE = (() => {
if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() === window) {
return 'BACKGROUND';
} else if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() !== window) {
return 'POPUP';
} else if (!chrome || !chrome.runtime || !chrome.runtime.onMessage) {
return 'WEB';
} else {
return 'CONTENT';
}
})();
source to share
chrome.tabs.getCurrent(function(tab) {
if(tab == undefined)
document.getElementById('mButton').style.display = 'inline-block';
});
I originally set the button display: none;
if the returned tab undefined
means it is not a tab (so it is a popup) and then I show the button. You can, of course, cancel it.
======
Well, the submit parameter also works, which in this case you won't need to add the query string to the manifest, just add it to the button to listen to the button.
btn.addEventListener('click', function() {
chrome.tabs.create({url: "index.html?popup=false"});
});
And then the same process (reading the query string and comparing, etc.).
======
Alternatively, you can make a copy of the index.html
say index2.html
, remove the button from index.html, use index2.html in the manifest, and index.html for the button clicked. :)
source to share