11
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Chromeブラウザ拡張機能を作ってみたら意外と簡単だった

Last updated at Posted at 2025-12-23

はじめに

私は、普段利用しているブラウザはFirefoxである。
利用している理由は、「昔から使っているから」というほぼ惰性のようなものだが、気に入っているFirefox独自の機能もある。

それが、ハイパーリンクを右クリックしたときに、その文字列を検索する機能。
文字列を選択することなく、ただ右クリックするだけで検索できる。
image.png

私が知る限りデフォルトでこの機能を持っているのは、メジャーなブラウザではFirefoxのみ。
「使うか?」と思われるかもしれないが、私は時々使う!

ここで、ふと最近思った。他のブラウザでも拡張機能を使えば、同様の機能を実装できるのではないか。
そこで、この「ハイパーリンクを右クリックしたときに、その文字列を検索する機能」を実現する拡張機能を実装してみた。

準備: Chromeブラウザ開発者モードの有効化

Chromeブラウザの拡張機能を開発するのであれば、自作の拡張機能を読み込めるようにする必要がある。
これは、Chromeブラウザの 設定 > 拡張機能から拡張機能画面を開き、「ディベロッパーモード」をオンにすることで読み込めるようになる。
image.png

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

このボタンをクリックし、作った拡張機能のディレクトリを指定してあげれば、拡張機能の動作を確認できる!
やったね!

なお、作った拡張機能のリロードも拡張機能画面から行う。
当該の拡張機能のリロードボタン(丸い矢印のボタン)を押すとリロードできる。
image.png

実装

ファイル構成

ファイル構成は、以下のとおり。

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はマニフェストのバージョン。
nameversiondescriptionはそれぞれ、拡張機能の名前、拡張機能のバージョン、拡張機能の説明。

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ブラウザに読み込ませたところ、次のように動作した。

「ハイパーリンクを検索」のメニューが表示される。
image.png

そのメニューをクリックすると、確かに検索される。
やったね!
image.png

これで、私が実現したかった「ハイパーリンクを右クリックしたときに、その文字列を検索する機能」を実現できた!

思っていたよりも簡単に実現することができた!

おまけ

実はこの拡張機能には欠陥があって、例えば以下のようにリンク付き画像を右クリックしても、「ハイパーリンクを検索」が出てしまう。

image.png

これは、background.jscreateContextMenu()で、ハイパーリンクを右クリックしたときに表示するよう指定したが、文字列に限定していないためである。
そこで、文字列のリンクに限定する方法を公式ドキュメントを確認してみたが、解決策は見つけられなかった。

「ハイパーリンクを検索」をクリックしても不具合を起こすわけでもなく、製品として公開するわけでもない自分用の拡張機能なので黙認することにした。


Chromeは、Google LLCの商標です。
Firefoxは、Mozilla Foundationの商標です。

11
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?