-
Notifications
You must be signed in to change notification settings - Fork 0
/
annotater.js
134 lines (121 loc) · 3.6 KB
/
annotater.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
function getUpdatingLinkFunction() {
return new Promise(resolve => {
if (!window.updatingLink) {
chrome.runtime.sendMessage({getCode: "code"}, (response) => {
window.updatingLink = eval(response.code);
resolve(window.updatingLink);
});
return;
}
resolve(window.updatingLink);
});
}
// TODO: Don't check this in (and cycle the key).
const API_KEY="AIzaSyCTBTG6ouekwiL_z11bvIsKuZ_CkuC8qT0";
(function() {
async function wait(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
// Throttle PSI requests
let psiCalls = 0;
// Stub out for testing
const fakeData = true;
async function getSiteSpeed(pageUrl) {
if (fakeData) {
let origin;
try {
origin = new URL(pageUrl).host;
} catch(e) {
let pathArray = pageUrl.split('/');
let protocol = pathArray[0];
origin = pathArray[2];
}
console.log(origin);
if (SLOW_ORIGINS.has(origin)) {
return {
fcp90: 8000,
fcp95: 9000,
urlSpecific: false,
}
} else {
return {
fcp90: 1000,
fcp95: 2000,
urlSpecific: false,
}
}
}
let api = 'https://www.googleapis.com/pagespeedonline/v5/runPagespeed';
const parameters = {
url: encodeURIComponent('https://en.wikipedia.org/wiki/Speed'),
category: "best-practices", // can't turn lighthouse off - use cheapest
strategy: "desktop",
fields: "analysisUTCTimestamp%2CcaptchaResult%2Cid%2Ckind%2CloadingExperience%2CoriginLoadingExperience%2Cversion",
key: API_KEY
};
let first = true;
for (key in parameters) {
api += first ? "?" : "&";
api += `${key}=${parameters[key]}`;
first = false;
}
psiCalls++;
// Quota is 60 queries per 100 seconds per user :-(
await wait(2000 * (psiCalls-1));
const response = await fetch(api);
psiCalls--;
const json = await response.json();
let crux = json.loadingExperience || json.originLoadingExperience;
if (!crux)
return {};
return {
fcp90: crux.metrics.FIRST_CONTENTFUL_PAINT_MS.percentile,
fid95: crux.metrics.FIRST_INPUT_DELAY_MS.percentile,
urlSpecific: 'loadingExperience' in json,
};
}
async function updateAnnotation(state, a) {
// Ignore #foo hrefs as they just scroll the page.
if (location.origin == a.origin && location.pathname == a.pathname)
return;
// TODO: Make updates and removes work.
if (state != 'added')
return;
const speed = await getSiteSpeed(a.href)
let updatingLink = await getUpdatingLinkFunction();
updatingLink(state, a, speed);
}
const mutationObserver = new MutationObserver((mutationList) => {
mutationList.forEach((mutation) => {
switch(mutation.type) {
case 'childList':
for (let newNode of mutation.addedNodes) {
if (newNode.nodeName != "A")
continue;
updateAnnotation("added", newNode);
}
for (let newNode of mutation.removedNodes) {
if (newNode.nodeName != "A")
continue;
updateAnnotation("removed", newNode);
}
break;
case 'attributes':
updateAnnotation("updated", mutation.target);
break;
default:
throw "unhandled mutation of type " + mutation.type;
}
});
});
const mutationObserverOptions = {
attributeFilter: ["href"],
attributeOldValue: false,
attributes: true,
childList: true,
subtree: true,
};
mutationObserver.observe(document.documentElement, mutationObserverOptions);
})();