HTML processing in Service Worker without access to any foreground document?

Viewed 28

So I am upgrading a Chrome extension to MV3 and the background page now becomes a Service Worker. From this question apparently there is no access to any DOM element. I need to upgrade this function that basically get an HTML snippet and get its text content:

    const htmlStripper = document.createElement("template")
    const striphtml = html => {
        htmlStripper.innerHTML = html
        return htmlStripper.content.textContent
    }

I tried using DocumentFragment as well but it's also not available to Service Worker. Unlike the other question, I do not have access to any foreground HTML page so message passing is not possible as well.

What is a solution for this? Beside this specific problem (nice if I can solve this one), is there a generic solution for all kind of HTML processing we could have done as if we had access to a document?


For my specific case, this solution is good enough, stealing from a C# solution:

    const striphtml = html => {
        return html.replace(/<.*?>/g, "").trim();
    }

Be warned that this is not perfect.

1 Answers

Off-screen document.
For now you can only do some testing in Chrome Canary.
You have to create first a browser shortcut to Chrome Canary with the command line option --enable-features = ExtensionsOffscreenDocuments

const myHtml = "<div>Ciao<span>amico</span>come <b id="foo">va?</b></div>";
await chrome.offscreen.createDocument({
    url: 'osd.html',
    justification: 'ignored',
    reasons: ['dom_scraping']
});
let hd = await chrome.offscreen.hasDocument();
if (hd) {
    let reply = await chrome.runtime.sendMessage({'html': myHtml});
    await chrome.offscreen.closeDocument();                         
    console.log(reply)
}

//manifest.json
...
"permissions": [
    ...
    "offscreen"
]
...

//osd.html
<html><head><script src="osd.js"></script></head></html>

//osd.js
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
    const htmlStripper = document.createElement("template")
    const striphtml = html => {
        htmlStripper.innerHTML = html
        return htmlStripper.content.textContent
    }
    sendResponse({'reply': striphtml(msg.html)})
})
Related