如何确定 Chrome 扩展名是否在内容脚本的弹出窗口中?
How can I determine if a Chrome extension is in a popup from the content script?
背景
我有一个 Chrome 扩展程序,带有浏览器操作以在新选项卡中启动 index.html
。
我想更新扩展以先在 popup 中打开 index.html
,然后包含一个按钮,用户可以单击该按钮以选择性地在新选项卡中打开该应用程序。
我不希望此按钮在不是弹出窗口时显示(因为它没有意义),这意味着内容脚本需要知道它是否是弹出窗口才能显示按钮。
问题
这是一个由两部分组成的问题:
- Chrome 扩展弹出窗口如何知道它是一个弹出窗口?
- 如何在呈现弹出窗口之前将该信息传递给内容脚本?
我试过的
我试过在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) {});
});
};
然后在我的内容脚本中,我收听消息,然后在正文中添加一个 class:
// 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.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';
最后,如果是弹出窗口,请在正文中添加一个class:
$('body').toggleClass('popup', isPopup)
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.html
说 index2.html
,从 index.html 中删除按钮,在清单中使用 index2.html 并使用 index.html按钮点击。 :)
在清单文件中添加一个散列到 url:
"browser_action": {
"default_popup": "index.html#popup"
}
在JavaScript中:
if(location.hash == 'popup')
// do something awesome!
我需要类似的东西,因为我想为所有脚本类型创建一些交叉兼容的代码。
我发现这很管用。
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 扩展程序,带有浏览器操作以在新选项卡中启动 index.html
。
我想更新扩展以先在 popup 中打开 index.html
,然后包含一个按钮,用户可以单击该按钮以选择性地在新选项卡中打开该应用程序。
我不希望此按钮在不是弹出窗口时显示(因为它没有意义),这意味着内容脚本需要知道它是否是弹出窗口才能显示按钮。
问题
这是一个由两部分组成的问题:
- Chrome 扩展弹出窗口如何知道它是一个弹出窗口?
- 如何在呈现弹出窗口之前将该信息传递给内容脚本?
我试过的
我试过在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) {});
});
};
然后在我的内容脚本中,我收听消息,然后在正文中添加一个 class:
// 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.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';
最后,如果是弹出窗口,请在正文中添加一个class:
$('body').toggleClass('popup', isPopup)
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.html
说 index2.html
,从 index.html 中删除按钮,在清单中使用 index2.html 并使用 index.html按钮点击。 :)
在清单文件中添加一个散列到 url:
"browser_action": {
"default_popup": "index.html#popup"
}
在JavaScript中:
if(location.hash == 'popup')
// do something awesome!
我需要类似的东西,因为我想为所有脚本类型创建一些交叉兼容的代码。
我发现这很管用。
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';
}
})();