···11// Set up cross-browser compatibility
22-const runtime = typeof browser !== 'undefined' ? browser.runtime : chrome.runtime;
33-const tabs = typeof browser !== 'undefined' ? browser.tabs : chrome.tabs;
44-const storage = typeof browser !== 'undefined' ? browser.storage.local : chrome.storage.local;
55-const action = typeof browser !== 'undefined' ? browser.browserAction : chrome.action;
22+const runtime =
33+ typeof browser !== "undefined" ? browser.runtime : chrome.runtime
44+const tabs = typeof browser !== "undefined" ? browser.tabs : chrome.tabs
55+const storage =
66+ typeof browser !== "undefined" ? browser.storage.local : chrome.storage.local
77+const action =
88+ typeof browser !== "undefined" ? browser.browserAction : chrome.action
69710// On extension installation, check if privacy consent was already accepted and show it if not
811runtime.onInstalled.addListener(() => {
912 storage.get("privacyConsentAccepted", ({ privacyConsentAccepted }) => {
1010- if (typeof privacyConsentAccepted === "undefined" || !privacyConsentAccepted) {
1111- tabs.create({ url: "privacy_consent.html" });
1313+ if (
1414+ typeof privacyConsentAccepted === "undefined" ||
1515+ !privacyConsentAccepted
1616+ ) {
1717+ tabs.create({ url: "privacy_consent.html" })
1218 }
1313- });
1414-});
1919+ })
2020+})
15211622// If the message 'SHOW_CONSENT' is received, open the privacy consent tab
1717-runtime.onMessage.addListener((message, sender, sendResponse) => {
1818- if (message.type === 'SHOW_CONSENT') {
1919- tabs.create({ url: "privacy_consent.html" });
2323+runtime.onMessage.addListener((message) => {
2424+ if (message.type === "SHOW_CONSENT") {
2525+ tabs.create({ url: "privacy_consent.html" })
2026 }
2121-});
2727+})
22282329// Map to store tabs with DIDs
2424-const tabsWithDID = new Map();
3030+const tabsWithDID = new Map()
25312632// URL of the Bluesky Web Applications
2727-const bskyAppUrl = 'https://staging.bsky.app';
3333+const bskyAppUrl = "https://staging.bsky.app"
28342935// Function to set the extension icon
3036function setIcon(tabId, iconName) {
3131- action.setIcon({ path: iconName, tabId });
3737+ action.setIcon({ path: iconName, tabId })
3238}
33393440// On extension installation, set the icon to gray for all tabs
3541runtime.onInstalled.addListener(() => {
3642 tabs.query({}, (tabs) => {
3737- tabs.forEach((tab) => setIcon(tab.id, 'logo48_gray.png'));
3838- });
3939-});
4343+ tabs.forEach((tab) => setIcon(tab.id, "logo48_gray.png"))
4444+ })
4545+})
40464147// When a message is received from the DNS check, set the icon color to blue.
4242-runtime.onMessage.addListener((message, sender, sendResponse) => {
4848+runtime.onMessage.addListener((message, sender) => {
4349 if (message.type === "DID_FOUND") {
4444- setIcon(sender.tab.id, "logo48.png");
4545- tabsWithDID.set(sender.tab.id, message.did);
5050+ setIcon(sender.tab.id, "logo48.png")
5151+ tabsWithDID.set(sender.tab.id, message.did)
4652 } else {
4747- setIcon(sender.tab.id, "logo48_gray.png");
4848- tabsWithDID.delete(sender.tab.id);
5353+ setIcon(sender.tab.id, "logo48_gray.png")
5454+ tabsWithDID.delete(sender.tab.id)
4955 }
5050-});
5656+})
51575258// Open the consent page if it hasn't been accepted and the user clicks on the extension icon
5353-action.onClicked.addListener((tab) => {
5959+action.onClicked.addListener(() => {
5460 storage.get("privacyConsentAccepted", ({ privacyConsentAccepted }) => {
5555- if (typeof privacyConsentAccepted === "undefined" || !privacyConsentAccepted) {
5656- tabs.create({ url: "privacy_consent.html" });
6161+ if (
6262+ typeof privacyConsentAccepted === "undefined" ||
6363+ !privacyConsentAccepted
6464+ ) {
6565+ tabs.create({ url: "privacy_consent.html" })
5766 }
5858- });
5959-});
6767+ })
6868+})
60696170// When the extension icon is clicked, open the profile page if there's a DID
6271action.onClicked.addListener((tab) => {
6363- const did = tabsWithDID.get(tab.id);
7272+ const did = tabsWithDID.get(tab.id)
6473 if (did) {
6565- const newUrl = `${bskyAppUrl}/profile/${did}`;
6666- tabs.create({ url: newUrl });
7474+ const newUrl = `${bskyAppUrl}/profile/${did}`
7575+ tabs.create({ url: newUrl })
6776 }
6868-});
7777+})
+51-50
content.js
···11// Set up cross-browser compatibility
22-const runtime = typeof browser !== 'undefined' ? browser.runtime : chrome.runtime;
33-const tabs = typeof browser !== 'undefined' ? browser.tabs : chrome.tabs;
44-const storage = typeof browser !== 'undefined' ? browser.storage.local : chrome.storage.local;
22+const runtime =
33+ typeof browser !== "undefined" ? browser.runtime : chrome.runtime
44+const storage =
55+ typeof browser !== "undefined" ? browser.storage.local : chrome.storage.local
5666-// Main function to perform actions, but only if the privacy consent has been accepted
77-function performAction(privacyConsentAccepted) {
88- // If the user has accepted the privacy consent
99- if (privacyConsentAccepted) {
1010- // Function to get the domain name from the current hostname
1111- function getDomainName() {
1212- const hostname = window.location.hostname;
1313- return hostname.replace(/^www\./, '');
1414- }
77+// Function to get the domain name from the current hostname
88+function getDomainName() {
99+ const hostname = window.location.hostname
1010+ return hostname.replace(/^www\./, "")
1111+}
15121616- // Function to check for a DID in the domain's TXT records
1717- async function checkForDID(domain) {
1818- // We use Google's DNS over HTTPS API to resolve the TXT record
1919- const response = await fetch(
2020- `https://dns.google/resolve?name=_atproto.${domain}&type=TXT`
2121- );
2222- const data = await response.json();
1313+// Function to check for a DID in the domain's TXT records
1414+async function checkForDID(domain) {
1515+ // We use Google's DNS over HTTPS API to resolve the TXT record
1616+ const response = await fetch(
1717+ `https://dns.google/resolve?name=_atproto.${domain}&type=TXT`
1818+ )
1919+ const data = await response.json()
23202424- // We use the TXT record type to avoid CORS issues
2525- const records = data?.Answer?.filter((record) => record.type === 16) || [];
2121+ // We use the TXT record type to avoid CORS issues
2222+ const records = data?.Answer?.filter((record) => record.type === 16) || []
26232727- // We filter out all records that are not TXT records
2828- const didRecord = records.find((record) =>
2929- record.data.includes("did=did:plc:")
3030- );
2424+ // We filter out all records that are not TXT records
2525+ const didRecord = records.find((record) =>
2626+ record.data.includes("did=did:plc:")
2727+ )
31283232- // We return the DID if we found one
3333- return didRecord ? didRecord.data.replace("did=", "") : null;
3434- }
2929+ // We return the DID if we found one
3030+ return didRecord ? didRecord.data.replace("did=", "") : null
3131+}
35323636- // We check for a DID on the current domain
3737- ;(async function () {
3838- const domain = getDomainName()
3939- const did = await checkForDID(domain)
3333+// Main function to perform actions, but only if the privacy consent has been accepted
3434+function performAction(privacyConsentAccepted) {
3535+ // If the user has accepted the privacy consent
3636+ if (privacyConsentAccepted) {
3737+ // We check for a DID on the current domain
3838+ ;(async function () {
3939+ const domain = getDomainName()
4040+ const did = await checkForDID(domain)
40414141- if (did) {
4242- runtime.sendMessage({ type: "DID_FOUND", did })
4343- } else {
4444- runtime.sendMessage({ type: "DID_NOT_FOUND" })
4545- }
4646- })();
4242+ if (did) {
4343+ runtime.sendMessage({ type: "DID_FOUND", did })
4444+ } else {
4545+ runtime.sendMessage({ type: "DID_NOT_FOUND" })
4646+ }
4747+ })()
47484848- // We listen for messages from the background script
4949- runtime.onMessage.addListener((message, sender, sendResponse) => {
5050- if (message.type === "GET_DID") {
5151- checkForDID(getDomainName())
5252- .then((did) => sendResponse({ did }))
5353- .catch(() => sendResponse({ did: null }))
5454- return true // Indicate that the response will be sent asynchronously.
5555- }
5656- });
4949+ // We listen for messages from the background script
5050+ runtime.onMessage.addListener((message, sender, sendResponse) => {
5151+ if (message.type === "GET_DID") {
5252+ checkForDID(getDomainName())
5353+ .then((did) => sendResponse({ did }))
5454+ .catch(() => sendResponse({ did: null }))
5555+ return true // Indicate that the response will be sent asynchronously.
5656+ }
5757+ })
5758 } else {
5859 // Do nothing since the consent form has not been accepted.
5959- return;
6060+ return
6061 }
6162}
62636364// Get the user's privacy consent from the storage and perform actions accordingly
6465storage.get("privacyConsentAccepted", ({ privacyConsentAccepted }) => {
6565- performAction(privacyConsentAccepted);
6666-});
6666+ performAction(privacyConsentAccepted)
6767+})