From the docs:
Since service workers don't have access to DOM, it's not possible for an extension's service worker to access the DOMParser API or create an to parse and traverse documents.
Using an external library just for doing what DomParser
already does?? It is too heavy.
To work-around with it, we can use an offscreen
document. It's just invisible webpage where you can run fetch
, audio
, DomParser
, ... and communicate with background (service_worker) via chrome.runtime
.
See an example below:
background.js
// create (load) the offscreen document (xam.html)
chrome.offscreen.createDocument({
url: chrome.runtime.getURL('xam.html'),
reasons: [chrome.offscreen.Reason.DOM_PARSER],
justification: 'reason for needing the document',
});
// This is simply a test.
// It represents a scenario where, after three seconds, you want to fetch a webpage and extract HTML.
// Once the three seconds have elapsed, we send a 'broadcast' out to the listeners of our extension.
// The listener in the offscreen document will handle the job and send back us with its resulting data.
setTimeout(() => {
const onDone = (result) => {
console.log(result);
chrome.runtime.onMessage.removeListener(onDone);
};
chrome.runtime.onMessage.addListener(onDone);
chrome.runtime.sendMessage('from-background-page');
}, 3000);
xam.html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="xam.js">
</script>
</body>
</html>
xam.js
async function main() {
const v = await fetch('https://......dev/').then((t) => t.text());
const d = new DOMParser().parseFromString(v, 'text/html');
const options = Array.from(d.querySelector('select').options)
.map((v) => `${v.value}|${v.text}`)
.join('\n');
chrome.runtime.sendMessage(options);
}
chrome.runtime.onMessage.addListener(async (msg) => {
console.log(msg);
main();
});
manifest.json
"permissions": [
// ...
"offscreen"
]
https://developer.chrome.com/docs/extensions/reference/offscreen/
The extension's permissions carry over to offscreen documents, but extension API access is heavily limited. Currently, an offscreen document can only use the chrome.runtime APIs to send and receive messages; all other extension APIs are not exposed.
Notes:
- I haven't tested how long this
offscreen
document alive.
- Just sample codes, it should work. Customzie as your own cases.