Home > Latest topics

Latest topics 近況報告

たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。

萌えるふぉくす子さんだば子本制作プロジェクトの動向はもえじら組ブログで。

宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

Page 1/242: 1 2 3 4 5 6 7 8 9 »

ツリー型タブでタブの並び順が壊れる問題との格闘 - Jan 12, 2019

ただの苦労話です。

ツリー型タブWebExtensionsに移行してからこっち、ずーーーーーっと悩まされてる事がある。それは、TSTのサイドバー上のタブとFirefox本体のタブの並び順が一致しなくなる事があるという問題。

何故そういう事が起こるのかというと、色々な背景があるのですが……

  • 当初はタブの並び順の制御については、WebExtensionsのAPI経由でタブを移動した後、それがtabs.onMovedで通知されるのを待って、通知された情報に基づいてツリーを更新するということを考えていた。
  • しかし実際にそうしてみると、まあ遅いこと遅いこと。Firefoxとアドオンのプロセスが別だからなのかそれとも別の理由があるのか、イベントがTSTに通知されてくる(結果が返ってくる)までにかなりのタイムラグがある事が分かった。
  • そこで、WebExtensionsのAPI経由でFirefoxのタブを並べ替えるのと同時に、別途runtime.sendMessage()でタブの移動を行う指示をバックグラウンドページとサイドバーの間でやり取りして、イベントの通知を待たずに先にツリーだけ更新するようにした。

で、タブを一つ一つゆっくり操作している場面(僕の普段の使い方)ではこれで問題無かったんですが、このやり方には、リンクからタブをまとめて開くとかブックマークレットを使うとかしてTSTのあずかり知らぬ所で複数のタブが一気に開かれた場合に、TSTのツリーとFirefoxのタブの順番の同期が崩れやすくなってしまうという、大きな大きな副作用がありました。

  • tabs.onCreatedtabs.onMovedなどのイベントがそれぞれ非同期で送られてくる。
  • そのリスナの中で非同期に、タブを親タブにattachしたり、タブを並べ替えたりしている。
  • そうこうしている間に新しいタブが開かれたり移動されたりする事もある。
  • それどころか、処理中だったタブが閉じられてしまう事もある。(開かれたタブを自動的に別のコンテナで開き直す、みたいなアドオンがあると起こる)

こういった感じでもうシッチャカメッチャカで、こんな状況の中でタブの並び順やら存在確認やらを厳密に把握して破綻の無いように管理するなんて、どだい無理なわけです……全部のイベントをキューに積んでシーケンシャルに処理していけば安定はするだろうけど、そうしたら死ぬほど遅くなるだろうし。いまですら遅い遅いと言われているのに、これ以上遅くなったらどうなることか、考えるだけでもそら恐ろしい。

それでも何もしないわけにはいかないので、とりあえず、挿入中のタブがある時は最低限IDが確定するまでは次のタブを挿入する処理を止めるとかの、焼け石に水のような細かい対策をちまちま重ねていました。が、最近になって「ちまちまやっててももうどうしようもない」という境地にようやく至りまして、とりあえずタブの並び順の制御についてだけは、

  • まずruntime.sendMessage()でTSTのツリーだけ並べ替える。これはリアルタイムに行う。
  • tabs.move()の呼び出しは、ある程度キューを溜めておいて後でまとめて行う。その時は、TSTのツリー上のタブの並び順をマスターとして、それに合わせるようにFirefoxのタブを並べ替えるという事を徹底する。

という事をやるようにしました。

ただ、この方向で愚直にやると、全部のタブの並び順をチェックするような処理が頻繁に実行される事になって、タブが何千とか開かれてる環境ではますます遅くなってしまうと容易に予想できるわけで。もうやだ……どうやっても詰みじゃん……安定性を突き詰めればクッソ遅くなっていって、体感速度の向上を意識すれば安定性が犠牲になって……

こんなことならもっと早くに現行の設計を諦めてReactDOMとかの仮想DOMベースに作り直しとけば良かった。あれなら確か、JSON形式のマスターデータを雑に編集してそれをビューに随時渡すだけで、ビュー側は現時点のDOMツリーから期待されるDOMツリーの状態への最短の編集距離を求めて、最小限の変更で高速にDOMツリーを更新してくれるっていうじゃないですか……という所まで考えて、はたと気が付きました。そうだ、タブの並べ替えも最小限の変更だけで済むようにすればいいんじゃん、と。

実はこれにはアテがありました。遙か昔にアドオンの自動テストをやりたくてUnitTest.XUL略してUxUというアドオンを会社で作っていたのですが、テストケース中のアサーションの期待値と実測値の差分をdiff形式で出力するために、当時すとうさんPythonのdiffの実装をJavaScriptに移植した物を入れて下さっていて、これが使えそうだったのです。

これは元々はUnified Diffのテキスト形式を出力するだけの実装だったのですが、僕がTortoiseSVNやTortoiseGitで見慣れていたカラフルな差分表示をUxUでもやりたくなって、HTMLのタグを含めた出力を組み立てるような処理を自分で書いた事があり、その時に、diffの実装は内部的には行単位ではなく1文字単位で違いを検出できているという事を知ったのでした。ということは、それを応用すれば「元のDOMツリーからこの要素だけ移動すれば期待したDOMツリーになる」「元の並び順のタブからこのタブだけ移動すれば期待したタブの並び順になる」というような必要最小限の編集手順を特定するのにも使えるはずです。

ということで、実装をそのままTSTに持ってきて、いまどきのES2017っぽいスタイルに直した上で、tabs.move()でのFirefoxのタブの並べ替えDOMツリーの編集をそれぞれなるべく少ない手順でやるようにしてみました。

コードを見ると分かりますが、実際に使っているのはdiffの実装の中のSequenceMatcherというコア機能だけです。本来は文字列を1文字単位で比較するための物ですが、実装的にはArrayを渡せばArrayの要素単位で比較してくれそうな雰囲気だったので、文字列の代わりにタブのIDを入れた配列を渡してみた所、いい感じにequal(変更無し)、delete(削除)、insert(追加)、replace(置き換え)という形で最小の編集手順を導き出してくれました。タブの並べ替えでは「タブがなくなる」という事は前提としてあり得ないため、insertreplaceのうち挿入箇所にあたる部分だけを編集情報として使っています。これのお陰で、いままでは無駄に何度もタブを行ったり来たりさせていたのが、場合によってははるかに高速に並べ替えが完了するようになってくれました。

レガシーなやり方を捨ててモダンな仮想DOMへの移行のきっかけになるはずが、何だかんだで結局、部分的にとはいえ似たような事を自前でやるようにしてしまったということで、なんだかなあ……と頭を抱えているのが「今ココ」ということで、特にオチはありません。

(まあ、仮に仮想DOMに全面的に設計を刷新したとしても、tabs.move()でFirefoxのタブの並び順を制御する部分はきっとそのまま使い続ける事ができそうではあるので、今回やった事も完全に無駄というわけではないかな、と……)

How to use new "Successor Tabs API" of WebExtensions on Firefox 65? - Dec 03, 2018

By the fixed bug 1500479, following new features become available on Firefox 65 and later.

  • New property previousTabId for activeInfo object notified to listeners of tabs.onActivated.
  • New property successorTabId for tabs returned by tabs.get(), tabs.query(), and other APIs.
    • It is updatable via tabs.update().
    • However, there is no way to know changes of the property dynamically. It is not notified to listeners of tabs.onUpdated, and there is no alternative listening API like tabs.onHighlighted.
  • New method tabs.moveInSuccession() to set successorTabId for multiple tabs, as an atomic operation.

When you close the active tab (by Ctrl-W or any operation), Firefox instead focuses to its next or previous tab. Or, if the closed tab was opened from another tab, Firefox possibly focuses the opener tab. In short: new Successor Tabs API is a mechanism to override these behaviors.

続きを表示する ...

WebExtensionsのSuccessor Tabs APIの使い方 - Dec 03, 2018

Bug 1500479が解決され、Firefox 65以降のバージョンで、WebExtensionsのタブ関連APIに以下の変更が入る事になりました。

  • tabs.onActivatedのリスナに通知されるactiveInfoに、previousTabIdというプロパティが追加されました。
  • tabs.get()tabs.query()などで取得されるタブのオブジェクトにsuccessorTabIdというプロパティが加わりました。
    • このプロパティの値はtabs.update()で変更可能です。
    • このプロパティの値の変更はtabs.onUpdatedでは通知されません。tabs.onHighlightedのような専用のリスナもありませんので、変更を動的に検知する方法はありません。
  • 複数のタブのsuccessorTabIdをまとめて変更するtabs.moveInSuccession()メソッドが追加されました。

Firefoxでアクティブな(現在の)タブをCtrl-Wなどで閉じると、右隣や左隣、あるいはそのタブを開いた親のタブにフォーカスを切り替えるようになっています。上記の新機能は、この挙動に介入するための物です。「successor」とは「後継者」という意味で、つまり、アクティブなタブを閉じられた後に次にフォーカスされるタブを指定する仕組みという事になります。

今までの問題

今までは、WebExtensionsのAPI経由でこの挙動に介入する方法がなかったため、例えば「タブを閉じたら、必ずそのタブの直前に見ていたタブにフォーカスを移す」というような事をアドオンで実現しようとすると、

  1. Firefoxによって何らかのタブがフォーカスされる。
  2. その後改めて、別のタブにフォーカスし直す。

という手順を踏む必要がありました。これは見た目に美しくない(一瞬無関係のタブがフォーカスされてしまう)のもさることながら、現在のFirefoxの初期設定である「Ctrl-Tab/Ctrl-Shift-Tabで最近フォーカスされた順にタブのフォーカスを切り替える」という挙動にも悪影響を与えます。

拙作アドオンのツリー型タブも、ツリーの最後の子を閉じたら、右隣のタブ(=下にある別のツリーの親タブ)ではなく1つ前の兄弟タブまたは親タブにフォーカスを移すという機能があり、これを実現するにあたっては前述の点がずっと未解決のままでした。今回のAPI追加によって、ようやくこの問題を解決する目処が立ったと言えそうです。

続きを表示する ...

WebExtensionsのコンテキストメニューの新常識 on Firefox 64 - Nov 06, 2018

Here is the English version of this article.

朗報があります。2016年6月にWebExtensionsへ一本化の方針が示された時に出した要望であるBug 1280347 - Add ability to provide custom HTML elements working as alias of existing Firefox UI items, especially tabsが、最近ようやく解決されました。

何故これが朗報なのでしょうか? アドオンのXULからWebExtensionsへの移行の話をおさらいしてみましょう。

続きを表示する ...

WebExtensionsベースのアドオンが他のアドオンと連携するにはどうするのが良いか? - Nov 06, 2018

Here is the English version of this article. 7月に英語で書いた物の日本語版です。Qiitaにもクロスポストしています

ツリー型タブXULからWebExtensionsに移植した時の話で、アドオン同士の連携が取りづらくなる事への懸念について書きました。この点について現時点での知見をまとめておきます。

続きを表示する ...

WebExtensionsでのタブの複数選択APIのつかいかた - Nov 01, 2018

Tokyo WebExtensions Meetup #3で、標題の通りの発表をしました。スライドはQiitaにありますが、こちらにもクロスポストしておきます。

タブの「選択」状態とは?

タブの複数選択機能が入った事で「選択」という言葉が多義的になってしまったので、まずその点を整理します。 WebExtensions APIにおいては、「選択」という言葉で表されうる状態に以下の2つがあります。

  • アクティブ なタブの事
    • active tab というのがWebExtensions APIの語彙上の言い方
    • current tab という言い方も古くからある
    • foreground tab という言い方もある(background tabとの対比)
  • 選択複数選択) 状態にあるタブの事
    • highlighted tab というのがWebExtensions APIの語彙上の言い方
    • multiselected tab という言い方もされる

「selected tab」という表現は紛らわしいので、このエントリでは使いません。

Firefox本体に入ったタブの複数選択機能

Firefox 63でabout:configbrowser.tabs.multiselecttrueにすると試せます。Chromeでも同じ操作ができます。

  • タブの上でShift/Ctrl(Command)-クリックでタブを選択できます。
    • 選択されたタブは、上に青い線(Linux版ではシステムカラーに依存する。UbuntuのAmbientテーマではオレンジ色)が出る。
      (スクリーンショット)
  • タブが選択されていると、コンテキストメニューほか一部の機能が「選択中のタブすべてについてそれをする」ようになります。 (スクリーンショット:メニューのラベルが「Tab*s*」になっている)
    • まだ一部の機能はそのようになっていない。Firefox 64で一通りの機能がすべてタブの複数選択に対応するという事だと予想される。

アドオンからの2つの利用局面

WebExtensionsベースのアドオンにとっては、このタブの複数選択機能に対して2つの関わり方があります。

  • 選択されたタブに何かする
    • タブを処理対象にした便利な機能を提供するアドオンの場合
  • タブを選択する
    • タブを管理する、タブバーの代替となるアドオンの場合

それぞれ順番に紹介します。 なお、基本的にはChromeの拡張機能でも同様のAPIが使えます。

続きを表示する ...

Various "custom context menu" usages in Firefox 64 - Oct 26, 2018

As I described at the previous article, you can provide more useful and usable context menu for your addon on Firefox 64 and later, if it is focused to control tabs or bookmarks. The previous article described basics of new APIs, but it looked too complex because there are various usecases. So this article aims to describe how to provide context menu simply for different cases:

  1. Extra context menu items for custom commands, when your addon has no sidebar/popup panel
  2. Extra context menu items for custom commands, grouped under a submenu with a custom label
  3. Context menu dedicated to custom commands on your sidebar/popup panel, and expose them as a submenu on other situations
  4. Context menu dedicated to custom commands only on your sidebar/popup panel
  5. Context menu dedicated to custom commands on your sidebar/popup panel, and expose them as a submenu on other situations, with a custom label
  6. Imitated context menu compatible to Firefox's one on tabs or bookmarks, only on your sidebar/popup panel

All following examples assume that your addon named "Bucket" provides ability to send tabs to an online bucket, like the "Pocket".

続きを表示する ...

An improvement of WebExtensions on Firefox 64 about implicit collaboration of addons - Oct 14, 2018

このエントリの日本語版はこちらから読めます。

(Note that this article describes about an improvement on Firefox 64, and Firefox ESR60 is out of target.)

Good news! An old feature proposal filed at the time Mozilla announced that XUL become deprecated and WebExtensions become the next main line has became fixed: Bug 1280347 - Add ability to provide custom HTML elements working as alias of existing Firefox UI items, especially tabs.

Why it is a news for me? Let's look around the short history of addon migration from XUL to WebExtensions.

続きを表示する ...

What's the best way to collaborate an WebExtension-based addon with others? - Jul 28, 2018

このエントリの日本語版はこちらから読めます。

When I migrated my addon Tree Style Tab from XUL to WebExtensions, I wrote some concerns about communication between addons. Let's share my knowledge around the topic.

続きを表示する ...

私達はここまで来た - Jun 06, 2018

昨年10月のFirefox 57リリース直前の時期に、アドオンのWebExtensionsへの移行を主導してきたAndy McKay氏がそれまでの歩みを述懐して書かれたブログ記事の勝手訳です。


私はMozillaに在籍してきたこの7年の間に色々な事をやってきました(訳註:Mozilla Add-onsに始まり、Firefox OS用のマーケットプレイスとその支払いの仕組みに関わった後、Mozilla Add-onsとWebExtensionsに戻ってきた、とのこと)。 ほんの2年前、私はアドオンコミュニティをWebExtensionsに移行させるという、Mozillaに参加して以来で私にとって最大のプロジェクトを任されました。 あと3週間ほどのうちに、Firefox QuantumはすべてのFirefoxユーザーの元に届けられ、WebExtensionsはFirefox 57においてアドオンを実行するための唯一の方法となります(訳註:その後、2017年11月14日にリリースされた)。

これは、物事を変えると決めて一緒に取り組んできたMozillaの人々の素晴らしいチームによる、2年間の努力の成果です。 私はその最初の数週間、何でこんな事になってしまったんだ?という、とんでもない恐怖の感情に駆られた事をはっきりと覚えています。 多くの人がこのプロジェクトにおいて私を助け支えてくれましたが、特に私が思うに、Kev Needham(訳註:Mozillaでプロジェクトマネージャを務めている人)が我々を導いてくれなかったら、私達は救いようのない状態に陥っていたでしょう。 私がその最初の数週間のパニックと恐怖に陥った時に、Kevと何度か対話した結果もう少しマシな状態に戻る事ができたというのは、その好例です。

最初の数週間は私達のエンジニアリングチームにはKumar McMillan、Stuart Colville、Matthew MacPherson、そしてKris Maglioneがおり、外を出歩いて更なるエンジニアを見つける事が、その月の私の主な目標でした。 その後すぐにChristopher Grebs、Mathieu Pillard、Mark Striemer、そしてLuca Grecoが加わってくれました。 私達が働き始めた最初の週には、2016年のベルリンにMatthew Wein、Andrew Swan、そしてBob Silverbergもいました。 後にShane CaraveoとAndrew Williamsonが参加してくれたのも、私達にとってはとても幸運な事でした。 様々な分野の知見と技術力を備えた彼らエンジニアの能力は誇張するまでもなく、彼らが成し遂げられた事は驚くべき事です。 私は彼らがなした事のすべてをこの記事に列挙したかったのですが、それをすると記事がとんでもなく長くなってしまうでしょう。 私達がやった事やWebExtensionsのアドオンを書く事に関する多数のブログ記事をぜひ読んで下さい。

私にとっては、個人としてこのプロジェクトを受け入れないという選択は取り難かったのですが、この決定に反対する人達も大勢いました。 彼らは様々な異なる方法で定期的にその事を私達に知らしめようとしました。 私がMozillaに在籍するようになってから、これほどまでに激しい反対に遭った事はありませんでした。 Mozillaの他の人達が取り組まなくてはならなかった色々な事に対し、私は本当に感謝しています。

それらの懸念の声の周りを進む事は非常に大変で、時には私は舵をうまく取れず、その体験自体も助けになりませんでした(訳註:苦労したわりに得られる物が無かったという事か?)。 学習曲線がそうであるように、最初からはうまくいかない物です。

その一方で、この決定に同意してくれた他の人達による手助けは素晴らしい物でした。 ちょうど先週トロントで、複数の人々が私達の方にやってきて、私達がやり遂げた変革に対して感謝を述べてくれました。 助けてくれた皆さん、本当に、本当にありがとうございます。

私は今も、これが私達がFirefoxに対してできる最善の事の一つだったと強く確信しており、成し遂げた事を私は誇りに思っています。 それは大きな変革であり、リスクと不確実性を伴う物でした。 控えめな表現をすると、これが今後どう進んでいくかについて、やや神経質になっている部分はあります。

でも、私達はもうここまで来ました。3週間後にはFirefox Quantumがリリースされ、そこにはもうレガシーなアドオンは存在し得ません。


以上、Andy McKay氏のブログ記事の訳でした。

WebExtensionsへの完全移行に伴うレガシーアドオンの廃止については、アドオン作者や一般ユーザーから強い反発がありましたが、Mozillaの外からだけでなくMozillaの中からもそういった反発があったというのが興味深いです。

氏はその後、今年の3月にGitHubに移籍されています。そのGitHubが今度はMicrosoftに買収されて、間接的にMS資本の元におられる状態になっているという事で、不思議な運命を感じますね。

1つ前に訳したroc氏のブログ記事では、「Geckoを捨てWebKitに移行するべきだ」という破壊的な提案が述べられていましたが、そちらは実現する事はありませんでした。それと、このレガシーアドオンの大量死と大混乱をもたらしたWebExtensionsへの移行という大転換との間には、「最後までやり遂げて実現させたか、させなかったか」というだけの違いしか無いのかも知れません。

ただ、XULの中にはXPCOMと密に結合した部分も多々あり、XULの一切合切をWebKitの上に移植するのは現実的ではなかったのでしょう。仮に本当に互換性を保つ形でやるとしたら、相当に分厚い互換レイヤがWebKitの上に乗っかる事になり、そのオーバーヘッドは無視できないレベルだったのではなないでしょうか。あるいは、オーバーヘッドをなくすためにGecko上のXPCOMやXULとの互換性を犠牲にしていたら、結局それに合わせるための作業がXULアプリやアドオン側にも発生するわけで、それだったら最初からWebKitに親和性が高い形で作った方がなんぼかマシという事になっていたでしょう。いずれにしろ、roc氏の予想にあったような「WebKitの高性能さとXULの資産のいいとこ取り」は絵に描いた餅に過ぎなかったのだと僕は思っています。

Andy氏には、2016年のAll Handsにお声がけを頂き、現地でお会いした際には、グループディスカッションの場では英語のやり取りが速すぎてついていけなかったので、その後一人になられた時を見計らって捕まえて、「アドオン同士の連携を取れる事が大事なんだ」という事をつたない英語で一生懸命伝えた(同じような事をLuca氏にも言った)のを覚えています。

自分はこの記事が書かれる1ヵ月弱前にツリー型タブのWebExtensions版をリリースしましたが、「もうグダグダXULにしがみついててもしょうがない、やるしか無い」と腹を括って重い腰を上げ、他のアドオンとの連携を意識したAPIも備えた物をリリースするに至った背景には、その時Andy氏やLuca氏等と直接話して感じた「ああ、この人達は本気で物事を良くしようとしてるんだな」という心意気……みたいな? そういうのを感じて、こちらも相応の物で応えねばなるまいと思ったから、というのも心のどこかにあったのだと思っています。

1つ前の翻訳記事にも書きましたが、WebExtensionsによってFirefoxとアドオンが明確に切り離された事は、FirefoxおよびGeckoの抜本的改革を進める上でプラスに働いているという事を最近とみに実感します。 実際、Firefox 59からFirefox 60にかけての間でも、タブバー周りの実装からXBLが取り除かれるなどのかなり大きな変化がありました。 今までであれば(WebExtensions版より前のツリー型タブなどの)アドオンの互換性が損なわれたという事で大騒ぎになっていた(僕がグダグダ噛み付いていた)かもしれません。 そういった一切がWebExtensions APIの向こう側に隠蔽された事によって、アドオン作者は安心してアドオンの開発に集中できるようになっているという現実を見るに、レガシーアドオンの廃止とWebExtensionsへの移行はやはり必要だったという事を改めて感じる次第です。

(2018年6月8日追記。大袈裟だ、WebExtensions移行を正当化したいだけのこじつけだ、と思う人もいるかもしれませんが、最近実際にあったFirefox 61での後退バグとその原因の例を見るに、XULアドオンの仕組みのデメリットは色々あったという事は否定できないと思っています。)

というか、最近久しぶりに仕事でレガシーアドオンを触る事があって、「もうこんなの作りたくない……WebExtensionsで書かせてくれ……」と思ってしまいました。最初あれだけ渋ってたのに、今じゃすっかり骨抜きですよ……

Page 1/242: 1 2 3 4 5 6 7 8 9 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき