Manifest version 3(MV3) では background が service worker に置き換えられました。service worker では DOMParser が使えません。
Chrome のバージョン 109 から offscreen を通して service worker で DOMParser が使えるようになりました。
offscreenを使った処理の流れ
- chrome.offscreen.createDocument で offscreen を開く
- (service worker側) chrome.runtime.sendMessage でリクエストを出す
- (offscreen側) chrome.runtime.onMessage で受信して処理する
DOMParser でタイトルを抽出する
以下のコードは document からタイトルを抽出する例です
manifest.json
manifest のバージョンを v3 にして permissions に offscreen を追加します。
{
"manifest_version": 3,
"name": "extension name",
"permissions": [
"offscreen"
],
"background": {
"service_worker": "/service_worker.js"
}
}
service_worker.js
const document = ... // fetch などで取得した文字列
が入っている
chrome.offscreen.createDocument({ reasons: ['DOM_PARSER'], justification: 'parse dom', url: './offscreen.html' })
.then(() => {
chrome.runtime.sendMessage({ action: 'getTitle', document }, (title) => {
chrome.offscreen.closeDocument()
console.log(title)
})
})
offscreen.createDocument の reasons は offscreeの寿命に関係するそうです。justification はどんな役割なのか把握できていません。
offscreen はchrome.offscreen.closeDocument() しなくても放っておけば勝手に終了します。しかし、複数の offscreen が生きていると二重に処理される(このコードでは複数回 title が表示される)可能性があります。意図しない動作を防ぐために明示的にcloseDocument()した方が良いでしょう。
offscree.html
chrome.offscreen.createDocument の url にはローカルのファイルを指定します。そのため、offscreen.js を読み込む offscreen.html を用意します。
<html><head><script src="offscreen.js"></script></head></html>
offscreen.js
メッセージを受信してDOMの解析を行います。
callback で解析した結果を返します。
chrome.runtime.onMessage.addListener((request, _sender, callback) => {
if (request.action === 'getTitle') {
const parser = new DOMParser()
const document = parser.parseFromString(request.document, 'text/html')
const title = document.head.querySelector('title')
callback(title.innerText)
}
})
最後に
offscreen.html を用意しないといけないところが面倒です。
chrome のメッセージングではプリミティブな値しかやり取りできないので注意してください。この例では offscreen.js から document を callback に渡しても service_worker.js では受け取れません。
コメント