アクティブなタブを切り替える度にそのタイトルを取得しGoogleスプレッドシートに書き込むfirefoxアドオンを作った話


概要と、うだうだした話

サークルで一時流行したSlackBot開発も下火になる中、未だに密かにBotに機能を追加しようと開発を続けている者がいた……
この前サークルでの「SlackBot開発によって得られた知見共有会」にて「大学生はプライベートをネタにしてなんぼ」とか息巻いて今後の展望として「今何見てる機能(他の人からメンションを受けると現在見ているサイトをSlackに晒す)」とかを実装すると言いましたそれを実装した際に作った「アクティブなタブを切り替える度にそのURLを取得するfirefoxアドオン」について書きたいと思います。
 そもそも、firefoxのアドオンの作り方について解説してくれてる日本語のサイトが少ないんですよね。Chromeの拡張機能の作り方サイトはかなり充実しているのにfirefoxアドオンでググっても出てくるのは「firefoxアドオン使えなくなる」とかばっかり。firefoxユーザーってそんな少ない訳でも無いでしょうに。というわけでアドオンを作成したい人が参考に出来るようにかなり丁寧に説明しようと思います。

実装の概説

まずGASでGETを受けたら受け取った内容をスプレッドシートに書き込むスクリプトを作る。
firefoxアドオン側でfirefoxのアクティブなタブが切り替わる度にアクティブなタグの名前を取得しスクリプトに向けてGETを飛ばす。

必要なファイル群

今回は閲覧しているページとかを見て何かする訳では無いのでcontent_scriptsは必要ではなくmain.jsとmanifest.jsonにアイコンファイルだけです。この辺はChrome拡張と似てますね。

mainjs
function getCurrentWindowTabs() {
  return browser.tabs.query({currentWindow: true, active: true});
}
function handleCreated(tab) {
  getCurrentWindowTabs().then(tabs => {str=tabs[0].title});
  var url; // リクエスト先URL
  url=url + "?name="+str
  var request = new XMLHttpRequest();
  request.open( "GET", url, true );
  request.send(null);
  request.onreadystatechange = function () {
    if(request.readyState == 4){
          if(request.status == 200){
             console.log(str+'を見てます。');
          }
        }
};
}
browser.tabs.onActivated.addListener(handleCreated);
manifest.json
{
  "manifest_version": 2,
  "name": "Tab URL",
  "version": "1.0",
  "description": "Tab watcher",
  "icons": {
    "48": "icon.png"
  },
  "background": {
    "scripts": ["main.js"]
  },
"permissions": [
"tabs"]

}

main.jsについて、
アクティブなタブを取得する方法が分からなかったのですがこちらのサイト (hawksnowlog: 現在開いているタブの URL を取得する方法) に書いてあったのを参考にしました。要するにbrowser.tabs.queryでタブを取得するとアクティブなタグが配列の一番初めに格納されるらしい。.titleにすることでこのタブのサイトのタイトルを取得出来ます。
tabs.onActivatedがウィンドウ内でアクティブなタブが変わったときに発火するイベントですのでここにリスナーを追加します。

GASの用意

まず新規のGoogleスプレッドシートを作成し「ツール」から「スクリプトエディタ」を開きます。そこに以下のコードをコピペ

function doGet(e) {
  var ss       = SpreadsheetApp.getActiveSpreadsheet();
  var sheet    = ss.getSheetByName('シート1');
  var name=e.parameter.name
  sheet.getRange(1, 1).setValue(name);
  return ContentService.createTextOutput("OK");
}

これでGETを受けた時nameの値をA1のセルに書き込みます。
これで「公開」から「ウェブアプリケーションとして公開」、「Execute the app as:」にはMeを「Who has access to the app:」にはAnyone, even anonymousを選択でデプロイするとURLが発行されるのでこのURLをさっきのmain.jsのリクエスト先URLに代入しておきましょう。

アドオンを発行する方法

さてこのアドオンを自分の環境に読み込ませおきたい時about:debuggingでもいいんですがこれだと一時的な読み込みしかできません。firefoxはchromeと違ってパッケージ化して署名をもらわなければいけません。

まず、manifest.jsonとmain.jsにicon.pngを一つのzipに突っ込みます。
zipの拡張子をxpiに書き換えます。
https://addons.mozilla.org/ja/developers/ここから開発者登録を行い、xpiファイルをアップロードします。
配布手段で「自分自身」の方を選択したら審査なしに即座に使えるようになります。

結果

やってみたら分かると思うんですけどこれ実行すると今見てるタグというよりタグを切り替える前に見ていた一つ前のタグが送信されているみたいなんですよね。多分イベントが発火するのが早いのが原因だと思うのでhandleCreatedに少しだけ待機する処理をかませるといいかもしれませんね。
またタブの切り替えだけでなくページが切り替わった時も取得したい時はtabs.onUpdatedにもリスナーを追加すればいいのでしょうかね。