-
Notifications
You must be signed in to change notification settings - Fork 4
/
auth.js
117 lines (100 loc) · 3.44 KB
/
auth.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
var target = "<all_urls>";
var pendingRequests = [];
/*
* A request has completed. We can stop worrying about it.
*/
function completed(requestDetails) {
var tabId = requestDetails.tabId;
var index = pendingRequests.indexOf(requestDetails.requestId);
if (index > -1) {
pendingRequests.splice(index, 1);
}
}
/*
* Helper to extract the hostname and port from an URL.
* @param url The url to take the parameter from. Expects a propper protocol prefex like 'http://' or 'https://'.
* @returns An array of length two. The first element is the hostname as taken from the url. The second element is the hostname with a ':*' suffix.
*/
function getHostnames(url) {
var [, , host_and_port] = url.split("/");
return [host_and_port, host_and_port.split(":")[0] + ":*"];
}
/*
* Helper to check if a dictionary contains no keys.
*/
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
function hijackTab(requestDetails, is_error) {
var host = getHostnames(requestDetails.url)[0];
const url = browser.extension.getURL("modal.html?host=" + encodeURI(host) + "&url=" + escape(encodeURI(requestDetails.url)) + "&is_error=" + is_error);
var tabId = requestDetails.tabId;
browser.tabs.update(tabId, {
url: url
});
return {cancel: true};
}
/*
* Returns a promise which evaluates to authentication credentials if they where stored before.
* If no credentials are stored the user gets redirected to a page asking for them.
*/
function provideCredentialsAsync(requestDetails) {
if (pendingRequests.indexOf(requestDetails.requestId) != -1) {
return hijackTab(requestDetails, true);
} else {
// Mark the request as seen
pendingRequests.push(requestDetails.requestId);
var hosts = getHostnames(requestDetails.url);
let gettingItem = browser.storage.local.get(hosts);
return gettingItem.then(credentials => {
if (isEmpty(credentials)) {
// No credentials set yet and host is not ignored, so redirect to page to ask for credentials
return hijackTab(requestDetails, false);
}
// Take credentials with longest host.
var possibleCreds = Object.entries(credentials);
possibleCreds.sort((a, b) => b.length - a.length);
credentials = possibleCreds[0][1];
if (credentials == "ignored") {
// Host was ignored. Do nothing.
return;
}
else {
// There are credentials stored for the host.
return {authCredentials: credentials};
}
});
}
}
/*
* Handles updates of addon and migrates formats.
*/
function migration(details) {
browser.storage.local.get(null).then(credentials => {
Object.keys(credentials).forEach(function(host) {
if (!credentials[host]) {
browser.storage.local.remove(host);
}
else if (credentials[host] == "no") {
browser.storage.local.set({[host]: "ignored"});
}
});
});
}
/*
* Register request listeners
*/
browser.webRequest.onAuthRequired.addListener(
provideCredentialsAsync,
{urls: [target]},
["blocking"]
);
browser.webRequest.onCompleted.addListener(
completed,
{urls: [target]}
);
browser.webRequest.onErrorOccurred.addListener(
completed,
{urls: [target]}
);
browser.runtime.onInstalled.addListener(migration);