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