diff options
-rw-r--r-- | src/bg/RequestUtil.js | 67 |
1 files changed, 54 insertions, 13 deletions
diff --git a/src/bg/RequestUtil.js b/src/bg/RequestUtil.js index 839ff28..fa099d6 100644 --- a/src/bg/RequestUtil.js +++ b/src/bg/RequestUtil.js @@ -4,10 +4,13 @@ let DEFAULT_CHARSET = "utf-8"; let xmlFeedOrImage = /^(?:(?:application|text)\/(?:(?:r(?:ss|df)|atom)\+)xml(;|$))|image\//i; let rawXml = /^(?:application|text)\/xml;/i; - let brokenOnLoad = (async () => parseInt(await browser.runtime.getBrowserInfo().version) < 61); + let brokenOnLoad; let pendingRequests = new Map(); + let reloadingTabs = new Set(); + let tabKey = (tabId, url) => `${tabId}:${url}`; + let cleanup = r => { pendingRequests.delete(r.requestId); }; @@ -15,11 +18,23 @@ urls: ["<all_urls>"], types: ["main_frame", "sub_frame", "object"] }; - browser.webRequest.onCompleted.addListener(cleanup, filter); + + + browser.webRequest.onCompleted.addListener(r => { + cleanup(r); + let {tabId, url} = r; + let key = tabKey(tabId, url); + if (reloadingTabs.has(key)) { + debug("Reloading tab", key); + browser.tabs.update(tabId, {url}); + } + }, filter); browser.webRequest.onErrorOccurred.addListener(cleanup, filter); let executeAll = async (scripts, where) => { let {url, tabId, frameId} = where; + + let count = 0; for (let details of scripts.values()) { details = Object.assign({ runAt: "document_start", @@ -28,11 +43,13 @@ }, details); try { await browser.tabs.executeScript(tabId, details); + count++; debug("Execute on start OK", url, details); } catch (e) { error(e, "Execute on start failed", url, details); } } + return count; }; var RequestUtil = { @@ -42,7 +59,8 @@ }, async executeOnStart(request, details) { - let {requestId, tabId, frameId, statusCode} = request; + let {requestId, url, tabId, frameId, statusCode} = request; + if (statusCode >= 300 && statusCode < 400) return; let scripts = pendingRequests.get(requestId); let scriptKey = JSON.stringify(details); @@ -54,35 +72,57 @@ return; } + if (frameId === 0) { + let key = tabKey(tabId, url); + debug("Checking whether %s is a reloading tab...", key); + if (reloadingTabs.has(key)) { + debug("Skipping dynamic script injection for reloading feed tab", key); + let filter = browser.webRequest.filterResponseData(requestId); + filter.onstart = e => { + reloadingTabs.delete(key); + filter.write(NULL); + filter.disconnect(); + } + return; + } + } + let content = this.getContentMetaData(request); - debug(request.url, content.type, content.charset); + debug(url, content.type, content.charset); if (xmlFeedOrImage.test(content.type) && !/\/svg\b/i.test(content.type)) return; - let disconnect = !(brokenOnLoad && rawXml.test(content.type)); + if (typeof brokenOnLoad === "undefined") { + brokenOnLoad = await (async () => parseInt((await browser.runtime.getBrowserInfo()).version) < 61)(); + } + + let mustCheckFeed = brokenOnLoad && frameId === 0 && rawXml.test(content.type); + debug("mustCheckFeed = %s, brokenOnLoad = %s", mustCheckFeed, brokenOnLoad); let filter = browser.webRequest.filterResponseData(requestId); let buffer = []; - let first = true; let runAndFlush = async () => { - await executeAll(scripts, request); - if (buffer.length) { + let scriptsRan = await executeAll(scripts, request); + if (mustCheckFeed && !scriptsRan) { + debug(`Marking as "must reload"`, tabId, url); + reloadingTabs.add(tabKey(tabId, url)); + } + if (buffer && buffer.length) { debug("Flushing %s buffer chunks", buffer.length); for (let chunk of buffer) { filter.write(chunk); } - if (disconnect) filter.disconnect(); + filter.disconnect(); buffer = null; } }; if (brokenOnLoad) { filter.onstart = event => { - debug(`onstart ${request.url}`); filter.write(NULL); + debug("onstart", url); } } filter.ondata = event => { - if (first) { runAndFlush(); first = false; @@ -92,11 +132,12 @@ return; } - debug(`ondata ${request.url}`); + debug("ondata", url); filter.write(event.data); - if (disconnect) filter.disconnect(); + filter.disconnect(); }; + } } } |