はじめに
私は、普段利用しているブラウザはFirefoxである。
利用している理由は、「昔から使っているから」というほぼ惰性のようなものだが、気に入っているFirefox独自の機能もある。
それが、ハイパーリンクを右クリックしたときに、その文字列を検索する機能。
文字列を選択することなく、ただ右クリックするだけで検索できる。

私が知る限りデフォルトでこの機能を持っているのは、メジャーなブラウザではFirefoxのみ。
「使うか?」と思われるかもしれないが、私は時々使う!
ここで、ふと最近思った。他のブラウザでも拡張機能を使えば、同様の機能を実装できるのではないか。
そこで、この「ハイパーリンクを右クリックしたときに、その文字列を検索する機能」を実現する拡張機能を実装してみた。
準備: Chromeブラウザ開発者モードの有効化
Chromeブラウザの拡張機能を開発するのであれば、自作の拡張機能を読み込めるようにする必要がある。
これは、Chromeブラウザの 設定 > 拡張機能から拡張機能画面を開き、「ディベロッパーモード」をオンにすることで読み込めるようになる。

有効化すると、左上に「パッケージ化されていない拡張機能を読み込む」ボタンが表示される。

このボタンをクリックし、作った拡張機能のディレクトリを指定してあげれば、拡張機能の動作を確認できる!
やったね!
なお、作った拡張機能のリロードも拡張機能画面から行う。
当該の拡張機能のリロードボタン(丸い矢印のボタン)を押すとリロードできる。

実装
ファイル構成
ファイル構成は、以下のとおり。
project/
┣ manifest.json
┗ background.js
mainfest.jsonには拡張機能の構成などを定義するマニフェストファイル。拡張子の名前やアイコンといった拡張機能の情報を記述するほか、拡張機能の動作記述する.jsファイルの指定、拡張機能が利用する権限を指定する。
他方、backgraund.jsonには、拡張機能の動作を記述する。
manifest.json
作成したマニフェストファイルは以下の通り。
{
"manifest_version": 3,
"name": "リンクテキスト検索",
"version": "1.0",
"description": "ハイパーリンクの文字列を右クリックして検索する",
"permissions": [
"contextMenus",
"search",
"scripting"
],
"host_permissions": [
"<all_urls>"
],
"background": {
"service_worker": "background.js"
}
}
manifest_versionはマニフェストのバージョン。
name、version、descriptionはそれぞれ、拡張機能の名前、拡張機能のバージョン、拡張機能の説明。
permissionsは、拡張機能が利用する権限。
今回は、右クリックメニュー関連のcontextMenus、検索のsearch、コンテキストに対するスクリプト実行のscriptingを利用するので、それらを指定する。
host_permissionsは、拡張機能が操作できるウェブページ。要はCORSみたいなもの。
最後に、backgroundは、拡張機能Service workerを指定する。今回は、background.jsを指定する。
参考:
マニフェスト ファイル形式
background.js
拡張機能の動作を記述する。
なお、一部AIにも書いてもらった。
const MENU_ID = "searchLink";
/**
* コンテキストメニュー(右クリックメニュー)を作成
*/
function createContextMenu() {
chrome.contextMenus.removeAll(() => {
chrome.contextMenus.create({
id: MENU_ID,
title: "ハイパーリンクを検索", // 右クリックメニューで表示される文字列
contexts: ["link"] // ハイパーリンクを右クリックしたときに表示するよう指定
});
});
}
/**
* リンクテキストを取得して検索を実行
*/
async function handleLinkSearch(tab) {
try {
// chrome.scripting APIを利用して、ページからアクティブな要素のテキストを取得
const results = await chrome.scripting.executeScript({
target: { tabId: tab.id },
function: () => document.activeElement?.textContent
});
const linkText = results?.[0]?.result;
if (linkText) {
// chrome.search APIを利用して新しいタブで検索を実行
chrome.search.query({
text: linkText,
disposition: "NEW_TAB"
});
}
} catch (error) {
console.error("Error:", error);
}
}
// ここでイベントリスナーに追加しないと動作しない
chrome.runtime.onInstalled.addListener(createContextMenu);
chrome.runtime.onStartup.addListener(createContextMenu);
chrome.contextMenus.onClicked.addListener((info, tab) => {
if (info.menuItemId === MENU_ID) {
handleLinkSearch(tab);
}
});
簡単に解説すると、createContextMenu()はコンテキストメニュー(右クリックメニュー)に「ハイパーリンクを検索」項目を追加する。
次に、handleLinkSearch()は、内部でchrome.search.query()を利用し、リンクテキストを検索する。ただし、直接コンテンツの内容を取得できないので、chrome.scripting.executeScript()を利用してリンクテキストを取得する。
あとはこれらをイベントリスナーに登録してあげればよい。
動作
上記のファイル構成でChromeブラウザに読み込ませたところ、次のように動作した。
そのメニューをクリックすると、確かに検索される。
やったね!

これで、私が実現したかった「ハイパーリンクを右クリックしたときに、その文字列を検索する機能」を実現できた!
思っていたよりも簡単に実現することができた!
おまけ
実はこの拡張機能には欠陥があって、例えば以下のようにリンク付き画像を右クリックしても、「ハイパーリンクを検索」が出てしまう。
これは、background.jsのcreateContextMenu()で、ハイパーリンクを右クリックしたときに表示するよう指定したが、文字列に限定していないためである。
そこで、文字列のリンクに限定する方法を公式ドキュメントを確認してみたが、解決策は見つけられなかった。
「ハイパーリンクを検索」をクリックしても不具合を起こすわけでもなく、製品として公開するわけでもない自分用の拡張機能なので黙認することにした。
Chromeは、Google LLCの商標です。
Firefoxは、Mozilla Foundationの商標です。

