-
Notifications
You must be signed in to change notification settings - Fork 314
Expand file tree
/
Copy pathconnect.ts
More file actions
135 lines (124 loc) · 4.6 KB
/
connect.ts
File metadata and controls
135 lines (124 loc) · 4.6 KB
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
import { compact, first, sortBy } from 'lodash-es'
import stringify from 'json-stable-stringify'
import { delay } from '@masknet/kit'
import {
type PersonaIdentifier,
type ProfileIdentifier,
currentSetupGuideStatus,
SetupGuideStep,
} from '@masknet/shared-base'
import { definedSiteAdaptors } from '../../../shared/site-adaptors/definitions.js'
import type { SiteAdaptor } from '../../../shared/site-adaptors/types.js'
import type { Tabs } from 'webextension-polyfill'
async function hasPermission(origin: string): Promise<boolean> {
return browser.permissions.contains({
origins: [origin],
})
}
interface SitesQueryOptions {
isSocialNetwork?: boolean
}
export async function getSupportedSites(options: SitesQueryOptions = {}): Promise<
Array<{
networkIdentifier: string
}>
> {
return sortBy(
[...definedSiteAdaptors.values()].filter((x) =>
options.isSocialNetwork === undefined ? true : x.isSocialNetwork === options.isSocialNetwork,
),
(x) => x.sortIndex,
).map((x) => ({ networkIdentifier: x.networkIdentifier }))
}
export async function getSupportedOrigins(options: SitesQueryOptions = {}): Promise<
Array<{
networkIdentifier: string
origins: string[]
}>
> {
return sortBy([...definedSiteAdaptors.values()], (x) => x.sortIndex)
.filter((x) => (options.isSocialNetwork === undefined ? true : x.isSocialNetwork === options.isSocialNetwork))
.map((x) => ({ networkIdentifier: x.networkIdentifier, origins: [...x.declarativePermissions.origins] }))
}
export async function getOriginsWithoutPermission(options: SitesQueryOptions = {}): Promise<
Array<{
networkIdentifier: string
origins: string[]
}>
> {
const groups = await getSupportedOrigins(options)
const promises = groups.map(async ({ origins, networkIdentifier }) => {
const unGrantedOrigins = compact(
await Promise.all(origins.map((origin) => hasPermission(origin).then((yes) => (yes ? null : origin)))),
)
if (!unGrantedOrigins.length) return null
return {
networkIdentifier,
origins: compact(unGrantedOrigins),
}
})
return compact(await Promise.all(promises))
}
export async function getAllOrigins() {
const groups = await getSupportedOrigins()
const promises = groups.map(async ({ origins, networkIdentifier }) => {
const originsWithNoPermission = compact(
await Promise.all(origins.map((origin) => hasPermission(origin).then((yes) => (yes ? null : origin)))),
)
return {
networkIdentifier,
hasPermission: !originsWithNoPermission.length,
}
})
return Promise.all(promises)
}
export async function getSitesWithoutPermission(): Promise<SiteAdaptor.Definition[]> {
const groups = [...definedSiteAdaptors.values()]
const promises = groups.map(async (x) => {
const origins = x.declarativePermissions.origins
const unGrantedOrigins = compact(
await Promise.all(origins.map((origin) => hasPermission(origin).then((yes) => (yes ? null : origin)))),
)
if (!unGrantedOrigins.length) return null
return x
})
return compact(await Promise.all(promises))
}
/**
* It's caller's responsibility to call browser.permissions.request to get the permissions needed.
* @param identifier Persona
* @param network Network to connect
* @param profile Profile
* @param openInNewTab Open in new tab
*/
export async function connectSite(
identifier: PersonaIdentifier,
network: string,
profile?: ProfileIdentifier,
openInNewTab = true,
) {
const site = definedSiteAdaptors.get(network)
if (!site) return
const url = site.homepage
if (!url) return
let targetTab: Tabs.Tab | undefined
if (openInNewTab) {
targetTab = await browser.tabs.create({ active: true, url: site.homepage })
} else {
const openedTabs = await browser.tabs.query({ url: `${url}/*` })
targetTab = openedTabs.find((x: { active: boolean }) => x.active) ?? first(openedTabs)
if (!targetTab?.id || !targetTab.windowId) {
await browser.tabs.create({ active: true, url })
}
}
await delay(100)
if (!targetTab?.windowId) return
await browser.tabs.update(targetTab.id, { active: true })
await browser.windows.update(targetTab.windowId, { focused: true })
currentSetupGuideStatus[network].value = stringify({
status: SetupGuideStep.VerifyOnNextID,
persona: identifier.toText(),
username: profile?.userId,
tabId: targetTab.id,
}) as string
}