Firefox のアドオンを作ってみた

こんにちは。システム開発推進部、ブラウザタブ乱立マンの芦刈です。
最近、インターネットでの調べものをするたびに「また読み返すかも...」と思ったページを残したタブやウィンドウが増えていった結果、愛用のFirefoxのメモリ使用量が数GBと馬鹿にならないサイズになってしまいました。
一時期はタブグループなんか使ったり、必要なタブだけアクティブにしたりするなど工夫しては居ましたが、途中から面倒になって全部投げ出してしまいました。増えれば増えるほど管理が面倒ですしね。

というわけで今回は、探してもちょうどよさげなアドオンがかなり古いものしかなかったので、現在開いているウィンドウの全タブのページタイトルとURLをテキスト化して出力するアドオンを作ってみました。

f:id:tashi_monex:20220201111258p:plain:w100

知っておくべきこと

大体は下記に集約されています。

developer.mozilla.org

ですが、ここを一読しただけだと引っかかりそうなところをかんたんに説明します。

コンテンツスクリプトとバックグラウンドスクリプト

コンテンツスクリプトは特定のページ上でコンテンツに直接アクセスする形で拡張機能を提供する仕組みです。
これに対して、バックグラウンドスクリプトはページのコンテンツそのものに対して直接変更を及ぼすことはできないものの、代わりとして WebExtension JavaScript API のすべてを利用することができ、複数のウィンドウ、あるいはタブなどのブラウザそのものに対して影響を及ぼすことができる仕組みです。
これらは、アドオン内の manifest.json でそれぞれどのようなスクリプトを利用するかや各権限についての設定を行うことで利用できるようになります。

私はここで滅茶苦茶ハマったのですが、特に気を付けておくべきところは、それぞれでデバッグの際に確認すべき場所が異なる点です。
コンテンツスクリプトはF12を押下するなどして出現した開発ツールのコンソールをそのまま確認することとなります。
それに対して、バックグラウンドスクリプトの場合は Ctrl + Shift + J で開いたブラウザコンソールにおいて、右上の歯車マークから「コンテンツメッセージを表示」をチェックした状態にしなければ、console.log すら確認することができません。

権限について

アドオンを動かす際に、特定の権限が必要な挙動をするものについては、それぞれ要求する権限の設定が必要になります。
ただアドオンを動かすことを考えた場合、重要なのは host 権限と API権限です。
host 権限は、権限が有効となるURLの範囲をマッチパターン形式で設定します。
API 権限は、拡張機能が使用するWebExtension API に応じたキーワードを設定します。
これら権限をきちんと manifest.jsonに設定しておかないと、permission error でアドオンが想定する挙動をしてくれません。
他にも activeTab 権限がありますが、host 権限で<all_urls>を指定していれば、個人で動かす範囲でお世話になることはないでしょう。

上記2つを抑えておけば、後は自分が実現したい機能を作りこむだけです。

実際に作ってみた

右クリック時のコンテキストメニューから「全ウィンドウのタブURL取得」を選択すれば、開いているすべてのウィンドウからタブのタイトルとURLを「タイトル : URL 」の形式でファイル化してダウンロードしてくれるアドオンです。

以下の2ファイルを、適当なフォルダに突っ込んで about:debugging ページから一時的なアドオンとして有効化すれば動きます。

// コンテキストメニューを作成する。
browser.contextMenus.create({
  id: "getting-all-urls",
  title: "全ウィンドウのタブURL取得",
  contexts: ["all", "tab"]
});

// コンテキストメニューの動作を作成する。
browser.contextMenus.onClicked.addListener(() => {
  const urls = [];
  // ウィンドウ内のタブタイトルとurlを取得する。
  browser.tabs.query({}, (tabs) => {
    for (let tab of tabs) {
      urls.push(tab.title + " : " + tab.url);
    }
    // Blob化して一覧ファイルをダウンロードする。
    const blob = new Blob([urls.join(",\n")], { type: 'text/plain' });    
    browser.downloads.download({
      filename: "ブラウザURL一覧.txt",url: URL.createObjectURL(blob)})
  });
});
{
    "manifest_version": 2,
    "name": "addon_test",
    "version": "0.1",
    "description": "Add-on Test",
    "background": {
      "scripts": ["background.js"]
    },
    "permissions": ["<all_urls>","contextMenus","tabs","downloads"]
}

実際に出力した結果は、下記のような感じになります。
実際に実行すると2000以上のタブを開いていました...そんなん読み返せるわけないので完全にアホです。

f:id:tashi_monex:20220201105513p:plain:w500
出力結果(抜粋)

おわりに

今回は自分の愛用ブラウザということで、昔日の思い出Firefoxのアドオンを作成しましたが、同様の手法がChromeの拡張機能にも流用できます。
世にあふれているアドオンは、意外とかゆいところに手が届かないことも良くあることかと思いますので、困ったら今回ご紹介したように気軽にアドオンを作るのはいかがでしょうか?