Mercurial > addons > firefox-addons > context-web-search
view background.js @ 3:f77dab12bb52
Add support for contextual identities
Create new tab with the same contextual identity as the current tab and open
the search results in newly created tab. Accessing the tab's cookieStoreId
property requires the "cookies" permission.
author | Guido Berhoerster <guido+cws@berhoerster.name> |
---|---|
date | Thu, 31 Oct 2019 16:22:48 +0100 |
parents | 2050741e9711 |
children | d5f5d016facd |
line wrap: on
line source
/* * Copyright (C) 2018 Guido Berhoerster <guido+cws@berhoerster.name> * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 'use strict'; function encodeXML(str) { return str.replace(/[<>&'"]/g, c => { switch (c) { case '<': return '<'; case '>': return '>'; case '&': return '&'; case '\'': return '''; case '"': return '"'; } }); } function createFavIcon(name) { let firstLetter = name.trim().charAt(0); if (firstLetter === '') { firstLetter = '?'; } let svg = `<svg viewBox="0 0 16 16" ` + `xmlns="http://www.w3.org/2000/svg">` + `<defs>` + `<filter id="ds">` + `<feDropShadow dx="0" dy="0" stdDeviation=".5"/>` + `</filter>` + `</defs>` + `<rect width="16" height="16" rx="3" ry="3" fill="#ed00b5"/>` + `<text x="8" y="12" alignment-baseline="middle" fill="#fff" ` + `filter="url(#ds)" font-family="sans-serif" font-size="11px" ` + `font-weight="bold" text-anchor="middle">` + `${encodeXML(firstLetter)}</text>` + `</svg>`; return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}` } async function createMenu(isSelection) { let searchEngines = await browser.search.get(); let menuItems = new Set(); for (let engine of searchEngines) { let favIcon = typeof engine.favIconUrl !== 'undefined' ? engine.favIconUrl : createFavIcon(engine.name); let menuItemId = browser.menus.create({ id: engine.name, title: browser.i18n.getMessage(isSelection ? 'searchSelectionWithEngine' : 'searchLinkWithEngine', engine.name.trim()), icons: {16: favIcon}, contexts: ['link', 'selection'] }, async () => { if (browser.runtime.lastError) { console.log(`Failed to create menu item:` + `${browser.runtime.lastError}`); } // browser.menus.create does not return a promise that can be // awaited, thus collect the returned menu item IDs in a set and // remove them from this callback which is called when the // asynchronous creation function has finished; when the set is // empty all creation functions have finished and the menu can be // refreshed menuItems.delete(menuItemId); if (menuItems.size === 0) { try { await browser.menus.refresh(); } catch (e) { console.log(`Failed to refresh menu: ${e.message}`); } } }); menuItems.add(menuItemId); } } browser.menus.onShown.addListener(async (info, tab) => { try { await createMenu(info.contexts.includes('selection')); } catch (e) { console.log(e); } }); browser.menus.onHidden.addListener(async () => { try { await browser.menus.removeAll(); } catch (e) { console.log(`Failed to remove menu items: ${e.message}`); } try { await browser.menus.refresh(); } catch (e) { console.log(`Failed to refresh menu: ${e.message}`); } }); browser.menus.onClicked.addListener(async (info, tab) => { let query = typeof info.selectionText !== 'undefined' ? info.selectionText.trim() : info.linkText.trim(); // create a new tab with the same contextual identity as the current tab let newTab; try { newTab = await browser.tabs.create({ active: true, cookieStoreId: tab.cookieStoreId, openerTabId: tab.id }); } catch (e) { console.log(`Failed to create new tab: ${e.message}`); return; } try { await browser.search.search({ query: query, engine: info.menuItemId, tabId: newTab.id }); } catch (e) { console.log(`Failed to search for "${query}": ${e.message}`); } });