Mercurial > addons > firefox-addons > context-web-search
comparison background.js @ 0:2050741e9711
Initial revision
author | Guido Berhoerster <guido+cws@berhoerster.name> |
---|---|
date | Tue, 18 Sep 2018 22:57:18 +0200 |
parents | |
children | f77dab12bb52 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:2050741e9711 |
---|---|
1 /* | |
2 * Copyright (C) 2018 Guido Berhoerster <guido+cws@berhoerster.name> | |
3 * | |
4 * This Source Code Form is subject to the terms of the Mozilla Public | |
5 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
7 */ | |
8 | |
9 'use strict'; | |
10 | |
11 function encodeXML(str) { | |
12 return str.replace(/[<>&'"]/g, c => { | |
13 switch (c) { | |
14 case '<': return '<'; | |
15 case '>': return '>'; | |
16 case '&': return '&'; | |
17 case '\'': return '''; | |
18 case '"': return '"'; | |
19 } | |
20 }); | |
21 } | |
22 | |
23 function createFavIcon(name) { | |
24 let firstLetter = name.trim().charAt(0); | |
25 if (firstLetter === '') { | |
26 firstLetter = '?'; | |
27 } | |
28 let svg = `<svg viewBox="0 0 16 16" ` + | |
29 `xmlns="http://www.w3.org/2000/svg">` + | |
30 `<defs>` + | |
31 `<filter id="ds">` + | |
32 `<feDropShadow dx="0" dy="0" stdDeviation=".5"/>` + | |
33 `</filter>` + | |
34 `</defs>` + | |
35 `<rect width="16" height="16" rx="3" ry="3" fill="#ed00b5"/>` + | |
36 `<text x="8" y="12" alignment-baseline="middle" fill="#fff" ` + | |
37 `filter="url(#ds)" font-family="sans-serif" font-size="11px" ` + | |
38 `font-weight="bold" text-anchor="middle">` + | |
39 `${encodeXML(firstLetter)}</text>` + | |
40 `</svg>`; | |
41 return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}` | |
42 } | |
43 | |
44 async function createMenu(isSelection) { | |
45 let searchEngines = await browser.search.get(); | |
46 let menuItems = new Set(); | |
47 for (let engine of searchEngines) { | |
48 let favIcon = typeof engine.favIconUrl !== 'undefined' ? | |
49 engine.favIconUrl : createFavIcon(engine.name); | |
50 let menuItemId = browser.menus.create({ | |
51 id: engine.name, | |
52 title: browser.i18n.getMessage(isSelection ? | |
53 'searchSelectionWithEngine' : 'searchLinkWithEngine', | |
54 engine.name.trim()), | |
55 icons: {16: favIcon}, | |
56 contexts: ['link', 'selection'] | |
57 }, async () => { | |
58 if (browser.runtime.lastError) { | |
59 console.log(`Failed to create menu item:` + | |
60 `${browser.runtime.lastError}`); | |
61 } | |
62 | |
63 // browser.menus.create does not return a promise that can be | |
64 // awaited, thus collect the returned menu item IDs in a set and | |
65 // remove them from this callback which is called when the | |
66 // asynchronous creation function has finished; when the set is | |
67 // empty all creation functions have finished and the menu can be | |
68 // refreshed | |
69 menuItems.delete(menuItemId); | |
70 if (menuItems.size === 0) { | |
71 try { | |
72 await browser.menus.refresh(); | |
73 } catch (e) { | |
74 console.log(`Failed to refresh menu: ${e.message}`); | |
75 } | |
76 } | |
77 }); | |
78 menuItems.add(menuItemId); | |
79 } | |
80 } | |
81 | |
82 browser.menus.onShown.addListener(async (info, tab) => { | |
83 try { | |
84 await createMenu(info.contexts.includes('selection')); | |
85 } catch (e) { | |
86 console.log(e); | |
87 } | |
88 }); | |
89 | |
90 browser.menus.onHidden.addListener(async () => { | |
91 try { | |
92 await browser.menus.removeAll(); | |
93 } catch (e) { | |
94 console.log(`Failed to remove menu items: ${e.message}`); | |
95 } | |
96 try { | |
97 await browser.menus.refresh(); | |
98 } catch (e) { | |
99 console.log(`Failed to refresh menu: ${e.message}`); | |
100 } | |
101 }); | |
102 | |
103 browser.menus.onClicked.addListener(async (info, tab) => { | |
104 let query = typeof info.selectionText !== 'undefined' ? | |
105 info.selectionText.trim() : info.linkText.trim(); | |
106 try { | |
107 await browser.search.search({ | |
108 query: query, | |
109 engine: info.menuItemId | |
110 }); | |
111 } catch (e) { | |
112 console.log(`Failed to search for "${query}": ${e.message}`); | |
113 } | |
114 }); |