Given a moz-extension:// URL opened by bookmark, how can I switch to tab using extension code?

房东的猫 提交于 2019-12-12 02:14:48

问题


This is related to some other questions I am working on.

Say, for whatever reason, a user has bookmarked a page (call it pageURL of the pattern moz-extensions://MY-OWN-WEBEXT-ID/*) intended to be opened from a browser action context menu, and opened it in a tab, then opened many other tabs and possibly other windows. User knows the extension tab exists somewhere and doesn't want to keep opening new bookmarks, and so wants to use the add-on's browser action context menu to find the extension page's tab. Likewise, I don't want my add-on to open a duplicate tab.

The problem, since the add-on did not create the tab (a bookmark did), I have no tab ID to pass to browser.tabs.update( WebExtTab.id, { active: true } ) or window ID to pass to browser.windows.update( WebExtWindow.id, { focused: true } ). (WebExtWindow referring to a WebExtensions browser.windows.Window object, not a browser window object.

I can use browser.extension.getViews( ) to generate a list of browser window objects (aka tabs), and checking each window.location.href find that indeed the URL (and thus tab) does exist (somewhere), but I can't use that window object to focus on the tab nor to get a tab ID for browser.tabs.update().

In the case of multiple browser windows, I can't even get the right browser window to raise up given that window object, because the window objects returned by getViews have no id property with which to call browser.windows.update(). Similar to the tabs problem.

Finally, I can't use browser.tabs.query( { 'url': pageURL } ) to find the tab ID, because the url option must conform to match patterns, which FORBID using the moz-extension:// scheme.

What would be exceptionally useful was if the WebExtensions API allowed an extension to find the tabs and windows of all pages that belong to itself, regardless if those pages were opened by the add-on, manually entered, a bookmark or clicking a link.

For example, given a pageURL conforming to moz-extension://MY-OWN-WEBEXT-ID/*, one could do a browser.tabs.query and/or a browser.windows.query on a url matching the above pattern, and return a WebExt tab/window object, respectively. If such a tab/window was not opened by the WebExt API (i.e. bookmark), then generate a new object (i.e. a pseudo-create), to populate with existing data (i.e. location.href, status flags, etc) and generate new data as needed (i.e. the ID numbers), such that the returned object is usable within the context of the API.

This would fill a gap in API coverage where certain methods (i.e. getViews) return dead-end browser objects which have no hooks and no connection with the WebExt API and are thus mostly useless.


回答1:


The simple answer: ++RTFM. browser.windows.getAll() will allow you to populate the windows objects with tab info. You need the permissions: [ "tabs" ] in manifest.json to get the tab.url property. But other than that, all the windows and tab objects will have an ID so that you can trivially focus window and switch active tab!

Note: This requires Firefox 52.0+ to make use of the async/await feature. Otherwise, you just have to use function generators and promises. Also, I've omitted any error checking, for demonstration purposes, but it might be a good idea to put them back in later.

async function tabCreate ( opts ) {
    var pageURL = browser.runtime.getURL( opts.page + '.html' );
    var extWins = await browser.windows.getAll( { populate: true, windowTypes: [ 'normal' ] } );

    // Look for tab by comparing url, if url matches (i.e. tab exists), then focus window and make tab active.
    for ( var extWin of extWins ) {
        for ( var extTab of extWin.tabs ) {
            if ( pageURL === extTab.url ) {
                console.log( `My Extension->tabCreate(): Window ${extWin.id}, Tab ${extTab.id}:\n\t${extTab.url}` );
                browser.windows.update( extWin.id, { focused: true } );
                browser.tabs.update( extTab.id, { active: true } );
                return;
            }
        }
    }

    // Otherwise, create tab.
    browser.tabs.create( { url: pageURL } );
}

Opinion: I wish I didn't have to give away the tabs permission just for this feature. It would be nice if we always got our own moz-extension://MY-OWN-WEBEXT-ID/* urls, and null URLs for other tabs, without permissions given to access all tabs, but oh well.

Example Usage:

function myWebExt_Options ( ) {
    tabCreate( {
        'page': 'options',
        'panel': 1
    } );
}

browser.contextMenus.create( {
    title: 'Options',
    contexts: [ 'browser_action' ],
    onclick: myWebExt_Options
} );

Note: I've implemented this to expect options in an opts object that has a page property, which I use as a shorthand to generate the full page URL. This is because of another question which requires passing a message to the page, which I store in opts.panel. But none of that is necessary. It could be changed to a flat string, or use the full 'getURL' generated elsewhere as a parameter. Change to suit your need and style.



来源:https://stackoverflow.com/questions/41635692/given-a-moz-extension-url-opened-by-bookmark-how-can-i-switch-to-tab-using-e

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!