admin管理员组

文章数量:1194548

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
  }
});

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
  }
});
Share Improve this question edited May 2, 2015 at 1:43 Benjamin asked May 2, 2015 at 1:38 BenjaminBenjamin 3,9502 gold badges27 silver badges46 bronze badges 3
  • hi, is the index.html a popup window now for your code? I think it should be a popup instead of a new tab. And if you want to just not show the button in the new tab page, you can just add a url parameter like "?ispopup=false" in the link you open new tab when click the button. – Surely Commented May 2, 2015 at 3:18
  • Ah thanks, a friend of mine said the same thing - the URL parameter approach works well. I've added it as an answer! – Benjamin Commented May 2, 2015 at 3:56
  • Simply include it as a url parameter to the popup – Zig Mandel Commented May 2, 2015 at 13:09
Add a comment  | 

4 Answers 4

Reset to default 12

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)

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!

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';
    }
})();
chrome.tabs.getCurrent(function(tab) {
    if(tab == undefined)
        document.getElementById('mButton').style.display = 'inline-block';
});

I initially set the button's display: none; if the returned tab is undefined, means it's not a tab (so it is popup) and then I display button. You can reverse it of course.

======

Well the sending parameter also works, which in that case you won't need to add the query string in the manifest, just adding it in button's click listener would suffice.

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 index.html say index2.html, remove the button from index.html, use index2.html in the manifest and index.html for button click. :)

本文标签: javascriptHow can I determine if a Chrome extension is in a popup from the content scriptStack Overflow