Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I determine if a Chrome extension is in a popup from the content script?

Background

I have a Chrome extension with a browser action to launch index.html in a new tab.

I'd like to update the extension to open index.html in a popup first, and then include a button users can click to optionally open the app in a new tab.

I don't want this button to show when it's not a popup (since it wouldn't make sense), which means the content script needs to know whether it is a popup in order to show the button.

Questions

This is a two part question:

  1. How does a Chrome extension popup know it's a popup?
  2. How do I pass that information to a content script before the popup is rendered?

What I've tried

I've tried to use chrome.extension.getViews in background.js to firstly determine if a popup is open. Then, I send a message to the content script which then shows the button. However I haven't gotten it to work - views is always an empty array, and the message doesn't seem to ever be received by the content script.

Here are the relevant parts of my manifest.json file:

"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've been trying in my 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 for the message and then add a 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
  }
});
like image 824
Benjamin Humphrey Avatar asked May 02 '15 01:05

Benjamin Humphrey


3 Answers

After talking with a friend I discovered an elegant solution that doesn't involve messaging or even a background.js script at all.

I can specify ?popup=true in manifest.json and check for that parameter in my extension's content 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. Worth noting that this function can handle multiple URL parameters split by the & 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's a popup:

$('body').toggleClass('popup', isPopup)
like image 161
Benjamin Humphrey Avatar answered Sep 22 '22 21:09

Benjamin Humphrey


In the manifest file add a hash to the url:

"browser_action": {
  "default_popup": "index.html#popup"
}

In JavaScript:

if(location.hash == 'popup') 
    // do something awesome!
like image 43
Thoran Avatar answered Sep 25 '22 21:09

Thoran


I needed something similar as i wanted to create some cross-compatible code for all script types.

I found that this worked quite 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';
    }
})();
like image 25
Chad Scira Avatar answered Sep 24 '22 21:09

Chad Scira