Chrome拡張にコンテキストメニューを追加する
Chrome拡張にコンテキストメニューを追加する
趣味がChrome拡張を作る人みたいになっています。毎回書いている気がしますが、Chrome拡張はフロントエンドの勉強を行うのにお手軽な素材です。そして、日々手を動かすネタを考えています。
タイトルの通り、 「そういえばChrome拡張ってコンテキストメニューにコマンド追加出来るよなぁ」 って思ったのでちょっとやってみました。
参考にしたページ
manifest.json に追加
permissions のリストの中に contextMenus
を追加する。
"permissions": [
"activeTab",
"clipboardWrite",
+ "contextMenus",
"scripting",
"storage",
"tabs",
"webRequest"
],
ServiceWorkerにコンテキストメニューを追加する処理を追加
参考にさせていただいたページの通り、ServiceWorkerのコードに以下のようなコードを追加しました。
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: 'copy_all_urls',
title: 'ページ内のリンクをクリップボードにコピーする',
});
});
このコードを追加するとコンテキストメニューにアイテムが追加される。
拡張機能が最初にインストールされた時や、新しいバージョンへ更新された時、ブラウザーが新しいバージョンへ更新された時に発火します。
MSDNのマニュアルのとおり、Chrome拡張の更新が行われたときに発火するイベントを使ってコンテキストメニューを追加する。
コンテキストメニューのクリックイベントを追加する
今度はコンテキストメニューのクリックイベントを追加する。
chrome.contextMenus.onClicked.addListener((info, tab) => {
if (info.menuItemId === 'copy_all_urls') {
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: copyAllUrlInPage,
});
}
});
manifest.json
の permissions
に予め scripting
を追加しておく必要がある。
追加されていないと chrome.scripting.executeScript
が権限がないため以下のエラーが発生する。
Error in event handler: TypeError: Cannot read properties of undefined (reading 'executeScript')
onClicked.addListener
の第1引数 OnClickData に含まれている menuItemId
には追加したコンテキストメニューのIDが設定される。
そのため、今回のように1件であれば条件分岐する必要は無いが、複数件追加した場合にはIDに応じて条件分岐する必要がある。
chrome.scripting.executeScript
の引数 func
で予め定義しておいた関数を呼び出す形になる。
ここでは chrome.scripting.executeScript
の引数 target
に指定している通り、任意のタブで実行するため ContextMenu のスクリプトは定義自体は ServiceWorker 内で定義するものの、実行するコードの領域としては ContentsScript 内になる。
また、ContextMenuのスクリプトは独立して実行されるようで、メソッドや変数のスコープはContextMenu内で閉じてしまうようだ。そのため、ContextMenu外で定義された変数や関数といったものは使えない。
ここら辺はなんとか重複しないコードの実装が出来れば嬉しいんだが…。
感想
思ったよりも簡単にコンテキストメニューの追加を行えることがわかった。
ただ、実際に複雑な実装を行うのであればメッセージパッシングを行ってServiceWorkerに処理を委譲したりしないといけなさそうなので設計が肝になりそう。
最終的な追加差分
Discussion