最近在重构插件,把之前和现在遇到的问题都记录一下吧,抛砖引玉,不对的地方,欢迎指正,: )
诉求起源
在编写的插件的时候,我们经常会出现仅允许在某些情况下才可以弹出插件窗口的需求,如:用户打开了非插件页面、书签页面甚至是其他的插件页面。 chrome允许我们在manifest指定browseraction和pageaction,但是假如我们直接在manifest文件中指定了这两个json字段的内容,那么弹出窗的内容将会被***『锁死』***。
解决方案
browseraction和pageaction都包含一个叫做setPopup的API,允许我们动态的设置插件的弹出窗内容,解决问题的关键点之一也就是这个API了。 而在何时执行setPopup,怎么执行setPopup是另外一个关键点,执行过早,插件交互一样会如同诉求起源的问题一样,『锁死』弹出内容。 下面分别以两种类型的插件为例,这两种类型的插件互斥,manifest仅允许存在其中之一(仅简单描述插件的形式区别,暂不展开描述):
browser_action
这种类型的插件的表现形式是在插件栏会多一个图标,适用于各种场景。
manifest 配置
关键点在于不设置默认的popup等信息。
{
"browser_action": {
"default_icon": "image/icon/app-128.png",
"default_title": "字段配置从package.json中读取"
}
}
示例代码
在插件的background.js中合适位置声明每个tab的行为,即可以做到动态展示插件内容。 个人倾向在tabs.onUpdated事件中每个tab的loading状态进行弹出内容绑定,简单可靠:即可以解决新的tab的事件绑定,又能防止同一个tab内容切换后,插件弹出内容没有变化的问题。
function checkCurrentTabIsCorrect (tab) {
return helper.isStandardLink(tab.url, ['http', 'https']);
}
function init () {
try {
//初始化事件绑定
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
switch (changeInfo.status) {
case 'loading':
chrome.browserAction.enable(tab.id);
//浏览器标签未初始化完毕时初始化插件图标
if (checkCurrentTabIsCorrect(tab)) {
// 绑定弹出窗内容A
chrome.browserAction.setPopup({'tabId' : tab.id, 'popup' : 'page/popup/main.html'});
} else {
// 用户打开其他的插件页面或者chrome内置页面
if (tab.url.indexOf('chrome-extension://' + chrome.runtime.id) !== 0 || tab.url.indexOf('chrome://')) {
// 绑定弹出窗内容B
chrome.browserAction.setPopup({
'tabId' : tab.id,
'popup' : knowledge.showTopic('error', 'not-allow-page')
});
} else {
// 如果是自己的插件页面不允许弹出(示例)
chrome.browserAction.disable(tab.id);
}
}
break;
case 'complete':
//标签完成更新
break;
default :
break;
}
});
} catch (e) {
//插件加载出现错误,正在重载
location.reload();
}
}
document.addEventListener('DOMContentLoaded', init);
page_action
这种类型的插件的表现形式是在地址栏多一个图标,适用于插件功能和当前页面强关联的场景。
manifest 配置
{
"page_action": {
"default_icon": "image/icon/app-38.png",
"default_title": "字段配置从package.json中读取"
}
}
示例代码
和browser_action API稍有不同。
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
switch (changeInfo.status) {
case 'loading':
//浏览器标签未初始化完毕时初始化插件图标
chrome.pageAction.show(tab.id);
if (checkCurrentTabIsCorrect(tab)) {
// 绑定弹出窗内容A
chrome.pageAction.setPopup({'tabId' : tab.id, 'popup' : 'page/popup/main.html'});
} else {
if (tab.url.indexOf('chrome-extension://' + chrome.runtime.id) !== 0) {
// 绑定弹出窗内容B
chrome.pageAction.setPopup({
'tabId' : tab.id,
'popup' : knowledge.showTopic('error', 'not-allow-page')
});
} else {
// 如果是自己的插件页面不允许展示图标(示例)
chrome.pageAction.hide(tab.id);
}
}
break;
case 'complete':
//标签完成更新
break;
default :
break;
}
});