前置き
自作のChrome/Firefox拡張機能をManifest V3に対応させる過程で詰まったのでメモ
この拡張機能では、ServiceWorkerとしてcontextmenu.jsを実行させて、そこでコンテキストメニューのイベントを拾って処理をして結果をクリップボードにコピーしてる。
そのコピー処理のとこで問題が。
MV2のときはdocument.execCommandを利用していたのだけど、MV3になってバックグラウンド処理がServiceWorkerになった関係で利用できなくなった。Clipboard APIも使えないらしい、さてどうしたものか..
新しいタブを開き、そこでコピーする方法
ggってたらこの記事を見つけた
別解として、新しいタブを開いてスクリプトを挿入する方法があります。より安全にスクリプトを注入できます。ただし、タブのオープン・クローズによる画面のちらつきがあります。
なるほどそんな方法が。というわけで早速やってみる
// contextmenu.js
// 中略
const copy_url = "コピーするURL"
chrome.tabs.query({ active: true, lastFocusedWindow: true, audible: true})
.then(tab => {
if (tab[0] != undefined) {
chrome.storage.local.set({"tab_id": tab[0].id})
chrome.storage.local.set({"copy_url": copy_url})
chrome.tabs.create({url: 'copy.html'})
} else {
throw new Error("tab is undefined")
}
}).catch(error => {
console.error("現在タブの取得に失敗", error)
})
// copy.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>コピー用ページ</title>
<script src="copy.js"></script>
</head>
</html>
// copy.js
chrome.storage.local.get(["copy_url", "tab_id"])
.then(items => {
navigator.clipboard.writeText(items.copy_url)
.then(() => {
// 成功:copy.htmlが開く前に選択してたタブを選択する
chrome.tabs.update(items.tab_id, { selected: true });
// 即閉じするとなぜかコピペされない
setTimeout(() => {window.close()}, 10);
}).catch(error => {
throw new Error("copy failed")
});
}).catch(error => {
console.error("コピー処理に失敗", error)
});
- 今のタブIDとコピーする文字列をストレージに保存(manifest.jsonのpermissionsで”storage”を宣言する必要あり)
- コピー処理用のページを開いてコピー処理する
- タブIDを指定して、さっき開いてたタブを選択しなおす
課題点
さっき引用した中にもあったけど、タブ移動でちらつきが出る。
一応現在のページにjsを仕込んでServiceWorkerから呼び出してコピーさせる方法?もあるみたいだけど、全ページへのアクセス許可求めるのは個人的にはちょっと抵抗あるかも
それと、アクセス許可のポップアップが出てきて、ブロックされるとコピーできない。
ブロック解除方法をcopy.htmlに書いておいた方がいいかも。
chrome.action.setPopup使ってポップアップで表示できればちらつき問題は解消できるかなと思ったけど、自分が試したところ(ver108.0.5359.126)なんか使えなかった。stableではまだ実装されてないらしい。
Firefoxでの挙動
manifest.jsonのpermissionsで”clipboardWrite”を宣言しておけば許可ポップアップなしでコピーできた。
宣言してない場合はコピーに失敗する(ポップアップ無し)
コメント
Hi! I just finished reading your blog post, and I must say, it was excellent. Your ability to explain complicated concepts in a simple and engaging way is truly remarkable. Thank you for providing such valuable content. I can’t wait to read more from you in the future.