Home > Latest topics

Latest topics 近況報告

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

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

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

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

「なぜMozillaはXULアドオンを廃止したのか?」に寄せられていた反応を見て、「甘い……甘すぎる……」と思って、W3C信者時代からの価値観に行き着いた話 - Aug 27, 2020

1つ前の翻訳記事の末尾には当初、自分の個人的な考えを長々と書いていたのですが、翻訳記事でそういうことをやるのはマナー違反という指摘を頂きました。自分でも確かに、思い入れのあまり熱くなって書きすぎと感じていたので、別記事に分けるついでに増補改訂することにしました。)

原文に寄せられていたHacker Newsでの反応や、僕の翻訳に寄せられていた反応を見ていると、XULを捨てる判断を間違いと断じる物や、そのような判断をしたMozillaに対する恨み節、あるいは「バカな判断をしやがって、そんなだから俺らパワーユーザーから見捨てられたんだ」みたいな捨て台詞じみた物が結構見られました。

それらを見て僕は正直、「これだけ丁寧に書いてあってまだそんな風に思えるってどういうことなの……」と驚くやら呆れるやらしたのですが、自分自身もかつてはそっち側にいた自覚があったので、「なんでそう思うのか」も分からなくはありません。

甘い見通し

今でも「見境のない拡張機能の仕組み」を支持し続けている人というのは、アドオン開発者にしてもユーザーにしても、ある意味で楽天的というか、性善説を信じているというか、そういう感じなのかなあと思っています。

「従来路線でいっても生きていけただろう、少なくとも玄人向けとしてなら生き残れただろう」という意見については、以前の記事で「それでは結局現実に生き残れない」とバッサリ切りましたし、1つ前の記事のコメント欄にも書いてみました。しかし、それとは別に「諸々の進歩を継続しつつ、アドオン開発者やユーザーに自己責任での自由を残すのでは駄目なのか?」という主張もあります。自分もFirefox Quantum以前はそのような立場でした。

この場合の世界観は以下のように要約できるかと思います。

  • アドオン開発者:「自分はFirefoxの変更に振るい落とされることはない、いつまでだって追従し続けられる」と考えている。
  • ユーザー:「アドオン開発者はそのような努力をいつまでも続けてくれる」と考えている。

しかし、自分の体験と先の記事の内容を踏まえて、今僕が思うのは、「甘い……まったく甘すぎる……」ということです。

僕自身、日々壊れていくXULアドオン時代のTSTを維持するのには、ものすごい苦労を要していました。当時はそれが当たり前だと思って麻痺していただけで、実際には狂気の沙汰だったと感じています。TSTをWebExtensions化して以後の感覚では、XULアドオンを書くのなら、実作業時間で1時間あたりN万円くらいのお金を貰って仕事としてやらないと、とてもじゃないけどやってられないです。それくらいに、XULアドオンは維持にコストがかかると言わざるを得ません。「少額ながら寄附を……」とかいうレベルでは収まらない、もはやビジネスの話です。

僕自身はライフステージはそれほど変わらないままですが、結婚や子育てなどライフステージの変化の影響で、毎日アドオンのメンテナンスに時間を割くことはできなくなってしまう人も、当然いたでしょう。メンテナンスに膨大なコストを要するアドオンを継続し続けなくてはならないのでは、作者の人生をそれだけに縛り付けることにもなりかねません。

あるいは、作者個人が自分の使う範囲だけで細々メンテナンスし続ける程度なら可能かもしれませんが、それを「第三者が使いやすい」状態でリリースまでするモチベーションはどんどん下がっていく一方でしょう。

「見境のない拡張機能」は、もはや「ユーザー」はお断りの世界

なぜなら、ものすごく嫌な言い方をしてしまうと、今XULアドオンを一般向けにリリースしても、パッチも提供してくれない・問題の再現条件の特定もしてくれないクレクレ君達からの、「お願いですぅ~直してくださいぃ~ボクにはとてもメンテできましぇ~ん」みたいな声が増えるばっかりで、いいことがないからです。

それは言いすぎだろう、パワーユーザー向けならそんなことないのでは、と思う人もいるかもしれませんが、こういう修羅の世界では「敬意を払ってくれるユーザー」や「お金を出してくれるスポンサー」だけいても、結局は搾取構造にしかならない、と僕は考えています。。

一般的には「OSSにできるコントリビュートはプルリクエストだけではないです。障害報告も立派なコントリビュートです。必要な環境、再現手順、期待される結果、実際の結果を明記した良い障害報告をしましょう」ということを僕も言っていますが、「見境のない拡張機能」の世界では、それですら作者側の負担が大きすぎると言わざるを得ません。プルリクエストやコードを実際に提供し合うような、「同じ技術レベルで共に並び戦ってくれる戦友」同士で助け合う以外には成り立たない、そのレベルで戦列に加われない人に関わられて期待されても困る、というのが正直な所です。

技術的な事実をいうと、今でもFirefoxでは「見境のない拡張機能の仕組み」と同等のことをやる余地は残っています。AutoConfigの仕組みを使って、(Firefoxのインストール先)/defaults/pref/autoconfig.js

pref("general.config.obscure_value", 0);
pref("general.config.filename", "autoconfig.cfg");
pref("general.config.vendor", "autoconfig");
pref("general.config.sandbox_enabled", false);

という内容のファイルを置き、(Firefoxのインストール先)/autoconfig.cfgにゴリゴリ書いていけば、Firefoxのchrome領域上で任意の特権スクリプトを動かすことができます。実際、僕も仕事の上でどーーーーーーしても必要に迫られた場合はそうしていますし、Firefox内部で任意のスクリプトを特権付きで動作させるアドオンだった「userChrome.js」のエコシステムを継続している人達も、この方法を使っているようです。

こういう使い方をすると、前の記事で散々書かれているような「バージョンアップですぐ動かなくなる」「代替策がない」というドン詰まり状況が頻繁に発生します。ググって見つけたブログ記事やQiitaの記事のコピペで使うだけではとても維持できず、「自分で原因を調べて、自分でコードを直す」ということがどうしたって必要になってきます。誰かが直してくれるのをボケッと待ってるだけでは、今のFirefoxのリリースサイクルにはまず追従できないでしょう。

なお、この方法を使っている人達は百も承知だとは思いますが、この方法もいつまで使い続けられるかは分かりません。それでも、「Firefoxのソース自体に手を入れて、Firefoxそのものを独自ビルドする」のは依然として可能です。あるいは、そこまでやるならChromiumに乗り換える(Chromiumを改造して独自ビルドする)方がいいかもしれません。もはや完全に根性試しの世界ですが、腕力さえあれば乗り切れるのがOSSのいい所です。腹を括って「この方向でも生きていけるんだ」ということを示し続けていく人は、いてもいいとは思います。僕にはとても真似できませんが……

Thunderbirdの場合

FirefoxはFirefox 57で「見境のない拡張機能」をバッサリ切りましたが、Firefox ESRのスピード(1年ごとのメジャーアップデート)でゆっくり物事が推移しているThunderbirdは、もう少しソフトランディングな方向で進んでいます。会社のブログに書いたThunderbirdアドオンのTb78対応の話では「使うな」とサラッと流していますが、アドオン作者向けのThunderbird 78向け移行ガイドによると、Thunderbird 78では「公式のWebExtensions APIには含まれていないけれども、こういうAPIが欲しい」という機能があるときに、アドオン作者がそれを自力で実装する、Experimental APIという仕組みが利用できるようです(これはFirefoxでも提案はされていたのですが、なんやかやで結局実際には使える状態にならなかったと記憶しています)。

ただ、そのような本来の意図とは裏腹に、Experimental APIは結局「見境のない拡張機能」と同じことをするための互換レイヤー作りのために使われてしまっているようです。少なくとも、CardBookという巨大アドオンのThunderbird 78対応ブランチでは、ほとんどのソースはXULオーバーレイ前提になっていて、Experimental APIでXULオーバーレイ相当のことをしている様子が伺えました。

まあ、そうしたくなる気持ちは、分からなくもないんですよ。移行ガイドは(ちょろっとしか見てないですが)「こうやってちょっとずつ移行していきましょう」みたいなソフトな書き方をしてるし。一般的に、ハードランディングよりソフトランディングの方がいいとされてますし。前の記事にあった通り、Firefox自体もちょっとずつ段階的に改良されていったわけですし。

でもねえ、XULアドオンのWebExtensionsへの移行だけは、TSTのWebExtensions化で僕がやったように、「腹を括ってゼロから作り直す」以外の選択はないと思うんですよ。XULアドオンとWebExtensionsアドオンではパラダイムが違いすぎて、「ちょっとずつ置き換え」なんてできないんですよ。

「ちょっとずつ置き換えるためにとりあえずExperimental APIで全部持ち越した」の先にあるのは、「ちょっとずつ移行しようと思ってたけど、どうやって移行したらいいか見当もつかない」という混乱、そして何もできずに手をこまねいての停滞、最終的には時間切れ(Experimental APIの廃止)での完全死だけ。そうなる前に、いかに早く頭を切り替えて腹を括ってゼロから作り直そうと思い切れるか、それが生死を分けると僕は思ってます。

優先順位が違ったから僕は腹を括れたのかもしれない

XULアドオンのWebExtensions化では、「WebExtensionsらしいやり方でゼロから作り直して」「APIが足りない部分は、WebExtensionsらしい作法に則ったAPIを提案する」「要望が通らなかったら諦める、無理はしない」というのが最も「正しい」やり方です。自分は一応今のところはそういう方針でやっているつもりですが、改めて考えてみると、僕がこの方針を取れているのは、僕の本心が、多くの「見境のない拡張機能の仕組みに今でもこだわり続けている人達」とは別の所にあったからなのかもしれません。

元記事に寄せられたPale Moonのメンテナーの人のコメントでは、徹底的なカスタマイズを必要としている人のために頑張っているのだ、ということが語られています。それ以外の怨念の籠もったコメントや捨て台詞じみたコメントも、通底しているのは「自分のやりたいようにカスタマイズできることが一番大事、それ以外は二の次」という価値観のように僕には思えました。

対する僕は、「Mozillaの掲げるOpen Webの実現が一番大事、そのために必要な物としてGeckoというレンダリングエンジン実装が継続することが必要、自分のやりたいようにカスタマイズできることは二の次」と考えているようです。いま自分がインターネットを使いたいように使えるのはOpen Webがあってこそで、その邪魔になるなら自分の細かい要望は(なるべく実現できるに越したことはないけど、どうしても衝突するなら)脇に置いても構わない、というか、自分の要望を無理に押し通した結果Open Webが失われては元も子もない、という考え方なのだと思います。

これはべつに、Mozilla信者だからMozillaの言うことに何でも従ってる、というわけではありません。Mozillaに入れ込むようになるより以前、W3C信者として調子こいてた頃に僕が入れ込んでいた、アクセシビリティとかユニバーサルとかの話が先にあって、Mozillaの掲げるOpen Webはそれに連なる物だと捉えている、ということです。(そもそもで言えば、僕はWeb標準を素晴らしいと思っていて、そのWeb標準の技術に基づいたXULとCSSて実用的なデスクトップアプリケーションを作れる実例が示されていたから、ということでMozillaに入れ込むようになったのでした。)だから、もしMozillaが「Open Webなんかどうでもいい、Web技術の標準化とかどうでもいい」なんて言いだしたら、僕はその時の方が深く失望すると思います。

 

この日記の話題が、ここ数年ジェンダーとか差別とか多様性とかそういう話ばっかに偏ってた感じはありましたし、「シス管系女子」でみんとちゃんやその周辺の人物達の様子を描くときにもそれがずっと裏テーマとしてはあったんですが、それらも大きな括りでは近いところにあるんですよね。

そう考えると、僕がやってることはあれもこれもどっかで繋がってるんだなと。しがないラジオのとき自分のやってきたことを線で繋いだ図にしたけど、単にバラバラにそれらがあったわけじゃなく、1つの価値観の多様な表現形だったということなのかなと。

W3C信者活動をやめてすっかり軸足がよそに移ってしまったと思ってたけど、判断の根底にはまだまだW3C信者だった頃の何かが残ってたんだなあ、と改めて思い知らされて、感慨深い思いをしたここ数日だったのでした。

なぜMozillaはXULアドオンを廃止したのか?(翻訳) - Aug 22, 2020

原著:David Teller, 2020年8月20日CC BY-NC 4.0で公開されている内容の全訳。Qiitaにもクロスポストしています。

要約:Firefoxはかつて、XULとXPCOMに基づく偉大な拡張機能の仕組みを持っていました。この仕組みは長い間私達によく尽くしてくれました。しかし、Firefox開発者と拡張機能開発者の両方にとって、メンテナンスコストは増大し続けるばかりでした。ある面では、増大していくコストは、Firefoxをセキュアにしたり、高速化したり、新しい事を試したりするための努力を、少しずつ破壊していきました。また別の面では、増大していくコストはアドオン開発者のコミュニティを少しずつ破壊していきました。最終的に、古いアドオンの仕組みを守ろうとして数年を過ごした後、Mozillaは、この拡張機能の仕組みを廃止し、それより拡張性は劣るもののメンテナンスしやすいWebExtensions APIに置き換えるという、難しい決断をしました。この選択のおかげで、Firefox開発者は再び、セキュリティや安全性やスピードを改善するために必要な変更を行えるようになったのです。

ここ数日、私はFirefoxのユーザーと会話して、2020年8月のMozillaによるレイオフの結果に関する噂と事実を区別しようとしていました。その過程で何度か持ち出されたのが、Firefox Quantumへの移行におけるXULベースのアドオンの廃止のことでした。私は非常に驚きました。もう何年も前に起こったことについて、この選択に感情を害されたと感じている人が、コミュニティにまだいるということにです。

そして、誰かがredditで指摘していたとおり、私は、何故XULベースのアドオンの廃止以外に選択の余地が無かったかについて、私達が深いところを説明する機会をまだ持っていなかったということに気付きました。

そこで、アドオンとGeckoの内部事情の話に飛び込む準備ができている人向けに、これを機にもう少し詳しい話をしてみようと思います。

続きを表示する ...

Virtual DOMでなく生のDocumentFragmentを与えてDOMを差分更新したいって話 - Mar 09, 2020

この記事はQiitaとのクロスポストです。

概要

FirefoxのアドオンやChromeの拡張機能向けに、名前空間をまたいでDOMに変更を差分適用したい場面で使える、Virtual DOMでないReal DOMで差分適用する、webextensions-lib-dom-updaterという名前のライブラリをつくりました。

どう使うの?

クライアント側でタブの情報を取得して、サーバー側でそれをレンダリングする、という場面であれば以下のようになります。

クライアント側(制御担当):

// IDからタブのオブジェクトを得る(WebExtensionsのAPI)
const tab = await browser.tabs.get(tabId);
// プロセスをまたいで、レンダリングして欲しい内容を送る
browser.runtime.sendMessage(
  '受信側の識別子',
  // ↓テンプレート記法でHTMLのコード片をそのまま生成
  `
    <span id="tab"
          class="${tab.active ? 'active' : ''}">
      <span id="throbber"
            class="${tab.status}">
        <span id="throbber-image"
              class="${tab.status}"></span>
      </span>
      <img id="favicon"
           class="${tab.status}"
           src="${tab.favIconUrl}">
      <span id="label">${tab.title}</span>
    </span>
  `.trim()
);

サーバー側(画面描画担当):

import { DOMUpdater } = './dom-updater.js';

// 他のプロセスからのメッセージを待ち受ける(WebExtensionsのAPI)
browser.runtime.onMessageExternal(message => {
  // 反映先の要素
  const before = document.getElementById('container');

  // 反映する内容をDocumentFragmentにする
  const range = document.createRange();
  range.setStart(document.body, 0);
  const after = range.createContextualFragment(message);
  range.detach();

  // DocumentFragmentの内容でbeforeと異なる部分があれば、
  // それをbeforeに差分適用する
  DOMUpdater.update(before, after); // ←これを作った。
});

どの辺に新規性があるの?

Virtual DOMでなく生のReal DOMを更新内容として指定する(※例ではDocumentFragmentを使ってますが、普通のElementでも構いません。)ので、Virtual DOMの独自記法を覚えなくていいです。利点はそれだけです。

既に同じ事をするライブラリが世の中にはあったのかもしれませんが、自分には見つけられませんでした。どなたかご存じでしたら教えてください……

→と書いていたら、morphdomという似た趣旨のライブラリが既にあると教えて頂きました。今回実装したものとの比較を最後に追記しました。

なんで作ったの?

Tree Style TabというFirefox用アドオンで、「他のアドオンから指示して、タブの中に任意のUI要素を追加する」という事をやるために作りました。

(スクリーンショット:Tree Style Tabでの利用例) 見た目を元々のタブに合わせているのでちょっと分かりにくいですが、このスクリーンショットの左側で「Add-ons - Mozilla | MDN」というラベルを伴って表示されている「細いタブっぽい物」が、別のアドオンから指示された通りの内容を、このライブラリによる差分適用で埋め込んだ部分です。

アドオン間での通信ではJSONオブジェクト形式のメッセージしか扱えないため、こういう事をやろうとすると

  • 挿入するUI要素の内容を、どんな書式でどうやって指定させるか
  • 挿入されたUI要素を、どんな書式でどうやって指定して更新させるか

ということを決める必要があります。

Virtual DOM使えばいいやん

DOMの変更の差分適用といえば既存のVirtual DOM専用のライブラリは既にいくつもあって、

このあたりの記法をそのまま使えばいいといえばいい話です。

が、どれもべつに「スタンダード」というわけではないようなので、どれを選んでも後で文句を言われそうな気がします。宗教戦争がもしあるなら、そこに参戦したくはないですし、ただでさえ「Tree Style Tabが他のアドオン向けに提供する独自のAPI」というめちゃめちゃニッチな場面なので、こんな限定された場面のために新たに(もし普段から使っている物があるなら、それとは別のライブラリ由来の)独自の記法を覚えてもらうのは忍びないです。というか、自分がこれ以上覚えたくありません。

その点、HTMLのソースを文字列で指定してDOMの標準的な機能でNodeやDocumentFragmentにするという事にしておけば、多少冗長ではあるものの、「デジュールスタンダードなんで」と言ってしまえます。技術選択で悩まなくてもよくするためだけの選択というわけです。

続きを表示する ...

ツリー型タブ バージョン3.0への道 - Mar 30, 2019

これはただの苦労話です。

2月末から3月末までをかけて、長らく懸案事項となっていたツリー型タブ(Tree Style Tab、TST)の大規模改修をやりました。具体的な変更の量としては、改修に取りかかる前の2.7.22からの差分 git diff 2.7.22 で約1MBありました。見た目は変えなかったのであまり代わり映えしませんし、挙動を決定づけるロジックもほぼそのままなのですが、それらが乗っかる基盤にあたる部分が入れ替わった感じです。

何を改修したのか、どういう成果があったのか、という事を説明するために、TSTのこれまでの歴史を振り返ってみます。WebExtensionsに移行した時の話ではあまり触れなかった、細かい実装の話が多めですが、誰の役に立つかは分かりません。

続きを表示する ...

Chrome Extensions Manifest V3とFirefoxアドオンの死(の可能性) - Feb 04, 2019

1523784 - Set up analytics for https://extensionworkshop.com というbug(※bugzilla.mozilla.orgではシステム上でトラックされているタスクを一般的に「bug」と呼ぶ)でどうやら何かアドオン(拡張機能)作ってみましょう的なイベント?の準備が進められているらしいという事を、人から教えて頂いた。キャンペーンサイトの準備中バージョンらしき物を見てみると、絵が豊富で見た目とっつきやすそうな感じに仕上がってる印象で「ほほう」って思ったんだけど、アドオンの構造を図解してる部分でbackground script等の話が出てきてるのを見て、ちょっとキナ臭いというか不安というかそういう思いが頭をよぎった。

というのも、FirefoxのWebExtensionsというのはGoogle Chromeの拡張機能の現行の仕様(Manifest V2)をベースに作られてるわけだけど、他ならぬGoogleがManifest V3でbackground scriptの廃止などのかなり大きな変更をしようとしている状況で、この内容で大々的にリリース打って大丈夫なのか? と。

だって、このキャンペーンサイト(多分)の内容を素直に受け取ると「WebExtensionsのAPIを使ってアドオンを作ろう。他のブラウザにも移植しやすいよ。」というような話になってると思うんだけど、いやちょっと待ってくださいよ。Firefox向けにWebExtensionsでアドオン作っても、Google ChromeがManifest V3に移行しちゃったら、それ動かないじゃんすか。っていうかChromeがManifest V3に移行するってことは当たり前だけどChromiumもManifest V3になるってことで、ということは、Chromiumベースのブラウザも(各ベンダがどう思ってるかに関係なく、強制的に)全部Manifest V3に移行するってことじゃんすか。次期EdgeもOperaもVivaldiもKinzaもみんなManifest V3に行っちゃって、そしたらChromiumベースでないFirefoxだけ置いてけぼりじゃんすか。

つまり、ChromeのManifest V3移行は、ちょっと前に騒がれてた「Chromeの拡張機能の大量死」という影響だけでなく、Firefoxにとっては「大多数の開発者にとっての、(Manifest V2互換の)WebExtensionsでFirefox用アドオンを作る意義の消失」という影響を及ぼすのではあるまいか? という事に、遅まきながら気付いたわけです。

昨年のTokyo WebExtensions Meetupに参加されていた方が実装上困っておられた事について「Firefoxでは(Chromiumに無い独自拡張の)APIがあるから、Firefox向けにだけちょっと便利にするみたいなことはできるよ」的な話をしたら、「いやあ……Chromeで使えないんじゃ、その機能は使えないですね……」と敬遠された時に、改めて思い知ったのですよね。ああ、WebアプリやWebページを作る人達だけじゃなくて、ブラウザを拡張するという拡張機能を作る人達にとっても、いまや「ふつうはChrome」であって「Firefox対応はオマケに過ぎない」んだな、って事を……

FirefoxのWebExtensionsはいまのところManifest V3に追従する予定はないみたいな話をどっかで又聞きした気がしてますが、いやいやそんな悠長なこと言うとれんやないですか。ツリー型タブを実装できなくなるからManifest V3に完全移行はしないで欲しいけど、Firefox一人だけ置いてけぼりを食らわないためには、オプションとしてでもManifest V3に対応は絶対しなきゃいけないじゃないですか。

ほんとどうなるんだこれ。

 

難しい事は脇に置いて、「アドオンを作る人」「ベンダが提供しているUIに気に入らないところがあってイラッてなったときに自分で手を動かして解決したい人」という立場から「こうだったらいいのに」という事を書き留めておきますと、

  • ブラウザ本体が提供するUIが気に食わない時に努力次第でゴッソリ置き換えられる余地は欲しい。(Tree Style TabやVimiumのような)
    • こういう物を実現するにあたっては、筋の良い設計にしようとするとどうしたって「永続的なバックグラウンドプロセスが全体を統括する」という設計になるので、それができる余地は欲しい。
    • 常時見える状態で画面上の領域を占有できる余地は欲しい。現状で言えばSidebar APIはその代表例。
    • この点で、「サイドバーみたいなものは不要」「拡張機能は原則として一時的に呼び出されすぐ終了する物であるべき」「UIの領域においそれと踏み込ませたくない」みたいな設計者達の思想が強く表れているGoogle Chrome、そしてそのChromeの設計に強く引きずられたあまり永続的なバックグラウンドプロセスまで廃止してしまう(と自分には読めた)Manifest V3は、自分が欲している物とはかけ離れている
  • サイトごとの権限と機能の権限は、確かに別々に記述できるべきだと思う。Manifest V2/現行WebExtensionsのpermissionsの書き方はあまりにダサイ
  • フィルタリングを宣言的に簡単に設定できることは、単純に良い事に思える。
  • 現行のwebRequestのような「クライアントサイドでリクエストやレスポンスの書き換えを任意に行える機能」は、新しい事をやる余地を残すために必要だと思う。
    • ただし、現状のようにシレッと他の権限と一緒に一言だけの注意書きで確認を求められる程度ではなく、「黄色と黒の縞々」みたいな禍々しい外観で激しく警告するような事は必要だと思うし、もっと細かく権限の段階を分けた方が良いと思う。
    • このページは拡張機能の何々によって内容が改変されています、みたいな警告をロケーションバーあたりに表示しておくというのもありかもしれない。
  • 総じて、自己責任で愚行権を行使できる余地は認められていて欲しい。警告も何も読まず、危険な物をホイホイインストールして、重くなったとか不安定になったとか言う、自分がやっている事の意味を自分で分からない・分かろうとしないような人のことまで手厚くケアする必要は無いんじゃないの? そういうのが欲しい人はApple製品を使うのが筋だと思う。技術屋が高級ブランド家電屋になろうというのが無理がある。

という風な事を自分は思っています。

Chrome Extensionsのマニフェストのバージョン3とアメリカの銃規制 - Jan 29, 2019

ちょっと前に話題になったChromeの拡張機能のAPIの新バージョンの案の概要を把握するために、変更点のまとめの部分だけを読んでみた。全訳するのも大変なので、適宜つまみながら。


動機

APIや権限の仕組みに対して大規模な変更を行う物なので、マニフェストバージョンを3に上げる。拡張機能が実際に使用しているAPIや権限の中には、パフォーマンス、セキュリティ、プライバシー、および人間工学的な観点から、ユーザー体験を低下させている物が多数ある。新しいマニフェストバージョンではそういった負の影響を与える要素を一掃し、新しいAPIや機能だけを使えるようにする予定である。拡張機能の作者達に向け、移行を容易にするための明確な手順と、新基準に拡張機能を移行するに足る追加のインセンティブを用意するつもりである。

  • 目標: マニフェストV3では、安全・高速・プライバシーに配慮された拡張機能を容易に開発できるようにし、一方で、危険・低速・プライバシー情報の漏洩に繋がる拡張機能を開発しにくいようにする。拡張機能の品質を高め、ユーザーに積極的に勧めやすいような物にする。
  • セキュリティ: マニフェストV3に基づいて開発される拡張機能は、外部からの攻撃(その拡張機能を狙ってXSSを仕掛けてくるような悪意あるWebサイトなどからの攻撃)と、内部からの攻撃(悪意ある拡張機能)の両方に対して、より強力なセキュリティ機構を保証するのが望ましい。ユーザーは安心して拡張機能をインストールできることが望ましく、そのためには、その拡張機能が重大な損害をもたらし得ない事を保証する必要がある。その結果、自動および手動でのレビューをより容易にする。
  • プライバシー: ユーザーは拡張機能に対してより広範な制御権を持つことが望ましい。ユーザーは各拡張機能に対して、どの個人情報の使用を許可するかを制御できることが望ましい。
  • 性能: マニフェストV3に基づいて開発された拡張機能は、より高速になる事が望ましい。長時間動作するバックグラウンドプロセスは禁止されるべきである。APIは高速・効率的である事が保証されている必要があり、性能を劣化させるような誤った使い方がしにくいようなAPI設計となっていることが望ましい。

変更の概要

優先度1(最高)

  • バックグラウンドプロセスについては、イベントベースの永続的なバックグラウンドページから、Service Workersへ移行する
  • コンテンツのデータへのアクセスの制限については、activeTabスタイルの、実行時にのみアクセスが許可されるモデルへ移行する
  • リモートに置かれたコードについては、直接の実行を禁止する
  • クロスオリジンの通信は、コンテントスクリプトはWebページのスクリプトと同じルールに基づくこととして、拡張機能のページは過去にアクセスしたことがあるサイトに対してはクロスオリジンの通信を可能とする。
  • ホスト単位での権限の指定は、API自体の権限を列挙する permissions 配下でまとめて指定していたのを host_permissions に分離する。
  • PromiseベースのAPIとする

優先度2(高い)

  • Webからアクセスできるリソースについては、拡張機能の実行コンテキストから切り離された安全な領域に登録されたリソースを、動的に生成されるURLで読み込む形とする。
  • 動的なコンテントスクリプトについては、それに特化した権限の仕組みを設ける。

APIの変更

  • webRequest は、リソースの読み込みをブロックする使い方を制限する
  • 代わりに、読み込みブロックのための宣言型の新しい仕組みとして declarativeNetRequest を設ける。
  • ツールバーの動作とページでの動作は、browserActionpageAction を単一の action APIに統合する。
  • chrome://favicon に関する権限をchrome.favicon APIに移す。
  • tabs, pageCapture, tabCaptureおよび desktopCaptureを単一のcapture APIに集約する。
  • オープンなWeb標準で定義された機能はAPIからは削除する。
  • ServiceWorkerベースのAPIへの更新。特に、いわゆるメインスレッドとして走る処理のための物。
  • 公に非推奨・廃止予定とされていたAPIの廃止・削除
  • その他、性能や利便性、人間工学的な観点での細かい修正。

以上、翻訳とメモの中間みたいな物でした。

この中で特に webRequestdeclarativeNetRequest に関わる部分は、chromeの機能拡張の変更について | 280blockerで詳しく解説されている。

コンテンツのデータへのアクセスについて、<all_urls>を廃止して、コンテンツに触れたければ必ずactiveTabの権限の範囲でできる事だけに制限するというのは、かなり息苦しくなるなあという感じがある。例えば複数選択されたタブのそれぞれについてコンテンツの内容を収集してきてクリップボードにコピーする、みたいな事はできなくなるという事だろうか?

Promiseベースにするというのは、FirefoxのWebExtensionsが既にそうなっているし、ChromeのAPIをそのスタイルに合わせるためのPolyfillも既に広く使われているようなので、妥当だと思う。

 

総じて、Chrome開発チームが思う所の「こうあるべき」という思想を前面に押し出した案だなと感じた。元々、Firefoxの拡張機能がXULとXPCOMでなんでもできたのに対して、無害そう・使用頻度が高そうなニーズに応える機能だけ取捨選択してChromeの拡張機能APIとしてまとめたのが、今からほぼ10年前。10年を経てさらに取捨選択を進めると同時に、新たに明らかになってきたリスクを改めて潰し直すというのが、マニフェストV3でやりたい事なんだろう。Googleのやり方を強硬的で独善的だと非難する向きもあるようだけど、それは今に始まった事じゃない「Googleの社風」なんだと思う。

Googleが認めるやり方での広告ブロック以外は認められないという形に結果的になっているのは事実のようだけれど、巷で騒がれている「広告ブロックを禁止するための陰謀だ」みたいな見方は深読みしすぎだと思う。多分Googleの人達はそこまで考えてなくて、彼らはきっと、性能劣化がとにかく嫌で、それに繋がりうる物をなくしたら結果的にこうなった、という事なんだと僕は思ってる。やっかみ混じりで悪意に取ったとしても、せいぜい「は? 俺らが熟慮して『これで充分じゃん』って考えた物なんだから、これで完璧でしょ? 文句の付け所があるわけ?(キョトンとした顔で)」くらいの事なんじゃないかな。

サイドバーAPIを頑なに付けないのも、要はそういう「は? そんなもんいらんやろ? ブラウザは最低限の機能だけでええやん、常時表示するカスタムUIなんて無駄なだけやん(キョトンとした顔で)」みたいな感じなんじゃないのかなと僕は認識してる。僕はツリー型タブを「脳内ワーキングメモリが極めて貧弱な自分でも、Webのブラウズ履歴を視覚的にその場に残して常に全体をざっと眺められるようにできれば、ワーキングメモリの小ささを補って人並みの仕事ができる」という使い方をしてるけれども、優秀なGoogleの人達は(※やっかみ)ワーキングメモリが広大で、そんな風にツールで補う必要がきっと無いから、それで必要性を認めないんだろう、と僕は思ってる。

 

速度以外のセキュリティについても、セキュリティが担保されるなら利便性はどうでもいいというのが彼らの本音であるように思う。いや、セキュリティ第一であるべきというのは一般的にもちろん正しいし、一般ユーザー向けに「セキュリティより自由度を」なんて言ってる人がもしいたら、アホだとは思う。「よく分かってる人・開発者向けにだけ裏道を残しておけばいい」とは言っても、大抵の人は自分が何をしてるか分からないまま自分の足を撃ち抜きがちで、しかもその事に気付いてすらいないものだから、そういう「パワーユーザー向けにだけ解放」が絵空事でしかないというのも分かる。

これって何かに似てるなと思ったら、あれだ、アメリカの銃規制に似てるんだ。アメリカは銃を所持する事が自分の自由を守る事とセットだという建国の精神だから、いくら安全のためとはいっても銃を完全に社会からなくそうとすると強い反発が起こる、っていう。

銃乱射事件が起こる度に出てくる「全米ライフル協会『(被害者が)銃を持っていればこんな事件は防げた』」というジョークを見る度に「アホやなあ」と僕は思っていたけれど、それを笑っていた僕自身もまた、リスクに目を瞑って、危険な武器を自分が手にできる自由を声高に叫んでいた人の1人だったのだな、と。自分自身が「ただのユーザー」から「自分の使う道具を自分で作り替えられる開発者」にステップアップできる余地があったから(他にも理由はあったけど)、僕はMozillaを使っていたし、「Chromeと同じになってしまった」「Mozillaはアドオンを殺した」なんて言われた後の今でもSuccessor Tabs APIコンテキストメニューのコンテキストのオーバーライドのように「安全」とのバランスを取りながら自由度を増す事に寛容な姿勢が垣間見えていて、方向性としてはまだそういう自由度を尊重してくれているように思えるので、それで僕はFirefoxを使い続けてるんだな。自分が独り立ちできた事の根底にあった「建国の精神」とガッチリ結びついてるから、僕は自由度をなるべく捨てたくないんだな。ということを、Chromeの拡張機能マニフェストV3のいざこざを見ていて改めて意識させられた。

 

そういう感じでなんかこうセンスというか目指すところが合わないので、僕は今後も当面Chromeに移ることは無いかなと思っているのでした。

「じゃあサイドバーAPI付きのChromiumベースのブラウザならどうなんよ、Operaとか」っていう疑問も当然浮かぶわけだけれど、ベースになってる物の設計思想が決定的に自分とマッチしてない(と僕は思ってる)以上、その上に組み上げられた物も自分にはマッチしないんじゃないかなあという見方をしてしまうし、それにChromeチームの意向で梯子を外されてOperaも他のChromiumベースの製品もみんなおじゃんになっちゃいましたみたいな未来もあるんじゃないかくらいに悲観的に考えてるので、やっぱりその路線も無しというのが今の自分の考えです。

ツリー型タブでタブの並び順が壊れる問題との格闘 - 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への移行の話をおさらいしてみましょう。

続きを表示する ...

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

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき