|
4 | 4 | let DEFAULT_CHARSET = "utf-8"; |
5 | 5 | let xmlFeedOrImage = /^(?:(?:application|text)\/(?:(?:r(?:ss|df)|atom)\+)xml(;|$))|image\//i; |
6 | 6 | let rawXml = /^(?:application|text)\/xml;/i; |
7 | | - let brokenOnLoad = (async () => parseInt(await browser.runtime.getBrowserInfo().version) < 61); |
| 7 | + let brokenOnLoad; |
8 | 8 |
|
9 | 9 | let pendingRequests = new Map(); |
10 | 10 |
|
| 11 | + let reloadingTabs = new Set(); |
| 12 | + let tabKey = (tabId, url) => `${tabId}:${url}`; |
| 13 | + |
11 | 14 | let cleanup = r => { |
12 | 15 | pendingRequests.delete(r.requestId); |
13 | 16 | }; |
14 | 17 | let filter = { |
15 | 18 | urls: ["<all_urls>"], |
16 | 19 | types: ["main_frame", "sub_frame", "object"] |
17 | 20 | }; |
18 | | - browser.webRequest.onCompleted.addListener(cleanup, filter); |
| 21 | + |
| 22 | + |
| 23 | + browser.webRequest.onCompleted.addListener(r => { |
| 24 | + cleanup(r); |
| 25 | + let {tabId, url} = r; |
| 26 | + let key = tabKey(tabId, url); |
| 27 | + if (reloadingTabs.has(key)) { |
| 28 | + debug("Reloading tab", key); |
| 29 | + browser.tabs.update(tabId, {url}); |
| 30 | + } |
| 31 | + }, filter); |
19 | 32 | browser.webRequest.onErrorOccurred.addListener(cleanup, filter); |
20 | 33 |
|
21 | 34 | let executeAll = async (scripts, where) => { |
22 | 35 | let {url, tabId, frameId} = where; |
| 36 | + |
| 37 | + let count = 0; |
23 | 38 | for (let details of scripts.values()) { |
24 | 39 | details = Object.assign({ |
25 | 40 | runAt: "document_start", |
|
28 | 43 | }, details); |
29 | 44 | try { |
30 | 45 | await browser.tabs.executeScript(tabId, details); |
| 46 | + count++; |
31 | 47 | debug("Execute on start OK", url, details); |
32 | 48 | } catch (e) { |
33 | 49 | error(e, "Execute on start failed", url, details); |
34 | 50 | } |
35 | 51 | } |
| 52 | + return count; |
36 | 53 | }; |
37 | 54 |
|
38 | 55 | var RequestUtil = { |
|
42 | 59 | }, |
43 | 60 |
|
44 | 61 | async executeOnStart(request, details) { |
45 | | - let {requestId, tabId, frameId, statusCode} = request; |
| 62 | + let {requestId, url, tabId, frameId, statusCode} = request; |
| 63 | + |
46 | 64 | if (statusCode >= 300 && statusCode < 400) return; |
47 | 65 | let scripts = pendingRequests.get(requestId); |
48 | 66 | let scriptKey = JSON.stringify(details); |
|
54 | 72 | return; |
55 | 73 | } |
56 | 74 |
|
| 75 | + if (frameId === 0) { |
| 76 | + let key = tabKey(tabId, url); |
| 77 | + debug("Checking whether %s is a reloading tab...", key); |
| 78 | + if (reloadingTabs.has(key)) { |
| 79 | + debug("Skipping dynamic script injection for reloading feed tab", key); |
| 80 | + let filter = browser.webRequest.filterResponseData(requestId); |
| 81 | + filter.onstart = e => { |
| 82 | + reloadingTabs.delete(key); |
| 83 | + filter.write(NULL); |
| 84 | + filter.disconnect(); |
| 85 | + } |
| 86 | + return; |
| 87 | + } |
| 88 | + } |
| 89 | + |
57 | 90 | let content = this.getContentMetaData(request); |
58 | | - debug(request.url, content.type, content.charset); |
| 91 | + debug(url, content.type, content.charset); |
59 | 92 | if (xmlFeedOrImage.test(content.type) && !/\/svg\b/i.test(content.type)) return; |
60 | | - let disconnect = !(brokenOnLoad && rawXml.test(content.type)); |
| 93 | + if (typeof brokenOnLoad === "undefined") { |
| 94 | + brokenOnLoad = await (async () => parseInt((await browser.runtime.getBrowserInfo()).version) < 61)(); |
| 95 | + } |
| 96 | + |
| 97 | + let mustCheckFeed = brokenOnLoad && frameId === 0 && rawXml.test(content.type); |
| 98 | + debug("mustCheckFeed = %s, brokenOnLoad = %s", mustCheckFeed, brokenOnLoad); |
61 | 99 | let filter = browser.webRequest.filterResponseData(requestId); |
62 | 100 | let buffer = []; |
63 | | - |
64 | 101 | let first = true; |
65 | 102 | let runAndFlush = async () => { |
66 | | - await executeAll(scripts, request); |
67 | | - if (buffer.length) { |
| 103 | + let scriptsRan = await executeAll(scripts, request); |
| 104 | + if (mustCheckFeed && !scriptsRan) { |
| 105 | + debug(`Marking as "must reload"`, tabId, url); |
| 106 | + reloadingTabs.add(tabKey(tabId, url)); |
| 107 | + } |
| 108 | + if (buffer && buffer.length) { |
68 | 109 | debug("Flushing %s buffer chunks", buffer.length); |
69 | 110 | for (let chunk of buffer) { |
70 | 111 | filter.write(chunk); |
71 | 112 | } |
72 | | - if (disconnect) filter.disconnect(); |
| 113 | + filter.disconnect(); |
73 | 114 | buffer = null; |
74 | 115 | } |
75 | 116 | }; |
76 | 117 |
|
77 | 118 | if (brokenOnLoad) { |
78 | 119 | filter.onstart = event => { |
79 | | - debug(`onstart ${request.url}`); |
80 | 120 | filter.write(NULL); |
| 121 | + debug("onstart", url); |
81 | 122 | } |
82 | 123 | } |
83 | 124 |
|
84 | 125 | filter.ondata = event => { |
85 | | - |
86 | 126 | if (first) { |
87 | 127 | runAndFlush(); |
88 | 128 | first = false; |
|
92 | 132 | return; |
93 | 133 | } |
94 | 134 |
|
95 | | - debug(`ondata ${request.url}`); |
| 135 | + debug("ondata", url); |
96 | 136 | filter.write(event.data); |
97 | | - if (disconnect) filter.disconnect(); |
| 137 | + filter.disconnect(); |
98 | 138 | }; |
99 | 139 |
|
| 140 | + |
100 | 141 | } |
101 | 142 | } |
102 | 143 | } |
0 commit comments