comparison js/background.js @ 10:ff5e5e3eba32

Implement feed subscription for web-based feed readers Add options page for configuring web-based feed readers which allow for subscribing to feeds via GET requests. Track tabs containing feed previews and inject a content script which retrieves the configured feed readers and keeps them in sync.
author Guido Berhoerster <guido+feed-preview@berhoerster.name>
date Fri, 07 Dec 2018 23:00:41 +0100
parents 5d7c13e998e9
children a4590add4901
comparison
equal deleted inserted replaced
9:fcd65cf3f634 10:ff5e5e3eba32
15 '<rss', 15 '<rss',
16 '<feed', 16 '<feed',
17 ...Object.values(feedParser.XMLNS) 17 ...Object.values(feedParser.XMLNS)
18 ]; 18 ];
19 var tabsFeeds = new Map(); 19 var tabsFeeds = new Map();
20 var tabsFeedPreviews = new Map();
20 var fetchingFeedPreview = fetch('web_resources/feed-preview.xhtml') 21 var fetchingFeedPreview = fetch('web_resources/feed-preview.xhtml')
21 .then(response => response.text()); 22 .then(response => response.text());
22 23
23 function parseContentType(header) { 24 function parseContentType(header) {
24 let contentType = { 25 let contentType = {
36 } 37 }
37 38
38 return contentType; 39 return contentType;
39 } 40 }
40 41
41 async function handleFeed(inputText, url) { 42 async function handleFeed(inputText, tabId, url) {
42 // fast-path: eliminate XML documents which cannot be Atom nor RSS feeds 43 // fast-path: eliminate XML documents which cannot be Atom nor RSS feeds
43 let inputTextStart = inputText.substring(0, 512); 44 let inputTextStart = inputText.substring(0, 512);
44 if (!FEED_MAGIC.some(element => inputTextStart.includes(element))) { 45 if (!FEED_MAGIC.some(element => inputTextStart.includes(element))) {
45 return inputText; 46 return inputText;
46 } 47 }
56 return inputText; 57 return inputText;
57 } 58 }
58 throw e; 59 throw e;
59 } 60 }
60 console.log(`parsed feed ${url}:\n`, feed); 61 console.log(`parsed feed ${url}:\n`, feed);
62
63 // mark this feed preview for content script injection
64 tabsFeedPreviews.set(tabId, url);
61 65
62 // render the preview document 66 // render the preview document
63 let feedPreviewDocument = new DOMParser() 67 let feedPreviewDocument = new DOMParser()
64 .parseFromString(await fetchingFeedPreview, 'text/html'); 68 .parseFromString(await fetchingFeedPreview, 'text/html');
65 renderFeedPreview(feedPreviewDocument, feed); 69 renderFeedPreview(feedPreviewDocument, feed);
116 let filter = browser.webRequest.filterResponseData(details.requestId); 120 let filter = browser.webRequest.filterResponseData(details.requestId);
117 filter.addEventListener('data', ev => { 121 filter.addEventListener('data', ev => {
118 inputText += decoder.decode(ev.data, {stream: true}); 122 inputText += decoder.decode(ev.data, {stream: true});
119 }); 123 });
120 filter.addEventListener('stop', async ev => { 124 filter.addEventListener('stop', async ev => {
121 let result = await handleFeed(inputText, details.url); 125 let result = await handleFeed(inputText, details.tabId, details.url);
122 filter.write(encoder.encode(result)); 126 filter.write(encoder.encode(result));
123 filter.close(); 127 filter.close();
124 }); 128 });
125 129
126 details.responseHeaders[contentTypeIndex] = { 130 details.responseHeaders[contentTypeIndex] = {
143 // popup querying feeds 147 // popup querying feeds
144 sendResponse(tabsFeeds.get(request)); 148 sendResponse(tabsFeeds.get(request));
145 } 149 }
146 }); 150 });
147 151
148 browser.tabs.onUpdated.addListener((id, changeInfo, tab) => { 152 browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
149 if (typeof changeInfo.url === 'undefined') { 153 if (typeof changeInfo.url === 'undefined') {
150 // filter out updates which do not change the URL 154 // filter out updates which do not change the URL
151 return; 155 return;
152 } 156 }
153 157
154 // hide the page action when the URL changes since it is no longer valid, 158 // hide the page action when the URL changes since it is no longer valid,
155 // it will be shown again if the content script detects a feed 159 // it will be shown again if the content script detects a feed
156 browser.pageAction.hide(tab.id); 160 browser.pageAction.hide(tabId);
161
162 // inject content script once if the requested URL is a feed preview
163 if (tabsFeedPreviews.get(tabId) === changeInfo.url) {
164 browser.tabs.executeScript(tabId, {
165 file: 'content_scripts/feed-readers.js'
166 });
167 tabsFeedPreviews.delete(tabId);
168 }
157 }); 169 });
158 170
159 browser.tabs.onRemoved.addListener((tabId, removeInfo) => { 171 browser.tabs.onRemoved.addListener((tabId, removeInfo) => {
160 tabsFeeds.delete(tabId); 172 tabsFeeds.delete(tabId);
173 tabsFeedPreviews.delete(tabId);
161 }); 174 });