Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion chrome/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "Nordcraft",
"description": "Browser extension for the Nordcraft editor.",
"version": "2.3.5",
"version": "2.3.6",
"icons": {
"32": "icons/nordcraft-32.png",
"64": "icons/nordcraft-64.png",
Expand Down
160 changes: 82 additions & 78 deletions chrome/src/background.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// The .js extension is necessary for Chrome to pickup the import correctly
import { setCookies } from '../../shared/setCookies.js'
import type { RequireFields } from '../../shared/setCookies.js'
import { updateSessionRules } from './helpers.js'
import { nordcraftIsParentFrame, updateSessionRules } from './helpers.js'

console.log('Nordcraft extension loaded')

Expand All @@ -14,24 +14,12 @@ chrome.webNavigation.onBeforeNavigate.addListener(
removeRuleIds: [RULE_ID],
})

if (event.parentFrameId < 0) {
return
}
// check the parent frame so we only override cookies if we are on nordcraft.com
const parentFrame = await chrome.webNavigation.getFrame({
documentId: event.parentDocumentId,
frameId: event.parentFrameId,
const isNordcraft = await nordcraftIsParentFrame({
parentFrameId: event.parentFrameId,
parentDocumentId: event.parentDocumentId,
})

if (!parentFrame) {
return
}

const parentUrl = new URL(parentFrame.url)
if (
parentUrl.host.endsWith('toddle.dev') === false &&
parentUrl.host.endsWith('nordcraft.com') === false
) {
if (!isNordcraft) {
return
}

Expand Down Expand Up @@ -75,72 +63,88 @@ chrome.webNavigation.onBeforeNavigate.addListener(

chrome.webRequest.onHeadersReceived.addListener(
(info) => {
if (info.responseHeaders) {
const setCookieHeaders = info.responseHeaders
.filter(
(h): h is RequireFields<chrome.webRequest.HttpHeaders[0], 'value'> =>
h.name.toLowerCase() === 'set-cookie' &&
typeof h.value === 'string',
)
.map((h) => h.value)
if (setCookieHeaders.length === 0) {
return
// check the parent frame so we only override cookies if we are on nordcraft.com
nordcraftIsParentFrame({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to make the event listener asynchronous on line 65 so you can use await here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, I wasn't able to do it async so that's why I did it like this.

parentFrameId: info.parentFrameId,
parentDocumentId: info.parentDocumentId,
}).then((isNordcraft) => {
if (!isNordcraft) {
return undefined
}
setCookies({
setCookieHeaders,
requestUrl: info.url,
setCookie: async (cookie, domain) => {
await chrome.cookies.set(cookie)

const domainCookies = await chrome.cookies.getAll({
domain,
})

if (domainCookies.length > 0) {
await updateSessionRules({ domainCookies, RULE_ID })
}
},
removeCookie: async (cookie, domain) => {
await chrome.cookies.remove(cookie)

const domainCookies = await chrome.cookies.getAll({
domain,
})

if (domainCookies.length > 0) {
await updateSessionRules({ domainCookies, RULE_ID })
} else {
await chrome.declarativeNetRequest.updateSessionRules({
removeRuleIds: [RULE_ID],
})
}
},
notifyUser: async (requestedUrl) => {
const url = new URL(info.url)
const domainCookies = await chrome.cookies.getAll({
domain: url.host,
})

// Don't return the value for the http cookies and include the requested url
const cookies = domainCookies.map((c) =>
c.httpOnly
? { ...c, url: requestedUrl, value: undefined }
: { ...c, url: requestedUrl },
if (info.responseHeaders) {
const setCookieHeaders = info.responseHeaders
.filter(
(
h,
): h is RequireFields<chrome.webRequest.HttpHeaders[0], 'value'> =>
h.name.toLowerCase() === 'set-cookie' &&
typeof h.value === 'string',
)
.map((h) => h.value)
if (setCookieHeaders.length === 0) {
return
}
setCookies({
setCookieHeaders,
requestUrl: info.url,
setCookie: async (cookie, domain) => {
await chrome.cookies.set(cookie)

const parsedUrl = new URL(cookie.url)
const domainCookies = await chrome.cookies.getAll({
domain: domain ?? parsedUrl.host,
})

const tab = chrome.tabs.query({
active: true,
lastFocusedWindow: true,
})
if (domainCookies.length > 0) {
await updateSessionRules({ domainCookies, RULE_ID })
}
},
removeCookie: async (cookie, domain) => {
await chrome.cookies.remove(cookie)

const parsedUrl = new URL(cookie.url)

tab.then(([t]) => {
if (t && t.id) {
chrome.tabs.sendMessage(t.id, cookies)
const domainCookies = await chrome.cookies.getAll({
domain: domain ?? parsedUrl.host,
})

if (domainCookies.length > 0) {
await updateSessionRules({ domainCookies, RULE_ID })
} else {
await chrome.declarativeNetRequest.updateSessionRules({
removeRuleIds: [RULE_ID],
})
}
})
},
})
}
},
notifyUser: async (requestedUrl) => {
const url = new URL(info.url)
const domainCookies = await chrome.cookies.getAll({
domain: url.host,
})

// Don't return the value for the http cookies and include the requested url
const cookies = domainCookies.map((c) =>
c.httpOnly
? { ...c, url: requestedUrl, value: undefined }
: { ...c, url: requestedUrl },
)

const tab = chrome.tabs.query({
active: true,
lastFocusedWindow: true,
})

tab.then(([t]) => {
if (t && t.id) {
chrome.tabs.sendMessage(t.id, cookies)
}
})
},
})
}
return undefined
})

return undefined
},
{
Expand Down
30 changes: 30 additions & 0 deletions chrome/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,33 @@ export async function updateSessionRules({
],
})
}

export async function nordcraftIsParentFrame({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you do something similar for Firefox as well?

parentFrameId,
parentDocumentId,
}: {
parentFrameId: number
parentDocumentId?: string
}) {
if (parentFrameId < 0) {
return false
}
// check the parent frame so we only override cookies if we are on nordcraft.com
const parentFrame = await chrome.webNavigation.getFrame({
documentId: parentDocumentId,
frameId: parentFrameId,
})

if (!parentFrame) {
return false
}

const parentUrl = new URL(parentFrame.url)
if (
parentUrl.host.endsWith('toddle.dev') === false &&
parentUrl.host.endsWith('nordcraft.com') === false
) {
return false
}
return true
}