2020年6月22日月曜日

アドオンのThunderbird 78対応の仕方

Thunderbird 78は、Beta2までリリースされ、残すはBeta3の一回のみ、6/30には正式リリースと、秒読み態勢に入りました。
[2020/7/1] 追加でBeta4がリリースされ、正式リリースは7/6になったようです。
[2020/7/17] Thunderbird 78が正式リリースされました。

アドオン作者としては、アドオンの総作り直しが必要な、とんでもないバージョンアップです。(WebExtensions/MailExtensionsでの作り直し)

幸い、私のアドオンは、一部対応見送りをしたものの、予定していたものはなんとか間に合いました。

ここでは、備忘録もかねて、これからアドオン作成にチャレンジしたい、従来アドオンをなんとか動くようにしたい方のために、私が参考にした情報をまとめます。

前提知識として、JavascriptとHTML/CSSが必要です。他のプログラミング言語を知っていれば、サンプルコード等でなんとなくわかるかもしれませんが、Javascriptは、若干、変態仕様があり、つまづく可能性があります。


Javascript
Javascriptで得だしで押さえておきたい内容です。比較的新しめな(?)言語仕様で、従来のアドオン開発では使う機会がなく、私も今回の対応で初めて知ったものです。

■Promise, async, await
WebExtensions/MailExtensionsでは、非同期関数がよくつかわれ、Promise, async, awaitは重要なキーワードになります。

ざっくり言うと、asyncが非同期関数の宣言、非同期関数の戻り値がPromise、非同期関数の実行完了を待つ場合のキーワードがawaitです。重い処理でリソースを占有してしまい、UIが固まってしまうなどが起きないようにする仕組みです。

Promise
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Using_promises

async/await
https://wiki.developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function

上記にはいろいろ書かれていますが、よく使うのは、APIがPromiseを返す場合に、awaitを使ってPromiseの解決を待つパターンと思います。

例えば、タグの配列を返す messages.listTags() というAPIがありますが、これは非同期関数になります。タグのリストを手に入れて何か処理する関数(getTags())は、以下のようにします。

async function getTags() {
  let tags = await browser.messages.listTags();
  for (let i = 0; i < tags.length; i++) {
    let tag = tags[i];
    ...
  }
}
ポイントは、async/awaitです。

まず、listTags() は非同期関数なので、実行完了を待つためにawaitをつけます。これをつけないと、listTags()の完了を待たずに次のfor文に行ってしまい、うまく動きません。

さらに、このawaitは非同期関数の中でしか使えないので、asyncを使ってgetTags()関数を、非同期関数として定義します。

■アロー関数
WebExtensionsのコードを読んでいると、頻繁に「param => { ... }」という記述が出てくると思います。これは、「function(param) { ... }」とほぼ同意です。

細かくは、「this」の扱いが違っていたりしますので、詳細は以下をご確認ください。

アロー関数
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions


MailExtensions
■Hello world/サンプルコード
さて、いよいよ本題のMailExtensionsですが、まずはHello worldから。
ということで、以下にあります。

Hello world
https://developer.thunderbird.net/add-ons/examples/hello-world-add-on

ポップアップでHello worldを表示するスクリプトですが、で?という感じかと思います。
なんか動いたけど、やりたいこととのギャップが大きすぎる。

で、残念ながら、そのギャップを埋めるマニュアル等は現時点ではありません。
Thunderbirdチームが、以下にサンプルコードをおいているので、これを参考にすることになります。

サンプルコード
https://github.com/thundernest/sample-extensions

Firefoxのサンプルコードも参考になります。
 
いきなりサンプルコードをあたってもよいと思いますが、Hello worldにある、アドオンのインストール/デバッグの仕方は、確認しておいたほうがよいです。

私のアドオンのコードもよかったら参考にしてください。XPIファイルをダウンロードして、ZIPで解凍すれば見れます。
https://hogi-ja.blogspot.com/2020/06/thunderbird-78.html

■API
実際のアドオン作成は、サンプルコードを骨格に、必要なAPIを呼び出して、という流れになるかと思います。

APIは以下にあります。

WebExtensionsはFirefoxのもので、Thunderbirdでも使用できます。
(全部使えるかは、ちょっとわからないです)

WebExtensions API
https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions

Thunderbird用に追加されたAPI群がMailExtensionsです。WebExtensionsと呼んでいたりするので、そのうち、WebExtensionsに呼び方が統一されるかもしれません。

MailExtensions API
https://thunderbird-webextensions.readthedocs.io/en/latest/

これらのAPIは「browser」オブジェクトの中にあります。
例えば、accounts APIのlist()を呼びたい場合は、
  browser.accounts.list();
のようにします。

また、各APIのページに必要なパーミッションが書かれているので、manifest.jsonの中で指定するようにしてください。忘れていると動かず、エラーメッセージも分かりにくいのでハマります。

accounts APIだと、accountsReadが必要とあるので、
  "permissions": [
    "accountsRead"
  ],
のように指定します。

なお、ページの左下で、APIのバージョンを選ぶようになっています。現状だと、v68とlatestがありますが、Thunderbird 78向けにはlatestを選ぶようにしてください。v68とlatestで、API仕様が変わっていたり、APIが追加されていたりします。




WebExtension Experiments
■Experiments
これは、Thunderbirdにだけ許された大技です。(Firefoxでは禁止)
既存のアドオンを書き換えようとした場合に、WebExtensions/MailExtensions APIでは、できないことがほとんどだと思います。

そこで、自分でAPIを作ってしまおうというのが、WebExtension Experimentsです。これを使えば、従来のアドオンのように、Thunderbird内部を自由に触れるようになります。

WebExtension Experiments
https://thunderbird-webextensions.readthedocs.io/en/latest/how-to/experiments.html

Thunderbirdチームのサンプルコードの「experiment」に、上記のスクリプトがあるので、それをベースにするとよいと思います。

また、APIの名前やパラメタなどのインタフェースを定義するとき(schema.json)に、この場合どう書くんだ?というケースがでてくると思います。その場合は、文書を探すよりも、以下にジェネレータが用意されているので、こっちでサンプルコードを出してしまったほうが早いです。


Experiment API Generator
https://darktrojan.github.io/generator/generator.html


私のアドオンだと、
  • Maximize Message Pane
  • Tag Popup
  • New Tab Button
が、Experimentsを使用しています。
こちらも、よければご参考に。

■Thunderbird内部の変更点
Experimentsを使用すれば、自由度の高いことができる反面、Thunderbird内部の変更に追従していく必要があります。WebExtensions/MailExtensionsに移行した後、Thunderbirdチームは、ドラスティックにいじってくると思われます。

Thunderbird 68から78に向けて、現時点でまとめられている変化点は以下です。

Thunderbird 69-78の変化点
https://developer.thunderbird.net/add-ons/updating/tb78/changes 

特に、document.createElement() から document.createXULElement() の変更は、既存アドオンの書き換え時にハマるポイントかと思います。

createElement()はHTMLエレメントを返すようになるので、ThunderbirdのUIをいじっている場合は、createXULElement()で、XULエレメントを作る必要があります。たいてい、一括置換してしまえばいいはずです。

そもそもThunderbird 68にすら対応していない場合は、さかのぼって修正していく必要があります。

Thunderbird 61-68の変化点
https://developer.thunderbird.net/add-ons/updating/tb68/changes

Thunderbird 57-60の変化点
https://wiki.mozilla.org/Thunderbird/Add-ons_Guide_57

上記のように、WebExtension Experimentsは、なかなかにしんどい作業が多く、今後のThunderbirdの変更にも追従していく必要があるので、できれば取りたくない方針です。既存アドオンを書き換える場合は、まず、標準のAPIでできないかを検討して、それでもできないものを、Experimentsで実装していくのをおすすめします。


その他の情報
■開発ツール
Thunderbirdに組み込みの開発ツールでのデバッグの仕方です。Firefoxの説明ですが、Thunderbirdも同様です。 これが使えるとかなり開発が楽になります。

https://extensionworkshop.com/documentation/develop/debugging/

■メーリングリスト
アドオン開発のメーリングリストです。

英語ですが、これどうやってやるの?的な話題もあるので、参考になるものがあるかもしれません。がんばって投稿してみるのもアリかと思います。私はやったことありません(笑)

Add-ons Developer ML
https://thunderbird.topicbox.com/groups/addons

■制約いろいろ
MailExtensionsでは、アドオン一つにつき、一つしかアイコンが追加できません。
一応、複数追加できるようにするBugがあがっていますが、今のところ、対応する感じは見られません。

複数ボタンを追加するBug
https://bugzilla.mozilla.org/show_bug.cgi?id=1617758

レガシーアドオンでは、スレッドペインにカスタムカラムを追加できたのですが、MailExtensionsではできません。こちらも、対応するBugはあがっています。
(私のアドオンのPriority Switcherの対応を見送った理由の一つがこれです。)

カスタムカラムを追加するBug
https://bugzilla.mozilla.org/show_bug.cgi?id=1615801

これが一番衝撃的だったのですが、メッセージを新規タブで開くAPIがありません。
Webページは開くことができるのですが…
私のアドオンのNew Tab Buttonでは、Experimentsを使って実装しています。こちらもBugは登録されています。

タブでメッセージを開くBug
https://bugzilla.mozilla.org/show_bug.cgi?id=1603489


…と、一通りまとめてみたものの、レガシーアドオンをThunderbird 78で動くようにするには、WebExtension Experimentsがほぼ必須。ということは、新しいWebExtensions/MailExtensionsと、古いXUL/XPCOMの両方のフレームワークを押さえておく必要があり、相当レベルが高いです。

一体、どれくらいのアドオン作者が生き残ってくれるのか、どれくらいの人がフォークできるのか、なかなか厳しい状況に思います。

一方で、Thunderbird 78のベータ版を使ってみても、これといって、おお!というものはなく、移行もあまり進まないのかなと思います。Thunderbird 78がリリースされて、アドオンが壊滅状態で大騒ぎ、自動更新が始まってから、またさらに大騒ぎってことになりそうです。

他にも、わからない、知りたいことがあったら、コメントいただければ、私のわかる範囲で追記していこうと思います。

[2020/6/27]
英語ですが、公式サイトでThunderbird 78対応のまとめがされています。

Update for Thunderbird 78
https://developer.thunderbird.net/add-ons/updating/tb78

2 件のコメント:

匿名 さんのコメント...

とても有用な情報を日本語でまとめていただきありがとうございました。
かなり参考になりました。

匿名 さんのコメント...

「Thunderbird 68に未対応アドオンをインストールする方法」でもお世話になりましたが、今回も大変助かりました。
自分用ですが、旧アドオンを78対応させることができました。
有益な情報をまとめて頂いて、ありがとうございます。

人気の投稿(過去7日間)