rss-viewer-browser-extension/src/background.ts

102 lines
2.2 KiB
TypeScript
Raw Normal View History

import browser from 'webextension-polyfill';
interface State {
awaitingResponse: boolean
feedUrl: string | null
}
const state: State = {
awaitingResponse: false,
feedUrl: null,
}
const getActiveTab = async () => {
const [tab] = await browser.tabs.query({
active: true,
currentWindow: true
})
return tab
}
const onFeedDownloaded = (req: XMLHttpRequest) => {
return async () => {
state.awaitingResponse = false
if (req.status >= 400) {
console.error(
`Could not load URL feed: ${req.responseURL}: ` +
`${req.status}: ${req.statusText}`
)
return
}
const tab = await getActiveTab()
if (!tab || tab.id === -1)
return
await browser.tabs.sendMessage(
tab.id, {
type: 'renderFeed',
document: req.responseText
}
)
}
}
const renderFeed = (url: string) => {
state.awaitingResponse = true
const req = new XMLHttpRequest()
req.onload = onFeedDownloaded(req)
req.open('GET', url)
req.responseType = 'text'
req.send()
}
const updateFeedUrl = (tabId: number, feedUrl: string | null) => {
if (!feedUrl?.length) {
browser.pageAction.hide()
state.feedUrl = null
} else {
browser.pageAction.show(tabId)
state.feedUrl = feedUrl
}
}
browser.pageAction.onClicked.addListener(
async () => {
if (state.feedUrl?.length)
renderFeed(state.feedUrl)
}
)
browser.webNavigation.onCompleted.addListener(
async (event: {tabId: number}) => {
const { tabId } = event
const feedUrl = await browser.tabs.sendMessage(tabId, {type: 'extractFeedUrl'})
updateFeedUrl(tabId, feedUrl)
await browser.tabs.sendMessage(tabId, {type: 'renderFeed'})
}
)
browser.webRequest.onHeadersReceived.addListener(
async (event: {
url: string,
responseHeaders: Array<{name: string, value: string}>
}) => {
if (state.awaitingResponse)
return
const {url, responseHeaders} = event
const contentType = responseHeaders.find(
h => h.name.toLowerCase() === 'content-type'
)?.value || ''
if (contentType.startsWith('application/rss+xml'))
renderFeed(url)
},
{urls: ['<all_urls>']},
['blocking', 'responseHeaders']
)