Now browsing the archives for the 'WebExtensions' category.
Firefox用WebExtensionsをChromeに対応させる
自作のXULベースのレガシー拡張機能 FoxAge2ch の WebExtensions 版 FoxAge5ch を2018年4月にリリースしたが、その後のバージョンアップにより、ソースコードを共通化したまま Chrome にも対応済みとなっている。 Firefox 用 WebExtensions を Chrome でも動作可能とするにあたり、両者のAPI差異を吸収するライブラリである browser-polyfill.js によるところが非常に大きいが、それ以外にもいくつか気付いた点があったため、ノウハウとしてまとめた。なお、前提として、ブラウザのバージョンは Firefox 60、 Chrome 67 とする。
browser API と chrome API の違い
Firefox と Chrome の一番大きな差異は、WebExtensions APIの名前空間が異なる点である。 Firefox の browser API は async / await 構文による Promise ベースのコーディングが可能である一方、 Chrome の chrome API はコールバックベースとなっている。ソースコードを共通化したまま Firefox と Chrome 両対応させるにあたり、当初はブラウザを判別してif文で分岐しながら頑張ろうとしたが、開発途中でこの差異を見事に吸収してくれるありがたいライブラリ browser-polyfill.js の存在に気付いた。
browser-polyfill.js の github にはライブラリ自体のソースコードが置かれているが、 WebExtensions で使用するには npm でパッケージ化する必要がある。現時点の最新バージョンがパッケージ化されたものも入手可能である。 WebExtensions 内での使い方としては、バックグラウンドスクリプトの場合 manifest.json の “background”.”script” にてロードし、サイドバーやポップアップなどの各種UI用HTMLの場合 script タグでロードすればよい。たったそれだけで、 Firefox 向けに記述した browser APIのコードが Chrome でも動作するようになる。(ただし一部例外あり)
ブラウザの判別
前項の browser-polyfill.js を使用することで概ね Firefox と Chrome のソースコードは共通化することができた。しかし、一部共通化できない部分やCSSをブラウザごとに若干調整する必要があり、ブラウザを判別してif文で分岐させる必要があった。ブラウザを判別する方法として、 browser-polyfill.js をロードしている前提であれば、下記の方法が手っ取り早い。ただし、これが最善かどうかは不明。
if ("sidebarAction" in browser) { // Firefox向けの処理 ... } else { // Chrome向けの処理 ... }
background ページへのアクセス
Firefox では、サイドバーやポップアップなどの各種UI用HTML内で下記のようにして background ページへアクセスできた。
browser.runtime.getBackgroundPage(win => { window.MyBackgroundService = win.MyBackgroundService; });
ところが、 browser-polyfill.js では上記の処理がエラーとなってしまうため、前述した方法でブラウザを判別し、 Chrome の場合は下記のようにした。
let win = chrome.extension.getBackgroundPage(); window.MyBackgroundService = win.MyBackgroundService;
キー押下イベントのキー判別
keydown, keypress イベントに対するイベントハンドラ内でどのキーが押されたか判別する際、 Firefox では KeyboardEvent.keyCode プロパティの値(数値)を event.DOM_VK_* 定数で判別することが可能。
if (event.keyCode == event.DOM_VK_RETURN) { // Enterキーが押された時の処理 ... }
しかし、 Chrome では event.DOM_VK_* 定数が定義されていないためエラーとなる。keyCode プロパティの使用はやめて、key または code プロパティを使用すべき。なお、 key と code プロパティはNumlockされている場合に値が異なる。
if (event.key == "Enter") { // Enterキーが押された時の処理 ... }
ミドルクリックに対するイベントハンドラ
マウスの中ボタンによるクリック(ミドルクリック)に対して何らかの処理を行う場合、 Firefox では click イベントに対してイベントハンドラを追加して event.button == 1 により中ボタンが押されたことを判別できた。しかし、 Chrome ではそもそも中ボタンによるクリックは click イベントが発生しない。そこで、 auxclick イベントに対するイベントハンドラを追加することで両ブラウザで動作可能となる。
event.targetで取得できるDOM要素の差異
document.addEventListener("click", onClick)
のようにdocument全体にクリックイベントハンドラを追加しておき、イベントハンドラ側で event.target によりどのボタンが押されたかを判別する場合、ボタン(button要素)の中に img 要素を入れていたりすると、 event.target で取得できるDOM要素が Firefox と Chrome とで異なる。img 要素などでclickイベントを発生させないためには、下記のようなCSSを追加しておく。
img { pointer-events: none; }
CSSの:any疑似クラス
CSSの :any 疑似クラスは将来的に :matches に代わるようだが、現時点で Firefox はベンダープレフィックス付きの :any のみ対応している。したがって、 Firefox / Chrome 両対応するには下記のように記述する必要がある。
:-moz-any(#foo, #bar) { ... } :-webkit-any(#foo, #bar} { ... }
CSSのuser-select
各種UI用HTMLでマウスのドラッグなどで不必要な文字列選択を発生させなくするため、 user-select プロパティを設定すべきだが、現時点で Firefox ではベンダープレフィックスが必要となる。したがって、 Firefox / Chrome 両対応するには下記のように記述する必要がある。
html, body { user-select: none; -moz-user-select: none; }
XMLHTTPRequest の User-Agent 改変
Chrome では下記のように XMLHTTPRequest によるHTTP要求の User-Agent ヘッダーを改変しようとするとエラーとなる。この処理は Firefox 限定とする必要がある。
var request = new XMLHTTPRequest(); request.setRequestHeader ("User-Agent", "...");
Visual Tabs (Ver.0.1)
FoxAge5ch (Ver.5.0)
インストール
https://addons.mozilla.org/ja/firefox/addon/foxage5ch/
新機能
- タブの再利用(標準搭載)
- HTTPS接続オプション(*.5ch.netに限定)
制限事項
- ツールバーのカスタマイズからアイコンを配置可能ですが、サイドバーを開くだけで閉じることができません。
- 2ペーン表示したときに境界線をドラッグ&ドロップで調整することができません。(おそらく実装は困難)
- データの保存先はFirefoxプロファイルフォルダ内の「browser-extension-data\foxage2ch@xuldev.org」となり、これを変更することはできません。
- 1日1回のjsonファイル自動バックアップは行われません。
- 自動更新チェックなどいくつかの機能は不要と判断して削除しました。
- GUIの見た目はWindowsに適合させており、MacやLinuxでは違和感があるかもしれません。
今後の実装予定
- Firefox Syncによるデータの同期
その他
- FoxAge2ch(レガシー版)からのデータ移行は、「設定」の「復元」から.jsonファイルを選択して実行してください。このとき、旧データの「.2ch.net」はすべて「.5ch.net」へ置換されます。
- バグ報告は github (https://github.com/gomita/foxage5ch/issues) の方にして頂けるとありがたいです。
縦型2ペインのUI
WebExtensions にてサイドバーに縦型2ペインのUIを作成したい。
具体的には、上部にツールバーがあって、その下にリストボックスが2つ、という形式。
XULだとこんな感じ。
flex属性を指定しなければ上詰めで、flex属性を指定すれば同じ階層でflex属性値の比率にしたがって伸縮してレイアウトされる。
<toolbar> <toolbarbutton label="Button1" /> </toolbar> <listbox id="mainList" flex="1"> <listitem label="List1" /> ... </listbox> <listbox id="subList" flex="1"> <listitem label="List1" /> ... </listbox>
WebExtensions (HTML)であれば、まずFlexコンテナを作る。
Flexコンテナの高さをサイドバーぴったりにするため、height: 100vh;とするのがポイント。
Flexコンテナの直下に入れる要素はXULのflex属性と同じようにCSSのflexプロパティを設定する。
#container { height: 100vh; display: flex; flex-direction: column; } ul { margin: 0; flex: 1; overflow-y: auto; }
<div id="container"> <div id="toolbar"> <button>Button1</button> </div> <ul id="mainList"> <li>List1</li> ... </ul> <ul id="subList"> <li>List1</li> ... </ul> </div>
Thanks, and goodbye XUL!
先日 Tokyo WebExtensions Meetup #1 に参加したことをきっかけに、ここ1~2年終息状態だったアドオン開発を再開しようという気になった。「お前のアドオンをとっとと Firefox Quantum に移行しろ!」というメールも最近はあまり来なくなってしまったが、遅ればせながら自作XULアドオン(旧式の拡張機能)の今後について、方向性を整理しておこうと思う。
FireGestures
ユーザー数:199,320 ユーザー
個人的使用度:★★★★★
キーボードよりマウス派。とはいえ戻りたいときにいちいち戻るボタンをクリックしたり、タブを切り替えるためにタブバーから選択してクリックすることにはストレスを感じるので、マウスの右クリックをしながら小さな動きで様々なアクションができるマウスジェスチャーは便利だ。
XULとしてはタブブラウザ全体(xul:tabbrowser 要素)に対する mousedown, mousemove, mouseup などのDOMイベントを検知してマウスジェスチャーを実現可能だが、これを WebExtensions 流にやるなら content scripts で各ブラウザ内のWebページに対して同じことをすれば良さそう。すでにいくつかの新しい拡張機能が順調に開発を進めているようであり、十分な代替があるため FireGestures は開発打ち切り。
なお、自分が試したのは Gesturefy のみであるが、完成度が高く、FireGesuturesを少しだけ意識してくれつつもモダンなUIへと昇華されており、もはや自分自身手放せない状態である。
ScrapBook
ユーザー数:78,593 ユーザー
個人的使用度:★
Firefox黎明期から存在し、知名度的には高い。しかし、現在は自分自身がほぼ使用していないため、開発は打ち切り。かといって今まで保存したWebページが見られなくなってしまうのは困るかもしれないので、ツリー構造をHTML出力する機能を使ってからFirefox Quantumへアップデートしてください。なお、代替としては ScrapbookQ や Web ScrapBook といったものがあるもよう。
Tab Scope
ユーザー数:55,836 ユーザー
個人的使用度:★★
昔Operaにあった機能を参考とし、タブにマウスポインタを当てることでプレビューしてくれる。怪しい画像を開くときに役立つ機能。技術的には CSS transition を使いまくってヌルヌル動くのが気持ちよく、結構好きなアドオンだが、無くても別に困らない。ブラウザUI改造系は WebExtensions としては実現可能性が低いため、開発打ち切り。
Vertical Toolbar
ユーザー数:4,577 ユーザー
個人的使用度:★★★
これもOperaにあった機能で、ブラウザのツールバーをサイドバーの左側に縦型表示してくれる。横長ディスプレイ主流の時代では理にかなっていると思う。むしろ標準機能として取り入れてほしい。 WebExtensions としては今のところ実現不可だが、新しいツールバーを追加する、ツールバーを縦に表示する、といったAPIが追加されれば是非とも開発したい。
Flat Bookmarks
ユーザー数:1,767 ユーザー
個人的使用度:★★
ブックマークツリーで階層が深くなるとインデントが増す問題への対処として、スタック型UIにしてくれる。食べログで行きたい店を見つけて最寄り駅別にフォルダに分けてブックマークしたり、ブックマークを一番活用していた時代には役立った機能。しかし、最近はブックマークが面倒な生活になってしまった。たまにPocketするくらい。技術的には XUL overlay や eval 駆使による魔改造系アドオンであり、開発打ち切り。
FoxAge2ch
ユーザー数:1,516 ユーザー
個人的使用度:★★★★
2ちゃんねる(現5ちゃんねる)およびいくつかの互換掲示板の更新チェッカー。自分自身も常用しており、現在はこれだけのために Firefox ESR を別プロファイルで起動する不便さを強いられている。
サイドバーの独自UI、HTTPリクエストやJSONデータ管理などを中心としたバックグラウンドのサービスだけで完結しているので、WebExtensions への移行は比較的容易い。現在移行作業中で、必要最小限の機能は利用できるレベルまで達している。
というわけで、奇しくも一番ユーザー数が少ない FoxAge2ch だけが今のところ開発継続という結果となってしまった。
最後に
XULに出会ったのはおよそ14年前、研究室の先輩からの提案であり、それ以来長らく関わってきた中で得たプログラミング知識、仲間達との出会い、イベントや旅行、書籍執筆など、さまざまな思い出が詰まっている。XULの名前空間 http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul をそらで言えるようになったり、 Components.classes[“@mozilla.org/ …と呪文のごとくXPCOMを呼び出すことに妙な興奮を覚えたり、深い思い入れがある。
しかし、Mozilla(Firefox)としては FUEL、Jetpack、Rebootlessアドオンなど長い長い試行錯誤を経てようやく辿り着いた真打 WebExtensions であり、実際に触れてみるとその敷居の低さ、デバッグ環境の充実ぶり、モダンなプログラミングスタイルなど、ブラウザアドオン界の新たな幕開けを確信させるものであった。
というわけで、Thanks, and goodbye XUL!