Mercurial > addons > firefox-addons > context-web-search
view background.js @ 7:369e61618ff0 version-3
Release version 3
author | Guido Berhoerster <guido+cws@berhoerster.name> |
---|---|
date | Sun, 10 Oct 2021 20:55:03 +0200 |
parents | d5f5d016facd |
children |
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: info.button === 1 ? false : 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}`); } });