|
| 1 | +/** |
| 2 | + * This is the background script that runs independent of any document. It |
| 3 | + * listens to main frame requests and kicks in if the headers indicate JSON. If |
| 4 | + * we have the filterResponseData API available, we will use that to change the |
| 5 | + * page to what Chrome displays for JSON (this is only used in Firefox). Then a |
| 6 | + * content script reformats the page. |
| 7 | + */ |
| 8 | + |
| 9 | +import { isJSONContentType } from "./content-type"; |
| 10 | + |
| 11 | +function isRedirect(status: number) { |
| 12 | + return status >= 300 && status < 400; |
| 13 | +} |
| 14 | + |
| 15 | +function detectJSON(event: chrome.webRequest.WebResponseHeadersDetails) { |
| 16 | + if (!event.responseHeaders || isRedirect(event.statusCode)) { |
| 17 | + return; |
| 18 | + } |
| 19 | + for (const header of event.responseHeaders) { |
| 20 | + if ( |
| 21 | + header.name.toLowerCase() === "content-type" && |
| 22 | + header.value && |
| 23 | + isJSONContentType(header.value) |
| 24 | + ) { |
| 25 | + addJsonUrl(event.url); |
| 26 | + if (typeof browser !== "undefined" && "filterResponseData" in browser.webRequest) { |
| 27 | + // We need to change the content type to text/plain to prevent Firefox |
| 28 | + // from using its built-in JSON viewer. |
| 29 | + header.value = "text/plain"; |
| 30 | + } |
| 31 | + } |
| 32 | + } |
| 33 | + |
| 34 | + return { responseHeaders: event.responseHeaders }; |
| 35 | +} |
| 36 | + |
| 37 | +// Listen for onHeaderReceived for the target page. |
| 38 | +chrome.webRequest.onHeadersReceived.addListener( |
| 39 | + detectJSON, |
| 40 | + // Firefox cannot fire onHeadersReceived for local files. |
| 41 | + { urls: ["<all_urls>"], types: ["main_frame"] }, |
| 42 | + ["blocking", "responseHeaders"] |
| 43 | +); |
| 44 | + |
| 45 | +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { |
| 46 | + if (message !== "jsonview-is-json") { |
| 47 | + return; |
| 48 | + } |
| 49 | + |
| 50 | + if (!sender.url) { |
| 51 | + sendResponse(false); |
| 52 | + return; |
| 53 | + } |
| 54 | + |
| 55 | + if (sender.url.startsWith("file://") && sender.url.endsWith(".json")) { |
| 56 | + sendResponse(true); |
| 57 | + return; |
| 58 | + } |
| 59 | + |
| 60 | + hasJsonUrl(sender.url).then(sendResponse); |
| 61 | + return true; // this means "we're going to sendResponse asynchronously" |
| 62 | +}); |
| 63 | + |
| 64 | +async function addJsonUrl(url: string) { |
| 65 | + await chrome.storage.session.set({ [url]: true }); |
| 66 | +} |
| 67 | + |
| 68 | +async function hasJsonUrl(url: string) { |
| 69 | + const stored = await chrome.storage.session.get(url); |
| 70 | + const present = url in stored; |
| 71 | + await chrome.storage.session.remove(url); |
| 72 | + return present; |
| 73 | +} |
0 commit comments