···991010## [Unreleased]
11111212+- Small fix for a bug introduced in `1.4.0` that occurs when the browser puts idle extensions to sleep
1313+1214## [1.4.0]
13151416### Changed
15171618- Migrate/refactor everything from `content.js` into a self-contained `background.js`
1719- Swap `activeTab` permission for `tabs` so that we can drop the `<all_urls>` permission
1818-- Remove permissions for "management" as it is not needed
2020+- Remove permissions for `management` as it is not needed
1921- Migrate Firefox to Manifest v3 (but this means the minimum FF version is now 109)
2022- Input validation for domains and DIDs (security enhancement)
2123- Replace `staging.bsky.app` with `bsky.app`
+59-36
background.js
···103103// The cache is cleared when the tab is closed
104104const didCache = new Map()
105105106106-function performAction(tab) {
107107- storage.get("privacyConsentAccepted", ({ privacyConsentAccepted }) => {
108108- if (privacyConsentAccepted) {
109109- const domain = getDomainName(tab.url)
110110- if (isValidDomain(domain)) {
111111- // Check if we have cached DID for this tab and domain
112112- const cachedDID = didCache.get(`${tab.id}:${domain}`)
113113- if (cachedDID !== undefined) {
114114- // If we have a cached DID or a cached "not found" state, use it
115115- if (cachedDID !== null) {
116116- setDID(tab, cachedDID)
117117- } else {
118118- setIcon(tab.id, "logo48_gray.png")
119119- tabsWithDID.delete(tab.id)
120120- }
121121- } else {
122122- // If not, proceed with the checks
123123- checkForDIDDNS(domain).then((domainDID) => {
124124- if (domainDID) {
125125- setDID(tab, domainDID)
126126- didCache.set(`${tab.id}:${domain}`, domainDID)
106106+async function performAction(tab) {
107107+ return new Promise((resolve, reject) => {
108108+ storage.get(
109109+ "privacyConsentAccepted",
110110+ async ({ privacyConsentAccepted }) => {
111111+ if (privacyConsentAccepted) {
112112+ const domain = getDomainName(tab.url)
113113+ if (isValidDomain(domain)) {
114114+ // Check if we have cached DID for this tab and domain
115115+ const cachedDID = didCache.get(`${tab.id}:${domain}`)
116116+ if (cachedDID !== undefined) {
117117+ // If we have a cached DID or a cached "not found" state, use it
118118+ if (cachedDID !== null) {
119119+ setDID(tab, cachedDID)
120120+ } else {
121121+ setIcon(tab.id, "logo48_gray.png")
122122+ tabsWithDID.delete(tab.id)
123123+ }
124124+ resolve()
127125 } else {
128128- checkForDIDHTTPS(domain).then((httpsDID) => {
126126+ // If not, proceed with the checks
127127+ const domainDID = await checkForDIDDNS(domain)
128128+ if (domainDID) {
129129+ setDID(tab, domainDID)
130130+ didCache.set(`${tab.id}:${domain}`, domainDID)
131131+ resolve()
132132+ } else {
133133+ const httpsDID = await checkForDIDHTTPS(domain)
129134 if (httpsDID) {
130135 setDID(tab, httpsDID)
131136 didCache.set(`${tab.id}:${domain}`, httpsDID)
···135140 // Cache the "not found" state
136141 didCache.set(`${tab.id}:${domain}`, null)
137142 }
138138- })
143143+ resolve()
144144+ }
139145 }
140140- })
146146+ } else {
147147+ reject(new Error("Invalid domain"))
148148+ }
149149+ } else {
150150+ reject(new Error("Privacy consent not accepted"))
141151 }
142152 }
143143- }
153153+ )
144154 })
145155}
146156···193203 })
194204})
195205196196-// Open the consent page if it hasn't been accepted and the user clicks on the extension icon
197197-action.onClicked.addListener(() => {
206206+// When the extension icon is clicked
207207+action.onClicked.addListener((tab) => {
208208+ // Get privacyConsentAccepted from storage
198209 storage.get("privacyConsentAccepted", ({ privacyConsentAccepted }) => {
210210+ // If privacyConsentAccepted is undefined or false, open the consent page
199211 if (
200212 typeof privacyConsentAccepted === "undefined" ||
201213 !privacyConsentAccepted
202214 ) {
203215 tabs.create({ url: "privacy_consent.html" })
216216+ } else {
217217+ // If there is a DID for this tab, open the profile page
218218+ const did = tabsWithDID.get(tab.id)
219219+ if (did) {
220220+ const newUrl = `${bskyAppUrl}/profile/${did}`
221221+ tabs.create({ url: newUrl })
222222+ } else {
223223+ // If there is no DID for this tab in cache, run performAction
224224+ const domain = getDomainName(tab.url)
225225+ if (isValidDomain(domain)) {
226226+ performAction(tab).then(() => {
227227+ // If performAction returned a DID, open the profile page
228228+ const didAfterPerformingAction = tabsWithDID.get(tab.id)
229229+ if (didAfterPerformingAction) {
230230+ const newUrl = `${bskyAppUrl}/profile/${didAfterPerformingAction}`
231231+ tabs.create({ url: newUrl })
232232+ }
233233+ })
234234+ }
235235+ }
204236 }
205237 })
206238})
207207-208208-// When the extension icon is clicked, open the profile page if there's a DID
209209-action.onClicked.addListener((tab) => {
210210- const did = tabsWithDID.get(tab.id)
211211- if (did) {
212212- const newUrl = `${bskyAppUrl}/profile/${did}`
213213- tabs.create({ url: newUrl })
214214- }
215215-})