-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.js
105 lines (95 loc) · 2.72 KB
/
index.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
/* eslint-env webextensions */
async function createWindow(options, useTab) {
if (browser.windows && !useTab) {
return await browser.windows.create(options);
}
const tabOptions = {
active: options.state !== "minimized",
url: options.url,
};
const tab = await browser.tabs.create(tabOptions);
return {
tabs: [tab]
};
}
async function updateWindow(windowId, tabId, options) {
if (windowId) {
return await browser.windows.update(windowId, options);
}
return await browser.tabs.update(tabId, {
active: options.focused
});
}
async function closeWindow(windowId, tabId) {
if (windowId) {
return await browser.windows.remove(windowId);
}
return await browser.tabs.remove(tabId);
}
function defer() {
const o = {};
o.promise = new Promise((resolve, reject) => {
o.resolve = resolve;
o.reject = reject;
});
return o;
}
async function launchWebAuthFlow({
url,
redirect_uri,
interactive = false,
alwaysUseTab = false,
windowOptions
}) {
const wInfo = await createWindow({
type: "popup",
url,
state: "minimized",
// https://crbug.com/783827
// note that Firefox doesn't support focused either
// focused: false
...windowOptions
}, alwaysUseTab);
const windowId = wInfo.id;
const tabId = wInfo.tabs[0].id;
const {promise, resolve, reject} = defer();
browser.webRequest.onBeforeRequest.addListener(onBeforeRequest, {
urls: ["*://*/*"],
tabId,
types: ["main_frame"]
}, ["blocking"]);
browser.webNavigation.onDOMContentLoaded.addListener(onDOMContentLoaded);
browser.tabs.onRemoved.addListener(onTabRemoved);
try {
return await promise;
} finally {
cleanup();
}
function onBeforeRequest(details) {
if (details.frameId || details.tabId !== tabId) return;
if (!details.url.startsWith(redirect_uri)) return;
resolve(details.url);
return {cancel: true};
}
function onDOMContentLoaded(details) {
if (details.frameId || details.tabId !== tabId) return;
if (interactive) {
updateWindow(windowId, tabId, {focused: true, state: "normal"}).catch(err => console.error(err));
} else {
reject(new Error("User interaction required"));
}
browser.webNavigation.onDOMContentLoaded.removeListener(onDOMContentLoaded);
}
function onTabRemoved(removedTabId) {
if (removedTabId === tabId) {
reject(new Error("Canceled by user"));
}
}
function cleanup() {
browser.webRequest.onBeforeRequest.removeListener(onBeforeRequest);
browser.webNavigation.onDOMContentLoaded.removeListener(onDOMContentLoaded);
browser.tabs.onRemoved.removeListener(onTabRemoved);
closeWindow(windowId, tabId).catch(err => console.error(err));
}
}
module.exports = launchWebAuthFlow;