Firefox WebExtensions:如何将背景页作为唯一选项卡打开



问题是:在Firefox WebExtensions中,从任意背景来源,如何在选项卡中唯一地打开任意页面?

要求:

1) 任意背景来源。我的初始用例来自browser_action contextMenu。然而,该技术应该在弹出窗口、选项或任何自定义背景脚本中工作。暂时不关心内容页面。尽管如果这项技术也适用于他们,那就太好了。

2) 在选项卡中打开任意页面。我最初使用的是选项页面,但该技术应该适用于任意背景页面(选项、弹出窗口或自定义页面)。

3) 以唯一方式打开。如果是第一次,请在新的选项卡中打开。如果以前打开过该选项卡,请将焦点放在现有选项卡上,不要创建重复的选项卡。

4) 如果我关闭了一个选项卡,我需要确保删除对以前打开的选项卡ID的引用。

我用一个可能的解决方案回答了我自己的问题。

如果解决方案可以改进,请告诉我。非常感谢。

如果问题重复,我会删除并在适当的时候将解决方案发布到其他地方。

这是一个尝试回答我自己的问题,内联注释。

这个简单的例子假设所有的寻呼机都位于顶级目录中,但这是任意的,很容易更改。

从本质上讲,它由四个部分组成:

1) 保存页面名称的全局对象tabIDs(不带".html")。您可以将其更改为包括扩展名的完整路径,或者将页面名称保留为短名称,并修改技术以使用另一个选项,如完整路径名称的路径等。

2) 一个名为tabCreate的异步函数(利用新的等待功能)来确定是否已经打开并切换到它或创建一个新的选项卡

3) onRemoved事件处理程序tabRemove,用于在选项卡关闭后处理tabIDs的清理(如果感兴趣的话)。

4) 一个用法示例,从上下文菜单项传递一些pagepanel选项,这两个选项在本问题中没有用处,但是另一个问题的一部分,此处仅用于演示。

background.js:

// tabID contexts
//     global var to keep track of different tabs,
//     i.e. options.html, popup.html and so on.
var tabIDs = {
'options': null,
'popup': null,
}
// Requires Firefox 52.0+ to use async/await
//     opts correspond to contexts above in tabIDs
//     of the form { 'page': 'options' } or { 'page': 'popup' }
//     note if using Node.js, this may require v7+ and --harmony_async_await
async function tabCreate ( opts ) {
var tab;
if ( tabIDs[ opts.page ] !== null ) {
// should probably bring window to front first... oops
// ..
// switch to tab
tab = await browser.tabs.update( tabIDs[ opts.page ], { active: true } );
} else {
tab = await browser.tabs.create( {
'url': opts.page + '.html'
} );
tabIDs[ opts.page ] = tab.id;
}
console.log( '**** opts.page = ' + opts.page + ', opts.tab = ' + opts.tab + ', tab.id = ' + tab.id );
}
// When tabs are closed, see if the tabID is in tabIDs,
//     and if so, set it to null
function tabRemove ( tabID, removeInfo ) {
console.log( 'Closed TAB ' + tabID );
Object.keys( tabIDs ).forEach( function( key, index ) {
if ( tabIDs[ key ] === tabID ) {
tabIDs[ key ] = null;
return;
}
} );
}
browser.tabs.onRemoved.addListener( tabRemove );
/*
* Context Menus
*/
browser.contextMenus.removeAll( );
browser.contextMenus.create( {
title: 'My Web Extension',
contexts: [ 'browser_action' ],
} );
browser.contextMenus.create( {
title: 'Options',
contexts: [ 'browser_action' ],
onclick: myWebExt_Options
} );
function myWebExt_Options ( ) {
tabCreate( {
'page': 'options',
'panel': 1,
} );
}

另一种方法可能是在每个页面中添加一个事件侦听器,并在关闭时将消息发送回background.js,但这似乎要复杂得多,几乎没有好处。

最新更新