-
Notifications
You must be signed in to change notification settings - Fork 3
/
service-worker.js
161 lines (137 loc) · 4.43 KB
/
service-worker.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
importScripts("lodash.min.js");
const signpostRelations = {
author: "is authored by",
collection: "is part of the collection",
describedby: "is described by",
describes: "describes the content at",
item: "has an item at",
"cite-as": "should be cited as",
type: "is of the type described at",
license: "is licensed according to",
};
chrome.storage.session.setAccessLevel({
accessLevel: "TRUSTED_AND_UNTRUSTED_CONTEXTS",
});
chrome.storage.session.clear();
const getRelationFromHeaderValue = (value) => {
const relRegex = /rel="?([a-z, A-Z, -]*)"?/;
const relMatch = value.match(relRegex);
if (relMatch) {
return relMatch[1].toLowerCase();
}
return;
};
const headerHasSignposts = (header) => {
if (!(header.name.toLowerCase() === "link")) return false;
if (header.value.indexOf("rel") < 0) return false;
const rel = getRelationFromHeaderValue(header.value);
if (signpostRelations[rel]) return true;
return false;
};
const getSignpostsFromHeader = (header) => {
const hval = header.value;
const links = hval.split(",");
let signposts = [];
links.forEach((link) => {
const rel = getRelationFromHeaderValue(link);
if (!signpostRelations[rel]) return;
const urlRegex = /(?<=<)([^>]+)(?=>)/g;
const urlMatches = link.match(urlRegex);
const mimetypeRegex = /type="([^"]*)"/;
const mimetypeMatch = link.match(mimetypeRegex);
const profileRegex = /profile="([^"]*)"/;
const profileMatch = link.match(profileRegex);
const signpost = {
url: urlMatches[0],
relationship: signpostRelations[rel],
mimetype: mimetypeMatch ? mimetypeMatch[1] : null,
profile: profileMatch ? profileMatch[1] : null,
};
signposts.push(signpost);
});
return signposts;
};
const storeSignposts = async (pageUrl, signposts) => {
const existingSignposts = await chrome.storage.session.get([pageUrl]);
if (existingSignposts[pageUrl]) {
await chrome.storage.session.set({
[pageUrl]: _.uniqBy([...existingSignposts[pageUrl], ...signposts], "url"),
});
} else {
await chrome.storage.session.set({ [pageUrl]: signposts });
}
};
chrome.webRequest.onHeadersReceived.addListener(
(details, callback) => {
const headers = details.responseHeaders;
let allSignposts = [];
headers.forEach((header) => {
if (headerHasSignposts(header)) {
allSignposts.push(...getSignpostsFromHeader(header));
}
});
if (allSignposts.length) {
storeSignposts(details.url, allSignposts);
}
},
{ urls: ["<all_urls>"] },
["responseHeaders", "extraHeaders"],
);
function htmlListener () {
chrome.webNavigation.onDOMContentLoaded.addListener((details) => {
const tabId = details.tabId;
// Check if the tab is ready (has a tabId)
if (tabId) {
chrome.scripting
.executeScript({
target: { tabId: tabId },
function: findSignpostLinks,
args: [signpostRelations],
})
.then((response) => {
for (const { result: signposts } of response) {
if (signposts.length) {
storeSignposts(details.url, signposts);
}
}
});
}
});
}
chrome.runtime.onInstalled.addListener(htmlListener);
chrome.runtime.onStartup.addListener(htmlListener);
function findSignpostLinks(signpostRelations) {
const links = Array.from(document.querySelectorAll("link"));
let allSignposts = [];
links.forEach((link) => {
if (link.rel && !!signpostRelations[link.rel.toLowerCase()]) {
allSignposts.push({
url: link.href,
relationship: signpostRelations[link.rel.toLowerCase()],
mimetype: link.type,
profile: null,
});
}
});
return allSignposts;
}
function setIcon(state) {
const iconPath = state ? 'logo.png' : 'logo-disabled.png';
chrome.action.setIcon({ path: iconPath });
}
function actionListener() {
chrome.storage.local.get(['overlayEnabled'], (result) => {
const currentState = result.overlayEnabled !== undefined ? result.overlayEnabled : true;
const newState = !currentState;
chrome.storage.local.set({ overlayEnabled: newState }, () => {
setIcon(newState);
});
});
}
chrome.action.onClicked.addListener(actionListener);
chrome.runtime.onStartup.addListener(() => {
chrome.storage.local.get(['overlayEnabled'], (result) => {
console.log("startup overlay state", result.overlayEnabled);
setIcon(result.overlayEnabled !== undefined ? result.overlayEnabled : true );
});
});