Reputation: 89
Goal: I want to add offline functionality to the online webpage via Chrome Browser Extension.
TLDR:
Current state: Changing any CSS or JS is no problem. It's done with content scripts (https://developer.chrome.com/docs/extensions/mv3/content_scripts/). And for additional JavaScript functionality, I'm injecting additional script injected.js through injector.js.
The code for injector.js looks like this:
const s = document.createElement("script");
s.src = chrome.runtime.getURL("script-dist.js");
(document.head || document.documentElement).appendChild(s);
s.onload = function () {
s.parentNode.removeChild(s);
};
Scripts already on the online website are checked "on load" through chrome.declarativeNetRequest (https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/) and swapped to prepared file copy through Internal Redirect (Code 307) that I've downloaded from the website and included to the files in the browser extension.
The problem: But here's the catch. I can't figure out how to inject "a whole" file. Because the Progressive Web Apps (PWA) application needs to have a js file as service-worker.js, I haven't figured out how to "inject it" into the current website. All I'm getting are Cross-Origin Resource Sharing (CORS) errors.
Here's a PWA Offline Fallback template I want to inject into the existing page: https://glitch.com/edit/#!/offline-fallback-demo?path=service-worker.js%3A1%3A0, where the most important is the service-worker.js and offline.html
How would you solve this issue?
Upvotes: 5
Views: 1263
Reputation: 1
apparently there is not direct way of injecting a js file to a web page from an extension, but there is a hack you can use to replace the content of one of the js files that already exist on the web page so you can use it as service worker.
It's basically using the webRequest API, with this you can intercept requests and change the response arbitrary from web extensions.
So the logic would be intercept one of the js files from the page after you try to register it as service worker and replace the response for the code you want in your service worker. It requires a few permissions and the host permission to the urls you want to replace the response.
It would be something like this:
browser.webRequest.onBeforeRequest.addListener(handleRequest, {urls: ["<all_urls>"], types: ["script"]}, ["blocking"])
function handleRequest(details) {
const filter = webRequest.filterResponseData(details.requestId)
let fileText = "";
filter.ondata = (event) => {
const buffer = event.data;
const text = new TextDecoder().decode(buffer);
fileText += text;
}
filter.onstop = () => {
const replacementText = `console.log("Hello world")
self.addEventListener("fetch", (event) => {
console.log("fetch event: ", event);
})
`
const buffer = new TextEncoder().encode(replacementText);
filter.write(buffer);
filter.close();
// Don't forget to do something with the content of the original js file like injecting it somehow.
console.log(fileText);
}
}
Upvotes: 0