あまり需要ない気もしますが,昔の firefox plugin を web extensions で書き直す際にハマった所など.
試した環境:
- Firefox 57.0.4
- Chrome 63.0.3239.132
- Android (バージョンを忘れた...)
- web-ext 2.2.2
開発環境のインストール
nodejs の web-ext command をインストールします.
- npm install -g web-ext
おわり.
サンプル
以下からクローンしておきます.
Desktop で動かしてみる
シェルなどを開いて適当なプラグインのディレクトリ,例えば chill-out へ移動して
web-ext run --bc -v
するとこうなる.
Firefox for Android で動かしてみる
先に開発者用の api_key を発行します. 開発者登録が必要ですが10分かからないと思います.
以下の手順に従って作業していきます.
-
web-ext sign
で xpi を生成します. - Android へ Firefox をインストールしておきます.
- Android をデバッグモードでつなぐなどして xpi を push します.
- Firefox を開いて
file:///mnt/sdcard/
を開きます. xpi をクリックするとインストールされます.
インストールしたプラグインをデバッグには以下を使います(詳細略).
UI を実装する
プラグイン開発で避けて通れないのが,プラグインを起動したり設定したりするためのボタンの追加です.
追加できるボタンには page_action
や browser_action
, sidebar_action
などが存在します.
page_action
うち Android が対応しているのは page_action
だけです.
どんな感じで動くのかは以下のサンプルを試してみるとわかります.
使い方は以下のページを見つつ,サンプル中の manifest.json と background.js を見るとよいです.
browser_action
sidebar_action
CSS
Bootstrap についてはスクリプトに依存しない部分はすんなり使えます(bootstrap.min.css
font.min.css
とか).
スクリプトに依存する部分 bootstrap.min.js
とか jquery.min.js
を使うのは正直なところ,かなりめんどくさいです.
コンソールを覗くと大量に警告やエラーが出ます.
どうもプラグインに同梱するスクリプトにいろいろと制限があることが原因のようです.
webpack
あまりお勧めはしませんが使えなくはないです.
1度目の公開前に review が入るのですが,minimize して配布する場合には pack 前のソースと pack 方法について提供を求められます.
ブラウザごとのサポート状況
Chrome
ほぼすべての API が Promise に対応していないので callback を渡す必要がある.
(拡張機能に関してはやる気がないのかもしれない).
存在しない API に対するハンドリング
非常に雑な実装ですと例えばこのようになります.
/*
* Firefox の場合は基本的に prefix が `browser.` の API を使うのですが chrome にはそれがありません.
* また Firefox は `browser.` と `chrome.` でたまに挙動が異なる API があります.
*/
function getBrowser() {
try {
return browser;
} catch (err) {
return chrome;
}
}
// tabs.query API のラップ関数
function tabsQuery(query) {
return new Promise(function (resolv, reject) {
try {
// callback なしで呼んでみる
let querying = getBrowser().tabs.query(query);
if (!querying) {
// Promise object が返ってこないなら callback を使う
getBrowser().tabs.query(query, resolv);
return;
}
querying.then(resolv).catch(reject);
} catch (err) {
// schema error が起きたらおとなしく callback を使う
try {
getBrowser().tabs.query(query, resolv);
} catch (err) {
reject('browser.tabs.query unsupported!');
}
}
});
}
// 使ってみる
let gettingAllTabs = tabsQuery({});
gettingAllTabs.then((tabs) => {
console.log('# of tabs ' + tabs.length);
for (let tab of tabs) {
// tab に対する操作
}
}).catch(console.warn);
メモ:
例外を起こして catch するやり方はパフォーマンスが著しく落ちる.
以下にある shim/polyfill が使えるかも
公開
開発者登録を行った後,以下のページからガイドに従ってぽちぽちクリックしてけば終わります.
プラグインをアップロードする前に,ローカル環境で web-ext lint
しておくと間違った API の使い方について指摘してもらえます.
Chrome
こちらは開発者登録にお金がかかります.
登録は以下から行います.
以前の SDK で使えた API について
以前は Components.classes
という API から様々なブラウザオブジェクトが呼べたのですが,Web Extensions では呼べなくなっています. 例えば Components.classes
を通した preferences などへの直接アクセスはできなくなりました.
以下においてある ESR については Components.classes
API などを使った昔のプラグインがそのまま使えますが,
そのうちサポート期限が切れる予定です.