【问题标题】:How can I determine if a Chrome extension is in a popup from the content script?如何确定 Chrome 扩展程序是否在内容脚本的弹出窗口中?
【发布时间】:2015-05-02 01:38:31
【问题描述】:

背景

我有一个带有浏览器操作的 Chrome 扩展程序,可以在新标签页中启动 index.html

我想更新扩展程序以首先在 popup 中打开 index.html,然后包含一个按钮,用户可以单击以选择在新标签中打开应用程序。

我不希望这个按钮在它不是弹出窗口时显示(因为它没有意义),这意味着内容脚本需要知道它是否是弹出窗口才能显示按钮。

问题

这是一个两部分的问题:

  1. Chrome 扩展弹出窗口如何知道它是弹出窗口?
  2. 如何在呈现弹出窗口之前将该信息传递给内容脚本?

我的尝试

我尝试在background.js 中使用chrome.extension.getViews 来首先确定弹出窗口是否打开。然后,我向内容脚本发送一条消息,然后显示该按钮。但是我还没有让它工作 - views 始终是一个空数组,并且内容脚本似乎从未收到过消息。

以下是我的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"
}

这是我在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) {});  
  });
};

然后在我的内容脚本中,我监听消息,然后在正文中添加一个类:

// Listen for the message
chrome.extension.onMessage.addListener(function(msg, sender, sendResponse) {
  if (msg.action === 'popup_open') {
    // My code here to show the button
  }
});

【问题讨论】:

  • 嗨,index.html 现在是您的代码的弹出窗口吗?我认为它应该是一个弹出窗口而不是一个新标签。如果您不想在新标签页中显示按钮,您可以在单击按钮时打开新标签页的链接中添加一个 url 参数,如“?ispopup=false”。
  • 啊,谢谢,我的一个朋友也说了同样的话——URL 参数方法效果很好。我已将其添加为答案!
  • 只需将其作为 url 参数包含到弹出窗口中

标签: javascript google-chrome google-chrome-extension


【解决方案1】:

在与朋友交谈后,我发现了一个优雅的解决方案,它根本不涉及消息传递,甚至根本不涉及 background.js 脚本。

我可以在manifest.json 中指定?popup=true,并在我的扩展内容脚本中检查该参数。代码如下:

manifest.json 现在看起来像这样:

"browser_action": {
  "default_icon": {   
    "19": "img/icon19.png",
    "38": "img/icon38.png"
  },

  "default_title": "Super Simple Tasks",

  "default_popup": "index.html?popup=true"
}

我的内容脚本中的以下代码(取自this answer)检查?popup=true。值得注意的是,该函数可以处理由& 字符分割的多个URL 参数。

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';

最后,如果是弹出框,则在 body 中添加一个类:

$('body').toggleClass('popup', isPopup)

【讨论】:

    【解决方案2】:

    在清单文件中为 url 添加一个哈希:

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

    在 JavaScript 中:

    if(location.hash == 'popup') 
        // do something awesome!
    

    【讨论】:

    • 一个小调整:应该是 if (location.hash == '#popup')
    【解决方案3】:

    我需要类似的东西,因为我想为所有脚本类型创建一些交叉兼容的代码。

    我发现这很有效。

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

    【讨论】:

    • 不幸的是,这无法区分弹出窗口和 moz-extension://hash 之类的扩展页面之间的区别
    • 这绝对很棒。谢谢你分享这个。不过有一件事 - WEB 与 CONTENT_SCRIPT 不一样(或者这里的网络是什么?)还有 OPTIONS 页面呢?
    • @bhavya_w 如果您还使用脚本标签或 eval 将脚本注入到实际的 WEBPAGE 中,这将是。我不确定 OPTIONS。
    【解决方案4】:
    chrome.tabs.getCurrent(function(tab) {
        if(tab == undefined)
            document.getElementById('mButton').style.display = 'inline-block';
    });
    

    如果返回的选项卡是undefined,我最初设置按钮的display: none;,表示它不是选项卡(所以它是弹出窗口)然后我显示按钮。你当然可以反过来。

    ======

    发送参数也可以,在这种情况下,您不需要在清单中添加查询字符串,只需将其添加到按钮的单击侦听器中就足够了。

    btn.addEventListener('click', function() {
        chrome.tabs.create({url: "index.html?popup=false"});
    });
    

    然后是同样的过程(读取查询字符串并进行比较等)。

    ======

    或者,您可以复制index.htmlindex2.html,从 index.html 中删除按钮,使用清单中的 index2.html 和 index.html 来单击按钮。 :)

    【讨论】:

      猜你喜欢
      • 2012-05-07
      • 2011-08-31
      • 2017-12-24
      • 2012-12-23
      • 2013-10-12
      • 2012-02-17
      • 2017-02-15
      • 2023-01-02
      • 2011-09-27
      相关资源
      最近更新 更多