2017/01/18 6:12 pm
Testing with selenium javascript binding #4
Uncategorized, , , ,

そういうわけで Linux 上では WebExtensions 版の wasavi の、Selenium による、Firefox 上の機能テストを一通り通せるようになったのだが、結局これを Windows 上ではできていない。過去の記事で何度か書いているが Windows では既存のプロファイルでもって Firefox を起動させることができず、かつ新規プロファイルに WebExtensions ベースの拡張を登録させつつ Firefox を起動させることもできない。両方できないと身動きが取れない。

実を言うと Linux 上でもテストが問題なく滞りなくできてるわけではない。例えば:

  • なにかが leak してますよ〜的なログがいっぱい出る。
    (node) warning: possible EventEmitter memory leak detected. 11 listeners added.

    云々。このエラー自体は書いてあるとおりのそのままの意味なんだろうけど、Chrome でテストする際は出ないので Selenium 内の Firefox とのやり取りをするコードにおける問題だと思う

  • wasavi でテストする際は当然ながら様々なキーストロークを発生させる必要がある。で、selenium.Key.chord() というものがあり、chord(Key.CONTROL, 'c') などと呼ぶと ctrl+C を押されたとブラウザに振る舞わせるような擬似的なキーストロークを生成する。Key[なんとか] は、型自体は普通の string で、Unicode の Private Use Area 内の文字である。chord 自体は単に引数を全部 join(”) したものに Key.NULL をくっつけたものを返す。したがって擬似的なキーストロークもまた単純な文字列である。さてそういうルールのもとに構成された chord を送出したあと、geckodriver かあるいは Firefox 本体が例えば前述の例だとそれを ctrl+C としてデコードしてくれないと困るわけなのだが。困ったことに、誰もデコードしてくれない。そのまんま PUA が入力され、テストは失敗する。ひどい
  • テスト中 Web Content なるプロセスが生成されて、これが60〜80%の CPU パワーを消費する。同時に Firefox 自体のプロセスが残りの CPU パワーを消費する。そんなわけでテスト中は待ってる以外にほとんど何もできないし、そもそも端末以外のアプリケーションを全て落とした状態じゃないとテスト自体がうまく始まらない。Chrome を起動しながらとか成功した試しがないのである。そして CPU パワーはめちゃくちゃ食いまくる割にテストの進行は Chrome でのそれより 2 割増しくらいで遅い

前述のプロファイル関連の不具合と合わせて、どーにもこーにも…… Firefox が絡む Selenium のテスト環境はいつも質が悪い、質が低いと言わざるを得ない。どうなってんのかなあこれ……。この辺が快適になってくれないと、Firefox 向けの拡張を作るという事自体にくじけてしまいそうなのだけど。

2017/01/14 10:06 pm
Testing with selenium javascript binding #3
Uncategorized, , , , , ,

テストを開始しても、Chrome は起動するもののテストページへのナビゲーションが発生せず、そのままタイムアウトで失敗してしまうことがたまにある。これの原因がよくわからない。とりあえずエラーメッセージとしては “unable to discover open pages” というものが返される。

原因はよくわからない。テスト用とは別の常用の Chrome を起動している状態でテストを開始すると、そういう状況が発生することがあるが、しないこともある。常用の Chrome を落とした状態でも発生することがある。また youtube とかの動画を再生中だと発生する確率が上がるような気がしないでもない。要するに chromedriver が Chrome を起動するものの、複数ある Chrome のうち自分が起動させたものを見失うことがある、というような感じなのだが……そんなわけあるかいな。

上記のエラーメッセージでググっても特にこれだというものもない。謎。

ちなみに Linux 版の Chrome で UI のロケールを任意のものにするには、LANGUAGE=en google-chrome などとする。LANG でも LC_ALL でもなく、LANGUAGE。また、--lang スイッチは効かない。

 * * *

というわけで、とりあえずすべての機能テストを java から javascript へ移植した。疲れた。次にこれを Windows 上の Firefox にて通してテストする。とその前に、Linux 上でも動かしてみよう。

ナウい Firefox で Selenium のテストをするには、geckodriver が必要なので、これをパスの通ったところに置いておく。

var options = new firefox.Options();
options.setProfile(profilePath);
result = new webdriver.Builder()
      .withCapabilities(webdriver.Capabilities.firefox())
      .setFirefoxOptions(options)
      .build()

こんな感じで起動。これは既存のプロファイルを利用するような動作を意図しているが、どうも既存のプロファイルを /tmp あたりにまるごとコピーしてから起動するような感じがする。そのため実際に Firefox のウィンドウが表示されるまでは結構待たされる。

それから、webdriver.actions().sendKeys().perform() が未実装なのだそうでエラーになる。その代わり WebElement#sendKeys() を使う。geckodriver 自体が新しいプロジェクトなので、すべての想定された機能が実装されるまでにはもうちょっとかかる雰囲気。

 * * *

結局のところ wasavi でテストするには

  1. npm install -g selenium-webdriver
  2. npm install -g chromedriver geckodriver operadriver
  3. npm install -g mocha
  4. npm install

と入れて、make run-chrome としてとりあえずテスト用プロファイルでもって起動し、開発者モードで wasavi を組み込み、ついでに dropbox などに wasavi からアクセスして認証を得ておき、ブラウザを閉じてから make test-chrome とする……という感じ。ただし Firefox に関しては、過去の記事の通りオンザフライで WebExtensions ベースの拡張を登録するのが現在のところできないので、wasavi をビルドした上で xpi を登録したプロファイルを用意する必要がある。

2016/12/25 10:20 am
Add-on SDK to WebExtensions #5
Uncategorized, , , ,

ところが結局、Windows 上の Firefox で Selenium によるテストを行うところまで至っていない。現状では

  • Windows 上で
  • 任意の拡張を一時的に読み込ませつつ
  • そのプロファイルを使うよう Selenium に指示する

という術がないように思える。となるとテストのために一旦 xpi をビルドして、署名して、それを使うしかない。

ちなみに Selenium は現在 version 3 になっていて、Firefox に関しては Chrome の chromedriver.exe と同様 geckodriver.exe を介在させるようになっている。そのためにシステムプロパティ webdriver.gecko.driver に geckodriver.exe へのフルパスを書いておく必要がある。

ということで試してみたところ

File p = new File("C:\\path\\to\\profile");
WebDriver driver = new FirefoxDriver(p);

の呼び出し中に

Java heap space
java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOf(Arrays.java:3332)
        at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
        at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
        at java.lang.StringBuilder.append(StringBuilder.java:136)
        at org.openqa.selenium.remote.ProtocolHandshake.amendOssParamters(ProtocolHandshake.java:183)
        at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:61)
        at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:141)
        at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:82)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:601)
        at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:241)
        at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:128)
        at org.openqa.selenium.firefox.FirefoxDriver.<init>(FirefoxDriver.java:259)
        at org.openqa.selenium.firefox.FirefoxDriver.<init>(FirefoxDriver.java:247)
        at org.openqa.selenium.firefox.FirefoxDriver.<init>(FirefoxDriver.java:242)
        at org.openqa.selenium.firefox.FirefoxDriver.<init>(FirefoxDriver.java:238)
        at org.openqa.selenium.firefox.FirefoxDriver.<init>(FirefoxDriver.java:131)
        at WasaviTest.WasaviTest.createDriver(Unknown Source)
        at WasaviTest.WasaviTest.beforeClass(Unknown Source)

……どうしろというのか。

 * * *

FirefoxDriver のコンストラクタに独自のプロファイルを与えるのではなくデフォルトのそれを使用するようにすると(要するに何も引数を与えないと)起動した。なにそれ。テストのためのツールである Selenium ががろくにテストされてない…。真面目にやってくださいよ本当に。

 * * *

FirefoxProfile p = new FirefoxProfile();
p.addExtension("/path/to/wasavi.xpi");
driver = new FirefoxDriver(p);

とやるととりあえず OutOfMemoryError で落ちることはないのだが、拡張を登録する処理で「アーカイブの中に install.rdf がないよ〜」的なエラーになる。この場合の wasavi.xpi は WebExtensions ベースの拡張なので install.rdf ではなく manifest.json を見に行ってくれないといけないのだが、Selenium 側がまだ WebExtensions ベースの拡張を知らない状態なのだろう。

うーん! だめじゃん。WebExtensions の拡張を Selenium でテストするのは時期尚早なのか。

2016/12/17 3:14 pm
Add-on SDK to WebExtensions #3
Uncategorized, , , ,

content script において window.Uint8Array を使おうとするとエラーになる。グローバルオブジェクトのそれを使わないといけない。両者は権限のドメインが違う、らしい。グローバルオブジェクトに Uint8Array が存在する場合はそれを、次に window に存在する場合はそれを使うようにした。

window. を前置するのをやめればいいじゃん、と思うかもしれないが、そうはいかない。赤福プラスでは window のプロパティを参照する際は必ず window を前置している。これは Presto Opera で動かすための措置で、Presto Opera の injected script では window がグローバルオブジェクトではないのである。したがって前置は必須なのだった。

それにしても、今 Presto Opera 使ってる人ってどんくらいいるのかなあ…? とはいえ赤福プラスはまだ Presto Opera もサポートしているので、動作確認のために新しい環境にも 12.16 を落としてインストール。

ところでメモやブックマークを同期しようとログインしようとしたらどうやっても弾かれるんですけど…。

Firefox の方は SDK 版から WebExtensions 版への自動更新が滞りなく行われることを確認。

さてこの SDK -> WebExtensions の作業において赤福プラスは前座でしかない。本丸は wasavi なのである。

2016/12/15 5:47 pm
Add-on SDK to WebExtensions #2
Uncategorized, , ,

一通り動くようになった。

すでに上げた Port の引数の問題の他、content script で生成した XMLHttpRequest の動きが変。

  • Referer が吐かれない
  • Cookie が送出されない
  • open() の際、相対 URL を与えるとエラーになる

同様の問題を抱えている人がいた。そのやり取りによると、

   try {
      return XPCNativeWrapper(new window.wrappedJSObject.XMLHttpRequest());
   }
   catch(evt){
      return new XMLHttpRequest();
   }

こんな感じで Firefox に限り意味の分からない書き方をすることで解決できるそうな。確かにこれでうまく行くけど…早く直してほしい。

ところでもうひとつ、ID の問題がある。Chrome のエクステンションは基本的にそれを識別する ID というものを開発者が意識する必要はない。エクステンションをローカルで crx にパッケージングした際に生成される .pem ファイルは取り扱いに気をつける必要はあるが、今日ではローカルパッケージングは zip で事足りるので .pem ファイルを生成する必要自体が基本的にない。

WebExtensions の場合は一応その流儀に倣っているが、しかしやはり Firefox の拡張らしく、ID は裏で健在だったりする。というのも署名を mozilla のサーバにつけてもらうと .web-extension-id という ID が書かれたドットファイルをもれなくプレゼントされるのである。うーんなんかイケてなくないですか。

一方で陽に ID を取り扱うこともできる。manifest.json の applications に

  "applications": {
    "gecko": {
      "id": "[email protected]",
      "strict_min_version": "42.0",
      "update_url": "https://github.com/akahuku/akahukuplus/raw/master/dist/firefox.json"
    }
  },

とこんな感じに書けばいい。ただよく分かんないことに、こう明示したとしてもやはり .web-extensions-id ファイルはプレゼントされる。いらないんですけど!

ところで上記の ID、いかにも Add on SDK 製の拡張っぽい書式だが、実際に SDK 版の赤福プラスの ID だ。というのも、おそらく流用しないと SDK 版から WebExtensions 版へのスムーズな自動更新が行えないからだ。うーんなんだかかっこ悪いなあ…。

2016/12/11 6:06 pm
Add-on SDK to WebExtensions
Uncategorized, ,

Firefox の拡張は本格的に WebExtensions ベースへの移行が始まっていて、一応のロードマップでは来年の 11 月には Firefox 57 において WebExtensions ベースではない旧来の拡張の読み込みをしないようになるという

拙作について考えてみると、あべアニの拡張の Firefox 版は WebExtensions で新規に書いたのだけど、既存の Addon SDK ベースの拡張は移行作業というものをしないといけない。具体的には赤福プラスと wasavi だ。あとは Webliopane だけど…これはどうかな。そもそも人様のものだし。

で、赤福プラスと wasavi に関しては SDK ベースではあるが、もともと Kosian という Chrome の拡張に近づけて書くためのラッパをかましているので、それぞれの拡張自身のコードに関しては大掛かりに書き換える必要はない。Firefox においてはただ単に動作の基盤を WebExtensions に差し替えればいい、はず、だ。たぶん。

というわけで、とりあえず赤福プラスをちまちまといじり始めたのだが。実際アプリケーションとしてのコードの修正よりむしろ WebExtensions の微妙な発展途上さに振り回されている。

  • まず content script と background の間を long-lived port で接続している。この際、background では port の onMessage イベントハンドラを
    function handlePortMessage (message, port) {
      ;
      ;
    }

    という風に定義している。最初の引数が飛んできたメッセージ、次の引数が使用された runtime.Port オブジェクトだ。このイベントハンドラの引数リストは Chrome の API ドキュメントに記述してある。

    で、それを Firefox の WebExtensions で動かすと、第 2 引数である port が渡されてこないのであった。これはきっとバグだろう

箇条書きにした割に 1 つしか書いてないが、きっと開発を進めるごとにいろいろ出てくる。

ところで web-ext ツールというものがあり、これは従来の cfx とか jpm に相当する。これで web-ext run とすると一時的なプロファイルによって Firefox が起動する。開発中の拡張は自動的に読み込まれている。そして面白いことに、その状態でソースファイルを更新すると拡張が自動的にリロードされる。これはちょっと便利。

2016/04/14 7:45 pm
Mysterious bound keyword
Uncategorized, , , , ,

Firefox 46a だったか 47a だったか忘れたが、wasavi と赤福プラスが両方動かなくなったことがあって調べてみた所、

  1. 両方が使っている extension_wrapper.js 内で、それが Firefox + Add on SDK で動いているかどうかを判断している箇所があり
  2. Firefox のその該当バージョンで判断のもとになっている箇所が変更されたため

動かなくなっているということだった。

extension_wrapper.js は Chrome でも Opera でも Firefox でも共通して動くので、それぞれのブラウザのうちどれで動いているのかを判断しないといけない。Chrome なら window.chrome が存在しており、Opera なら window.opera が存在しているのでそれが判断の助けになる。。

一方 Add on SDK の PageMod における content script かどうか、というのを判断するためのあんしんあんぜんな方法はないように思える。とりあえずのところ、self.on が存在し、それが function であり、かつその toString() の値が “function on (.*?) { [native code] }” とかそんな感じになっていればまあたぶんきっと SDK ベースの content script だろう…というような判断をしている。”[native code]” がミソなのだが、これが最適解というわけでは全然ない。

これが、今回動かなくなってしまったのである。それは、self.on の toString() の値が “function bound on (” というように、謎のキーワード bound が入るようになっていたからだ。bound……って何?

2016/03/04 7:49 pm
vi flavored browser UX #3
Uncategorized, , ,

実は今現在最新の Firefox Developer Edition 46.0a では Keysnail が動作しないので、とても不便である。

せっかく Chrome 上での vi flavored なエクステンション群の評価をしたので、cVim をベースに uBlock、ScriptBlock 等を入れて色々整えてみた所割合快適な感じになってしまって、あれ? これ Firefox もう窓から投げ捨ててしまってもいいんじゃないの? という気になりつつある。

従来、どういうわけか Linux 上で Chromium(Opera も)を動かすとオムニバー上のキー入力が耐えられないほど重かった。また Chrome ではオムニバー周辺をエクステンションからいじることはほとんどできない。アドレスを編集するときに ^F ^B ^H 位は使いたいのだ。そのあたりが Firefox を常用ブラウザに選んだ理由だったのだが、オムニバーの代わりに cVim のコマンドラインを代用すれば今まで感じていた不満が何とかなってしまうわけで、そんなわけで 3 日に 1 回くらい落ちる Firefox Developer Edition を常用する理由がなくなってしまった。

2016/03/03 3:09 am
vi flavored browser UX
Uncategorized, , ,

テストのために VimFx を入れたり外してたりしたわけだが、普段はこの手の、ブラウザのインターフェースを vi 風味にする拡張というものを使っていない。正確には、Keysnail によって最低限の vi っぽいショートカット(hjlk とかその程度)を付け足してはいるが、その程度だ。hit-a-hint などのナウい機能は使わなくても何とかなっている。

これはなぜかと改めて振り返ってみると:

  • トラックポイント付きのキーボードを常用しているので、そもそもポインティングデバイスとキーボードの併用にストレスがあまりない
  • wasavi の動作テストをするにあたって、特定の拡張の影響を排除したい
  • この手の拡張を入れると、web ページが個別に定義するキーボードショートカットと拡張自身のショートカットのどちらを優先するかという問題が必ずつきまとう。この手の問題に煩わされたくない

ということだろうと思う。

そういうわけで個人的な要求としては、「ブラウザのナビゲーションにおいて vi っぽいショートカットは多少はあれば嬉しいけど、おおがかりに vi っぽくはしなくていいし、してほしくない」ということなのである。現在常用している Firefox においては、それは Keysnail で自分でちまちまとスクリプトを書けば対応できる。一方で Chrome はどうだろうか。Chrome も常用とはいかないが、それなりに使っている。

まず vi flavored なエクステンションはどうだろうか。Chrome におけるその手のエクステンションを列挙してみると:

…なんでこんなにあるんだ?

2015/11/16 4:15 pm
Chromium versus Firefox on xubuntu
Uncategorized, ,

かつて、Presto Opera からの移行先をいろいろ検討した結果、Firefox を選択したわけなのだが、残念ながら、Firefox がベストなブラウザというわけでは全然ない。

xubuntu のノート上で Firefox を起動し、ノートをサスペンドし、リジュームする。そうすると困ったことにやたらノートが発熱する。不思議なことに load average は特段変化はないのだけれど、しかしノートの底面は信じられないほど熱くなる。Chromium ではそういうことはない。

そのほかにも、Linux 版の Firefox はなかなか不安定だ。入れているのが Developer Edition というのを差し引いたとしても週に数度は落ちるし、Flash のコンテンツは「運が良ければ見られる」レベルだし、そもそも Linux 版の Flash をどうするのかステートメントがいまいちはっきりしないし、製品はもとより拡張の行く末を始めとして Mozilla の動き自体が迷走に迷走を重ねていて、Mozilla というブランドの信用性はもう本当に、急降下している。

そんなわけで Chromium もちょっとずつ使うようにしているのだけど、困ったことにこちらにもいくつか問題があって、オムニボックス上の文字入力がやたら重いのである。キーを 1 つ打って、そのレスポンスが帰ってくるまでに数秒かかる。これはもしかしたら、いわゆる「おま環」なのかもしれない。ググってみるとプロファイルを一新すると治る的な記事もある。しかしこの現象、うちの環境では Chromium だけではなく Opera Developer でも同じなのだ。それなりに普遍的な不具合ではないのだろうか。

Archives