weblioPane fixed

Firefox の拡張に weblioPane というのがあって便利に使っていたのだが、最近になって(おそらく Firefox 40 のリリース以降)使用できなくなって困っていた。しかしなかなか新しいバージョンに更新される気配もないので勝手に直してみた。

https://github.com/akahuku/webliopane-fx40fixed

この拡張が参照している weblio の API についてのドキュメントが欲しいのだけど、見つからなかった。

WebExtensions…?

何やら物議をかもしている例の件。自作の拡張にはどういう影響があるのか考えてみる。

Firefox 版の wasavi や赤福プラスは Addon SDK ベースで作っているのだが、SDK の提供するモジュールをそのまま使っているのではない。抽象的なラッパーを挟んでいる。ラッパーが Chrome と Presto Opera と Firefox の差異を吸収して、アプリケーション内にはブラウザ固有のコードはほとんどない。

したがって、仮に WebExension ベースに移行するとしても、変更する必要があるのは Firefox 版のラッパーだけだ。そもそも WebExtensions が Chrome の拡張ベースだし、ラッパーも Chrome の拡張をベースにしたインターフェースにしてあるので、変更によりむしろコード量は少なくなるかもしれない。

一方で、SDK ベースのままにするという選択肢もある。ただ、SDK 自体は廃止は免れるということなのだけれど、それは [cci]require(‘chrome’)[/cci] していないものに限られるという。

ラッパーはもちろんこれを使っている。

  • XMLHttpRequest – SDK が提供するそれは upload プロパティをサポートしていない
  • FormData – SDK はこれを提供していない
  • Blob – SDK はこれを提供していない

つまるところ、なぜ [cci]require(‘chrome’)[/cci] を使っているのかといえば、SDK が提供する API が全般的に中途半端だからなのだ。それなのに Cu/Ci の使用を今さら咎められても困るのだが、この辺を何とかしないといけない。

width of character

wasavi のステータス行にはカーソル位置の桁・行位置を表示しているのだけど、その桁位置とはなんぞやというと、これはカーソル位置の内部的な行頭からのオフセットをそのまま指しているわけではない。つまり内部的な桁位置と表示上の桁位置は違う。

まず内部で charWidth という変数があり、これは大元の textarea のフォント関連のスタイリングに基づく、[cci]0[/cci] の文字幅だ。技術的には span 要素に [cci]0[/cci] を入れた際の offsetWidth の値だ。

それを踏まえて表示上の桁位置を算出するには、span 要素に行頭からカーソルの物理位置までの文字列を入れ、その offsetWidth を出し、charWidth で割る。表示しているフォントが固定幅であればこれで特に問題ない。

ところが困ったことに、固定幅フォントでさえ、文字列全体の offsetWidth が charWidth の整数倍にならないことが多々あるのであった。つまりこれは、cssom では offsetWidth の型は long だ。しかし実際には、それは小数で保持されているのが原因なんだと思う。そういうわけで正しい表示上の桁位置が得られない。

うーんどうしよう。

 * * *

charWidth を算出する際に、100 個並べた [cci]0[/cci] の offsetWidth を 100 で割るようにした。つまり charWidth の精度を上げた。

wasavi/0.6.559 released

リリースした。

Chrome: https://chrome.google.com/webstore/detail/wasavi/dgogifpkoilgiofhhhodbodcfgomelhe

Opera: https://addons.opera.com/ja/extensions/details/wasavi/

Firefox 版は AMO へのアップを諦めた。その代わり github 上の開発版は署名済みになっているので Firefox41+ でもインストール時に警告されることはない: https://github.com/akahuku/wasavi/raw/master/dist/wasavi.xpi

 * * *

wasavi が各ブラウザ上でアップグレードされた時、http://appsweets.net/wasavi/ を開くようになっている。ここで実質的なユーザー数をカウントすることができるので、そうなっている。先頭のテキスト “wasavi は Chrome、Opera、Firefox 用のエクステンションです。” の文句のそれぞれのブラウザ名にカーソルを合わせるとユーザー数を表示する。Opera に関しては Presto Opera と Blink Opera を分けてカウントする。

現在のところ、

  • Chrome: 1615
  • Presto Opera: 0
  • Blink Opera: 57
  • Firefox: 29

とのこと。Chrome では Web Store での表示が 3500 人とかそんな感じなので、まあ数日でその辺りに達するのだと思う。それにしても偏りがすごい。Opera に関してはブラウザ自体のシェア比からこんなもんなのかなという気はするが、Firefox 版ユーザーが妙に少ない。

Presto Opera でのユーザーが 0 というのはとてもいいことだ。これはもはや Presto Opera を考慮して開発する必要が全くないということだ。

Everything becomes Blink

Microsoft Edge が Chrome と Firefox の両方の拡張をサポートするかもしれない? という噂について、そんなことができるのかなと訝しんだ記事を以前書いた。

実際のところは、こういうことのようだ。
http://rockridge.hatenablog.com/entry/2015/08/16/234729
https://wiki.mozilla.org/WebExtensions

なるほど。つまり Firefox 側で Blink の拡張のインターフェース互換のフレームワークを構築すると…。しかしそうすると Addon SDK の存在意義が根底から揺らいでしまう気が。それから、Mozilla 自身が XUL を捨てたがっているというもある。しかし、Firefox 本体や既存の拡張のシステムって相当 XUL と絡み合っているわけで、そちらの存在意義も揺らいでくるような。

もしかしたら、レンダリングエンジンを servo にスイッチするタイミングでそれらも一気にグレートリセットされるのかもしれない。いやー Firefox 向けに拡張を書く人は大変だなー(他人事)。

signing akahukuplus

赤福プラスを Unlisted な拡張として AMO に提出し、署名を付けてもらった。

この際、機械的な validator が走り、ソースが検証される。この検証に引っかかった場合即時署名はされないが、AMO の中の人によるレビューを申請することはできる。一方、検証にすべて通れば即時署名が施される。いずれにしても署名された xpi は AMO の自分のアカウント内に保存されるのでそれをダウンロードして別の場所で公開すればいい。

赤福プラスがこの検証にすべて通ったわけだが、前に書いた通り検証を行う validator は本当にひどい出来なのだった。ひどい出来だし、意味のない設計方針に基づいて作られている。

たとえば validator は eval や、Function や、innerHTML や、insertAdjacentHTML や、引数がリテラルではない createElement があると即時署名を拒否する。そんなわけで

const FUN = '';
var fun = some_decrypt_function(FUN);
var f = window[fun]('alert("wow!");');

のような感じでとにかくソースからイケないメソッドやプロパティ名を隠す。すると、validator はころっと騙される。

ああ、嫌なコードだなあ。嫌だし、自動検証に対してしか提出しない場合にのみ許される手法だ。これを preliminary review とかに提出したら必ず「この処理って何やってんの?」と聞かれるし、そして拒否されるだろう。

そもそもこの手のチェックに意味があるんだろうか。eval や innerHTML 自身が悪というわけではないのだ。使い方の問題なのだ。AMO の手で署名を付けてその拡張の生殺与奪権を握っているわけなのだから、イケない拡張がイケない使い方をしているなあと判明した時点でロックダウンすればいいんじゃなかろうか。

Opera から移行して以来、努めて愛そうとしているけれど、残念ながら Mozilla にもその製品にも、本当にがっかりさせられることが多い。

Firefox 42 #2

42.0a2, e10s off

  • 新しいタブを開いてアドレスバーに適当なアドレスなり検索語句を打ち込んでエンターを押してもうんともすんとも言わない時がある
  • リンクをクリックしてもうんともすんとも言わない時がある

ここまではまあ Developer Edition だからそのうち直るのだと思う。

一方で keysnail の行く末が気になるのだけど:

eval を使ってるとだいたいレビュー結果は芳しくないものになるのはどこも同じようです。それから、innerHTML や insertAdjacentHTML を使ってもいい顔をされない。でも、プラグインのような機構を備えた拡張を作ろうとしたら、eval を使わざるを得ないわけで一律に reject されても困るよねえ。その場合、「これこれこういうわけで eval を使わざるを得ないので許してくだち!」というメッセージと共に人の手によるレビューを申請することになるんだと思うけど、その辺のフローがよく分からないというかさっぱり分からない。どうも AMO のやりたいことがよく分からない。AMO の言葉は誰にも分かんない。AMO の静かな願いも分かんない。

というか、bugzilla で validator 関連を見てみると現在進行形で署名フローの議論してたりするので、何がどうなるのが正しいのかは AMO の中の人にもまだ分からないのかもしれない。

……なんか、仕事が雑だなあ。

Firefox 42

Firefox Developer Edition が 42.0a2 に更新された。

  • 開発のため未署名のまま入れている拡張群がすべてブロックされてしまった。それらを動かすためにわざわざ Developer Edition を入れたんですけど……。しかしこれは単に about:config で [cci]xpinstall.signatures.required[/cci] を false にするだけだった。それにしてもどうしてデフォルト値を true にするんだ。どういう嫌がらせだ。
  • Electrolysis、あるいは e10s という Firefox をマルチプロセスにする計画があり、42.0a2 ではそれがデフォルトでオンになった。
    おそらく、wasavi などの Addon SDK ベースで作っている拡張は、e10s 環境下でも特に影響はないんだと思う。しかし困ったことに keysnail が動かなくなる。正確に言うと keysnail 自体は動くのだけど、.keysnail.js に書いたスクリプトでコンテント領域の DOM に触っている部分が軒並み動かなくなる。e10s は Firefox 自身のプロセスとコンテント領域のプロセスを分離するのがミソだということなので当然だ。
    幸いにして、今のところは e10s を有効にするかは単に about:preferences で指定できる。でも、将来的にはこれどうなるんだろう。常に有効とかになったら keysnail 死んじゃう。

Synchronizing the settings #3

とは言ってみたものの、本当に大丈夫なんだろうか。

とりあえず wasavi のバックエンドが localStorage に保存するデータのキーを列挙してみよう。

  • version: 現在インストールされている wasavi のバージョン文字列
  • targets, exrc, shortcut, shortcutCode, fontFamily, fstab, quickActivation, qaBlacklist, logMode, sounds, soundVolume: オプションページから編集することのできる項目群
  • memo-*: body 要素に対して wasavi を起動した場合その内容は localStorage に対して読み書きされる。これを Memorandum と呼んでいて、localStorage 上の memo-* キーは各 URL ごとの Memorandum の内容を保持している。* の部分は URL の SHA-1 値
  • filesystem.*.tokens: 各クラウドストレージに接続した際のクレデンシャル
  • wasavi_lineinput_histories: 行入力モードで入力された値の履歴
  • wasavi_registers: レジスタの内容

こうしてみるとキャメルケースだったり [cci]-[/cci] で繋いでいたり [cci].[/cci] で繋いでいたり [cci]_[/cci] で繋いでいたりとてもアレだがまあそれはそれとして。ユーザーをスイッチした時、リセットされるべきものと触るべきでないものを明確にしたい。大体の区別は前者は Chrome にログインするアカウントに属する情報、後者はローカルマシンに属する情報ということだ。

まず version は明らかにローカルマシンに属する。これはいい。したがって同期されるべきではなく、かつユーザーがスイッチされたとしても変更されるべきでない。

次にオプションページの項目は当然ながら同期される対象であり、ユーザーがスイッチされた場合は新しいユーザが所持するデータのものに差し替えられるべきである。

ここまでは簡単だ。これ以降が難しい。

Memorandum はまだその仕様自体が固まっていない。とりあえず version と同様の扱いにしておこう。

クレデンシャル。クレデンシャルの情報はクリティカルであり同期で使いまわすのは怖い。一方でユーザースイッチの場合はどうなんだろう。クラウドストレージに対して受けた認証は Chrome のアカウントでもローカルマシンでもなく各ストレージのアカウントだ。ということは Chrome のアカウントがスイッチされたとしても触らないほうが良いのだろうか。なんとも判断できない。

行入力履歴とレジスタはまた異なる疑問点がある。使い勝手で考えると、これらが Chrome のデバイス間で共有されるのはまあまあ便利だと思う。しかしこれらの情報ってかなり頻繁に更新されるのだ。デバイス A で wasavi を起動し履歴とレジスタの内容を更新する。それを同期に載せる。デバイス B でも wasavi を起動する。同期イベントがやってくる。ローカルで更新した内容が上書きされる。そんな感じで不整合が簡単に起こりうる気がする。ということは実装の都合上同期しないほうがいいのかもしれない。ユーザースイッチの場合はどうか。これもなんとも判断できない。

…ということなのだが、いまいち確固たる理由付けによる区分けができない。

Synchronizing the settings #3

よくリファレンスを読んでみたところ Identify API に getProfileUserInfo() と onSignInChanged イベントがあり、もちろん前者は Chrome にログインしているユーザーの情報を得るために使い、後者はユーザーがスイッチされる時に発生するようだ。

よかったよかった。これを使えば大丈夫。