-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
background.js
168 lines (141 loc) · 4.62 KB
/
background.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
import { patchCspForHypothesis } from './src/functions.js';
async function sha256(message) {
// encode as UTF-8
const msgBuffer = new TextEncoder('utf-8').encode(message);
// hash the message
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
// convert ArrayBuffer to Array
const hashArray = Array.from(new Uint8Array(hashBuffer));
// convert bytes to hex string
const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
return hashHex;
}
async function onHeaderPassed(details) {
// Filter out non top-level response URL
if (details.url.length <= 0 || typeof details.documentUrl !== 'undefined') {
return {};
}
let cspIdx = details.responseHeaders
.findIndex(function (headeritem) {
return headeritem.name.toLowerCase() == "content-security-policy"
&& (headeritem.value.indexOf('default-src ') !== -1 || headeritem.value.indexOf('script-src ') !== -1)
;
});
if (cspIdx != -1) {
var results = await browser.storage.local.get('hypothesisHash');
var csp = details.responseHeaders[cspIdx];
details.responseHeaders[cspIdx].value = patchCspForHypothesis(csp.value);
}
return {
responseHeaders: details.responseHeaders
};
}
async function onPageActionClicked() {
var config = await browser.storage.local.get('activeSites');
var isEnabled = (config.activeSites && config.activeSites[currentTab.url]) || false;
toggleHypothesis(!isEnabled);
}
async function togglePgActionIcon(toActive) {
if (!toActive) {
// Mark as disabled
browser.pageAction.setIcon({
tabId: currentTab.id,
path: {
19: "icons/hypothesis-19.png",
38: "icons/hypothesis-38.png",
}
});
browser.pageAction.setTitle({
tabId: currentTab.id,
title: "Show Hypothes.is",
});
} else {
// Mark as active
browser.pageAction.setIcon({
tabId: currentTab.id,
path: {
19: "icons/hypothesis-active-19.png",
38: "icons/hypothesis-active-38.png",
}
});
browser.pageAction.setTitle({
tabId: currentTab.id,
title: "Hide Hypothes.is",
});
}
}
async function syncTabHypothesis() {
var config = await browser.storage.local.get('activeSites');
var isEnabled = (config.activeSites && config.activeSites[currentTab.url]) || false;
// Setup icon
togglePgActionIcon(isEnabled);
// Reapply command
var command = isEnabled ? "hypothesis.enable()" : "hypothesis.disable()"
await browser.tabs.executeScript(currentTab.id, {
code: command,
});
}
async function toggleHypothesis(toActive) {
// Save toggle
var config = await browser.storage.local.get('activeSites');
if (typeof config.activeSites === 'undefined') {
config.activeSites = {};
}
config.activeSites[currentTab.url] = toActive;
await browser.storage.local.set({
activeSites: config['activeSites']
});
await syncTabHypothesis();
return toActive;
}
async function setupPageAction() {
browser.pageAction.show(currentTab.id);
await syncTabHypothesis();
}
/*
* Switches currentTab and currentBookmark to reflect the currently active tab
*/
function updateActiveTab() {
function updateTab(tabs) {
if (tabs[0]) {
currentTab = tabs[0];
}
}
var gettingActiveTab = browser.tabs.query({ active: true, currentWindow: true });
return gettingActiveTab
.then(updateTab)
.then(setupPageAction);
}
/** ----------------- *
* Event Listeners
* ----------------- */
// listen to tab URL changes
browser.tabs.onUpdated.addListener(updateActiveTab);
// listen to tab switching
browser.tabs.onActivated.addListener(updateActiveTab);
// listen for window switching
browser.windows.onFocusChanged.addListener(updateActiveTab);
// listen for page action toggled
browser.pageAction.onClicked.addListener(onPageActionClicked);
/* ----- *
* Main
* ----- */
var currentTab;
// Setting up CSP
fetch('https://hypothes.is/embed.js')
.then(response => response.text())
.then(async function (script) {
var hypothesisHash = await sha256(script);
browser.storage.local.set({ hypothesisHash: hypothesisHash });
browser.webRequest.onHeadersReceived.addListener(
onHeaderPassed,
{ urls: [ "<all_urls>" ] },
[ "blocking", "responseHeaders" ]
);
});
// update when the extension loads initially
updateActiveTab()
.then(setupPageAction)
.then(function () {
syncTabHypothesis();
});