Skip to content
Open
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
133 changes: 68 additions & 65 deletions background.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
function detectFeed(event) {
let isfeed = false;
let cache_idx = null;

if (event.statusCode == 301 || event.statusCode == 302)
if (event.statusCode === 301 || event.statusCode === 302)
return { responseHeaders: event.responseHeaders };


// force application/rss+xml to text/xml so the browser displays it instead of downloading
let isfeed = false;

for (let header of event.responseHeaders) {
if (header.name.toLowerCase() == 'content-type') {
for (const header of event.responseHeaders) {
if (header.name.toLowerCase() === "content-type") {
if (header.value.match(/application\/((x-)?rss|atom)\+xml/)) {
header.value = header.value.replace(
/application\/((x-)?rss|atom)\+xml/,
'text/xml'
"text/xml",
);
isfeed = true;
}
else if (header.value.toLowerCase() == 'text/xml' || header.value.toLowerCase() == 'application/xml' ) {
if (event.url.endsWith(".rss") || event.url.endsWith(".rss.xml") || event.url.endsWith(".atom") || event.url.endsWith(".atom.xml")) {
} else if (
header.value.toLowerCase() === "text/xml" ||
header.value.toLowerCase() === "application/xml"
) {
if (
event.url.endsWith(".rss") ||
event.url.endsWith(".rss.xml") ||
event.url.endsWith(".atom") ||
event.url.endsWith(".atom.xml")
) {
isfeed = true;
}
}
Expand All @@ -26,22 +33,21 @@ function detectFeed(event) {
}

if (isfeed) {

var cache_idx = null;

for (let i = 0; i < event.responseHeaders.length; i++) {
if (event.responseHeaders[i].name.toLowerCase() == 'cache-control') {
if (event.responseHeaders[i].name.toLowerCase() === "cache-control") {
cache_idx = i;
}
else if (event.responseHeaders[i].name.toLowerCase() == 'content-security-policy') {

} else if (
event.responseHeaders[i].name.toLowerCase() ===
"content-security-policy"
) {
try {
let options = JSON.parse(localStorage.getItem('options'));
const options = JSON.parse(localStorage.getItem("options"));

if (options.enableCss && options.bypassCSP)
event.responseHeaders[i].value = patchCSP(event.responseHeaders[i].value);
}
catch(e) {
event.responseHeaders[i].value = patchCSP(
event.responseHeaders[i].value,
);
} catch (e) {
console.log(e);
}
}
Expand All @@ -54,89 +60,86 @@ function detectFeed(event) {
// don't cache requests we modified
// otherwise on reload the content-type won't be modified again
event.responseHeaders.push({
name: 'Cache-Control',
value: 'no-cache, no-store, must-revalidate',
name: "Cache-Control",
value: "no-cache, no-store, must-revalidate",
});
}

return { responseHeaders: event.responseHeaders };


}

const browser = window.browser || window.chrome;

browser.webRequest.onHeadersReceived.addListener(
detectFeed,
{ urls: ['<all_urls>'], types: ['main_frame'] },
['blocking', 'responseHeaders']
{ urls: ["<all_urls>"], types: ["main_frame"] },
["blocking", "responseHeaders"],
);


function handleMessage(request, sender, sendResponse) {

function handleMessage(request, sender, _sendResponse) {
browser.runtime.getPlatformInfo().then((info) => {

let android = info.os == "android"
browser.storage.sync.get({orangeIcon: android}).then(function(options){

let popup = new URL(browser.runtime.getURL('popup/popup.html'));
popup.searchParams.set('tabId', sender.tab.id.toString());
popup.searchParams.set('feeds', JSON.stringify(request));

if (options.orangeIcon) {
browser.pageAction.setIcon({tabId: sender.tab.id, path: {
"19": "icons/rss-19.png",
"38": "icons/rss-38.png"
}
const android = info.os === "android";
browser.storage.sync.get({ orangeIcon: android }).then((options) => {
const popup = new URL(browser.runtime.getURL("popup/popup.html"));
popup.searchParams.set("tabId", sender.tab.id.toString());
popup.searchParams.set("feeds", JSON.stringify(request));

if (options.orangeIcon) {
browser.pageAction.setIcon({
tabId: sender.tab.id,
path: {
19: "icons/rss-19.png",
38: "icons/rss-38.png",
},
});
}
browser.pageAction.setPopup({
tabId: sender.tab.id,
popup: popup.toString(),
});
}
browser.pageAction.setPopup( {tabId: sender.tab.id, popup: popup.toString() });
browser.pageAction.show(sender.tab.id);

//sendResponse({response: "Response from background script to tab " + sender.tab.url , id: sender.tab.id });
browser.pageAction.show(sender.tab.id);

});
//sendResponse({response: "Response from background script to tab " + sender.tab.url , id: sender.tab.id });
});
});
}

browser.runtime.onMessage.addListener(handleMessage);


function parseCSP(csp) {
let res = {};
const res = {};

let directives = csp.split(";");
for (let directive of directives) {
let kw = directive.trim().split(/\s+/g);
let key = kw.shift();
let values = res[key] || [];
const directives = csp.split(";");
for (const directive of directives) {
const kw = directive.trim().split(/\s+/g);
const key = kw.shift();
const values = res[key] || [];
res[key] = values.concat(kw);
}

return res;
}

function patchCSP(csp) {
let parsed_csp = parseCSP(csp);
const parsed_csp = parseCSP(csp);

let stylesrc = parsed_csp['style-src'] || [];
if (! stylesrc.includes("'unsafe-inline'") ) {
let newstylesrc = ["'unsafe-inline'"];
const stylesrc = parsed_csp["style-src"] || [];
if (!stylesrc.includes("'unsafe-inline'")) {
const newstylesrc = ["'unsafe-inline'"];

for (let src of stylesrc) {
if (!src.startsWith("'nonce") && !src.startsWith('sha'))
for (const src of stylesrc) {
if (!src.startsWith("'nonce") && !src.startsWith("sha"))
newstylesrc.push(src);
}

parsed_csp['style-src'] = newstylesrc;
parsed_csp["style-src"] = newstylesrc;

let new_csp = "";

for (let kw in parsed_csp) {
new_csp += kw + " " + parsed_csp[kw].join(" ") + "; ";
for (const kw in parsed_csp) {
new_csp += `${kw} ${parsed_csp[kw].join(" ")}; `;
}
new_csp = new_csp.substring(0, new_csp.length-2);
new_csp = new_csp.substring(0, new_csp.length - 2);
return new_csp;
}
return csp;
Expand Down
35 changes: 35 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.10/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": false
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
119 changes: 60 additions & 59 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,59 +1,60 @@
{

"manifest_version": 2,
"name": "RSSPreview",
"version": "3.34",
"author": "Aurelien David",
"homepage_url": "https://github.com/aureliendavid/rsspreview",

"description": "Preview RSS feeds in browser",


"icons": {
"32": "icons/rss-32.png",
"48": "icons/rss-48.png",
"64": "icons/rss-64.png",
"128": "icons/rss-128.png",
"256": "icons/rss-256.png"
},

"background": {
"scripts": ["background.js"]
},


"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["rsspreview.js"]
}
],

"web_accessible_resources": ["preview.css", "rss.xsl", "icons/*.png"],


"options_ui": {
"page": "settings/options.html"
},

"page_action": {
"browser_style": true,
"default_icon": {
"19": "icons/rss-gray-19.png",
"38": "icons/rss-gray-38.png"
},
"default_title": "Feeds in page"
},

"browser_specific_settings": {
"gecko": {
"id": "{7799824a-30fe-4c67-8b3e-7094ea203c94}"
},
"gecko_android": {
"strict_min_version": "113.0"
}
},

"permissions": ["<all_urls>", "webRequest", "webRequestBlocking", "storage", "tabs"]

}
{
"manifest_version": 2,
"name": "RSSPreview",
"version": "3.34",
"author": "Aurelien David",
"homepage_url": "https://github.com/aureliendavid/rsspreview",

"description": "Preview RSS feeds in browser",

"icons": {
"32": "icons/rss-32.png",
"48": "icons/rss-48.png",
"64": "icons/rss-64.png",
"128": "icons/rss-128.png",
"256": "icons/rss-256.png"
},

"background": {
"scripts": ["background.js"]
},

"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["rsspreview.js"]
}
],

"web_accessible_resources": ["preview.css", "rss.xsl", "icons/*.png"],

"options_ui": {
"page": "settings/options.html"
},

"page_action": {
"browser_style": true,
"default_icon": {
"19": "icons/rss-gray-19.png",
"38": "icons/rss-gray-38.png"
},
"default_title": "Feeds in page"
},

"browser_specific_settings": {
"gecko": {
"id": "{7799824a-30fe-4c67-8b3e-7094ea203c94}"
},
"gecko_android": {
"strict_min_version": "113.0"
}
},

"permissions": [
"<all_urls>",
"webRequest",
"webRequestBlocking",
"storage",
"tabs"
]
}
Loading