たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。
の動向はもえじら組ブログで。
宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。
以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
会社で新しくWindows 10 PCをメイン環境として使い始めようとしていて、セットアップするのになんやかや詰まったので記録を残しておきます。
何も考えずにMicrosoftアカウントで使い始めると、例えば shimoda.hiroshi
みたいなMicrosoftアカウントだったら C:\Users\shimo
みたいな適当にぶった切られた名前でホームディレクトリができてしまう。C:\Users\piro
みたいに任意の名前のホームディレクトリにするためには、以下の手順を踏まないといけない。
C:\Users\shimo
とか)を管理者権限で削除する。コンピューター名はWindowsの通常使用だと意識する事はあまりなくて、LAN内で参照する時に使う程度だけど、WSLでホスト名として常時目にする事になる。これがランダムっぽい名前だと結構いらつくので、最初に変えておく。(以後はWSLでも勝手にこの情報を参照してくれる)
WSLを有効化してストアからUbuntuをインストールした後にやること。
"source": "Windows.Terminal.Wsl"
をコメントアウトして、代わりに "commandline": "wsl.exe ~ -d Ubuntu"
と書いておく。Windowsのファイルシステム上でWSLのファイルのパーミッションを保存できるようにするために、 sudo vim /etc/wsl.conf
で設定ファイルを開いて以下の内容を保存する。
[automount]
options = "metadata,umask=22,fmask=111"
マウントした既存のファイルや新たに作成したファイルが全部実行権限付きで認識されるとGitを使うのに不便なので、maskを指定して実行権限がつかないようにしておく。
LxssManager
を探し、再起動する。これで、上記の設定が反映される。ln -s /mnt/c/Users/username/Destop ~/Desktop
、ln -s /mnt/c/Users/username/Documents ~/Documents
、ln -s /mnt/c/Users/username/Downloads ~/Downloads
、ln -s /mnt/c/Users/Public ~/Public
などとして、WSLでよく使うWindowsのフォルダにシンボリックリンクを作っておく。シェルでよく使う基本の設定をする。
~/.bashrc
に以下の内容を加えて、コマンド履歴の逆方向検索に Ctrl-S を使えるようにする。
stty stop undef
stty start undef
~/.bashrc
に以下の内容を加えて、複数のシェルでコマンド履歴を共有するようにする。
function share_history {
history -a
tac ~/.bash_history | awk '!a[$0]++' | tac > ~/.bash_history.tmp
[ -f ~/.bash_history.tmp ] && mv ~/.bash_history{.tmp,} && history -c && history -r
}
PROMPT_COMMAND='share_history'
shopt -u histappend
export HISTSIZE=99999
~/.bashrc
に以下の内容を加えて、よく使うエイリアスを使えるようにする。
export LESS='--no-init --RAW-CONTROL-CHARS --LONG-PROMPT --shift 4'
alias grep!='grep --color=always'
alias jq!='jq --color-output'
alias cd='pushd > /dev/null'
SSHの秘密鍵を設置して、他のホストにSSHで接続できるようにする。 基本方針として、WSLのsshクライアントから直接秘密鍵を触らずに、Windows 10に最初から入ってるOpenSSHのssh-agentに鍵を読み込ませて、必ずrupor-github/wsl-ssh-agent経由で利用することにする。
C:\Program Files (x86)\wsl-ssh-agent\
あたりに置く。wsl-ssh-agent-gui.exe
へのショートカットを C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
(全ユーザー向けの場合)か、%AppData%\Microsoft\Windows\Start Menu\Programs\Startup
(自分のみの場合。Win-Rで shell:startup
を実行して開かれるスタートアップフォルダ)に作る。-socket "%temp%\ssh-agent.sock"
と起動オプションを付け足す。これで、毎回起動時にssh-agentのためのソケットが作られるようになる。wsl-ssh-agent-gui.exe
が起動していないので、ショートカットをダブルクリックして起動する。~/.bashrc
に export SSH_AUTH_SOCK=/mnt/c/Users/$USER/AppData/Local/Temp/ssh-agent.sock
という行を足す。これで、WSLの環境に入ると自動的にWindows側のssh-agentと繋がるようになる。source ~/.bashrc
を実行して設定を反映する。~/.ssh
(秘密鍵、公開鍵、設定ファイル)を持ってくる。chmod 700 ~/.ssh
で、ディレクトリのパーミッションを他のユーザーから参照不可能なようにする。ssh-add ~/.ssh/(秘密鍵)
を実行し、秘密鍵を ssh-agent に読み込ませる。(以下は、Windows 10のOpenSSHを使うようになるまで使ってた、PuTTYのPageantに鍵を読み込ませて、必ずweasel-pageant経由で利用する場合の手順。歴史的資料として残す。
C:\Users\username\.ssh
(/mnt/c/Users/username/.ssh
)を作成し、旧環境からファイルをコピーする。puttygen.exe
で秘密鍵のid_rsa
をインポートして、PuTTY形式の秘密鍵 id_rsa.ppk
として保存する。shell:startup
を実行してスタートアップフォルダを開き、pageant.exe
のショートカットを作成する。pageant.exe
を起動して、先の id_rsa.ppk
を読み込ませる。C:\Program Files (x86)\wsl-pageant
に置く。chmod +x /mnt/c/Program\ Files\ \(x86\)/weasel-pageant/weasel-pageant /mnt/c/Program\ Files\ \(x86\)/weasel-pageant/helper.exe
で明示的に実行権限を設定する。echo 'eval $(/mnt/c/Program\ Files\ \(x86\)/weasel-pageant/weasel-pageant -r)' >> ~/.bashrc
で、weasel-pageantを自動起動するようにする。(weasel-pageantにどのようなオプションを設定するべきかについては、必ず最新の解説を参照すること。)mkdir ~/.ssh; chmod 700 ~/.ssh
で、設定ファイル等の置き場所を用意する。
ln -s /mnt/c/Users/username/.ssh ~/.ssh
でシンボリックリンクとして作成してしまうと、次項の設定をしてもSSH接続を受け付けられなくなってしまう(~/.ssh
のパーミッションを適切に設定できなくなる)ので、必ずここは普通のディレクトリとして作成しておく。)
openssh-server
が最初から入っているので、後は必要な設定をするだけで使える。
/mnt/c/Users/username/.ssh/
以下に公開鍵等もコピーできているはずなので、/mnt/c/Users/username/.ssh/authorized_keys
があるのであれば ~/.ssh/authorized_keys
にコピーする。なければ、/mnt/c/Users/username/.ssh/id_rsa.pub
を ~/.ssh/authorized_keys
にコピーする。chmod 600 ~/.ssh/authorized_keys
として、パーミッションを適切に設定する。sudo service ssh start
してsshdを起動する。ssh localhost
でログインできることを確認する。sudo service ssh stop
してsshdを停止する。(以後は、必要な時にだけ起動する)mkdir -p ~/local/bin
で、ユーザー固有のバイナリ置き場を用意する。echo 'export PATH="~/local/bin:$PATH"' >> ~/.bashrc
してパスを通しておく。peco_linux_amd64.tar.gz
を使った)。unar peco_linux_amd64.tar.gz
でファイルを展開する。peco
を ~/local/bin/
に移動し、chmod +x ~/local/bin/peck
で実行権限を設定する。echo 'source ~/peco-commands.sh' >> ~/.bashrc
で自動的に読み込むように設定する。bash-git-promptを使うようにする。
cd ~/
して git clone https://github.com/magicmonty/bash-git-prompt.git ~/.bash-git-prompt --depth=1
で必要なファイルをローカルに用意する。以下の内容を ~/.bashrc
に追加して、機能を有効化する。
GIT_PROMPT_ONLY_IN_REPO=1
source ~/.bash-git-prompt/gitprompt.sh
GIT_PROMPT_THEME=Single_line_Ubuntu
時刻表示の部分が余計なので、以下のように編集する。
diff --git a/themes/Single_line_Ubuntu.bgptheme b/themes/Single_line_Ubuntu.bgptheme
index 7dd3a4f..542b259 100644
--- a/themes/Single_line_Ubuntu.bgptheme
+++ b/themes/Single_line_Ubuntu.bgptheme
@@ -15,7 +15,7 @@ override_git_prompt_colors() {
GIT_PROMPT_COMMAND_OK="${Green}✔ "
GIT_PROMPT_COMMAND_FAIL="${Red}✘ "
- GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${White}${Time12a}${ResetColor} ${Cyan}${PathShort}${ResetColor}"
- GIT_PROMPT_END_USER="${ResetColor} $ "
- GIT_PROMPT_END_ROOT="${BoldRed} # "
+ GIT_PROMPT_START_USER="${Cyan}${PathShort}${ResetColor}"
+ GIT_PROMPT_END_USER="${ResetColor}\$ "
+ GIT_PROMPT_END_ROOT="${BoldRed}# "
sudo update-alternatives --config editor
でデフォルトのエディタをvim.basic
に切り替えておく。ここまででWSL上のrsyncが使えるようになっているので、旧環境から rsync -a xxx.xxx.xxx.xxx:~/path/to/directory/ ~/Public/
みたいにしてパーミッションの情報込みでファイルを持ってこれる。
(シンボリックリンクまで勝手に辿らせると大変なことになりかねないので、シンボリックリンクの先は個別に辿るのがよい気がする。)
今回は移行元がハードウェア上にインストールされたUbuntuだったけれども、移行元がWindows 10マシンの場合も上記の要領であらかじめsshdを起動しておけば、同様にrsyncでファイルを持ってこれる。
最近のMozillaBuildとmozilla-centralはよくできてて、だいたい一発で環境ができあがる。以下、前半は会社のブログに書いた手順の通り。
c:\mozilla-build
にインストールする。C:\mozilla-source
の位置にフォルダを作る。Firefoxのソースコード一式はこの配下に置く事になる。c:\mozilla-build\start-shell.bat
を実行して、MozillaBuildのシェル(Bash)を起動する。echo 'export PATH=$PATH:~/.cargo/bin' >> ~/.bash_profile
を実行して、MozillaBuildのシェルを一旦終了し、c:\mozilla-build\start-shell.bat
で起動し直す。cd /c/mozilla-source
して、 hg clone https://hg.mozilla.org/mozilla-central
でmozilla-centralをcloneする。cd mozilla-central
してリポジトリに入り、./mach bootstrap
を実行する。これにより、Visual StudioやRustなどのビルドに必要なソフトウェア群が自動インストールされる。./mach build
して、ビルドできる事を確認する。./mach run
して、ビルドしたFirefoxを起動できる事を確認する。WSLとホームを共用してない関係でBashの設定が素のままなので、~/.bash_profile
に以下を追記する。
# Ctrl-Sで履歴を逆検索できるようにする
stty stop undef
stty start undef
# MozillaBuildの環境にはtacが無いので、関数で代用する
function tac {
exec sed '1!G;h;$!d' ${@+"$@"}
}
# 複数のシェルで履歴を共有する
function share_history {
history -a
tac ~/.bash_history | awk '!a[$0]++' | tac > ~/.bash_history.tmp
[ -f ~/.bash_history.tmp ] && mv ~/.bash_history{.tmp,} && history -c && history -r
}
PROMPT_COMMAND='share_history'
shopt -u histappend
export HISTSIZE=99999
Mozillaのサーバーに認証を求める時のユーザー名指定を省略できるようにするために、~/.ssh/config
に以下を追記する。
Host hg.mozilla.org
User yuki@clear-code.com
ssh hg.mozilla.org
してみて、認証できるかを確認する。(シェルには入れないでそのまま接続が切れるが、それでOK。)
tryserverを使うために、~/.hgrc
に以下を追記する。
[paths]
try = ssh://hg.mozilla.org/try
./mach try empty
で空のリクエストを送れるかどうか確認する。
hg grepfile
でワーキングコピーのファイルを対象に検索できるようにするために、hg-grepfileをインストールする。最近までWindows 10標準で仮想デスクトップ機能があるということを把握してませんでした。今回調べて初めて知りました。
Ubuntuではメインの作業画面とThunderbirdを使う(メールを読み書きする)画面とを分けていて、画面の端にカーソルでちょいっと触れると仮想デスクトップ切り替えの画面が出てくるようになってたんだけど、そういう事をできるようにするにはユーティリティが必要。タスクビューの切り替え画面を出すこと自体は、Windowsキー+Tabでできるので、任意のジェスチャでこのキー操作を代替すればよい。
マウスジェスチャーソフトの「MouseGestureL.ahk」でマウスホイールにWindows10の「タスクビュー」を割り当てる | PC ウェブログという記事を参考に、以下のようにした。
C:\Program Files
配下あたりに適当に置く。Setup.vbs
を実行する。screen-edge
CRB_
(画面右下角に接触)CLB_
(画面左下角に接触)screen-edge
以外すべて削除する。screen-edge
のアクションスクリプトを以下の通りに書く。
;キー操作を発生させる
Send, #{TAB down}{TAB up}
「その他」タブに切り替えて、「スタートアップに登録」で自動起動するようにする。
これで、画面の端に触れるだけで仮想デスクトップを切り替えられるようになる。
2020年5月1日追記。初期設定ではRB
(右ボタン)で始まるジェスチャがいくつか定義されてるんだけど、これがあると、Windows全体で右ボタンの動作に影響が及んでしまう。具体的には、window.addEventListener('mousedown', ...)
みたいな方法でマウスのボタンが押し下げられたことを検知しようとしても、右ボタンだけmousedownが取れなくなる(ボタンを放したときに初めてmousedownが発火するようになる)。自分はscreen-edge
をトリガーにした操作しか使わないので、RB
で始まるジェスチャは全部削除した。
Ubuntuではテキストを選択すると通常のクリップボードとは別の専用のバッファにテキストが格納されてミドルクリックで貼り付けるという動作になってた(これ自体はXの機能とのこと)んだけど、GNOME Terminal(端末)でコピー&ペーストのキーバインドが他のGUIアプリと違っていたこともあって自分でも驚くくらいに意外と多用していて、Windows環境でWSLを使っているとそのときの感覚が抜けなくてつい戸惑ってしまう。
代わりになりそうなものを探してみたらいくつか情報が見つかったんだけど、どれも今使うにはちょっと厳しい感じだった。
もうちょっと悪あがきしてみようと思って「Windows selection auto copy」という感じのキーワードで検索してみたら、AutoHotKey用のスクリプトの例が出てきた。自分は結局AutoHotKeyは入れずにMouseGestureL.ahkだけで使ってるんだけど、これの実態がほぼ同じ物のようで、MouseGestureL.ahkのインストール先にあるMG_User.ahk
のユーザー定義サブルーチンの所に以下のスクリプトを追加してMouseGestureL.ahkを再起動したら普通に使えた。
ただ、Ubuntuの時と違って専用のバッファが使われる訳ではないから、選択→Ctrl-Cでコピー→貼り付けたい箇所にある邪魔なテキストを選択→Ctrl-V という事をしようとすると、貼り付け先の邪魔なテキストの方がクリップボードに入ってしまうという難点があった。なので解説を見ながら試行錯誤して、クリップボードとは別のバッファを持つようなスクリプトを作ってみた。MouseGestureL.ahk単体版ではなくAutoHotKeyの方を使う場合は、上記の内容をSelectionClipboard.ahk
という名前で保存し、ファイル名を指定して実行→shell:startup
で開かれるスタートアップフォルダの中に置けばいいみたい。
で、しばらく試してみてたんだけど、以下の問題をどうしても解決できなかった。
Ctrl-Cでクリップボードへのコピーを試行するのが元凶なので、それ無しで選択範囲のテキストを取得できる方法があればいいんだけど、それはエディットコントロールに対してのみ動作する関数しか用意されてなくて、オフィシャルのサンプルの時点で「標準のエディットコントロール以外でも使えるのはCtrl-Cを使う方法だ」と紹介されてるレベルだったので、AutoHotKeyの制限事項としてどうにもならないというのが結論のようです。残念。
これ機能として欲しくなることが無くてまず誤爆で困るばかりなんですけど?
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
にDisallowShaking
というDWORDの値を作ってデータを1
にすると、この機能が無効化されるそうです。
そんなに頻繁にやるわけじゃなくて、数年に1回やる程度なので、
という風に思ってます。
毎月やるとか、まとめて10台くらいやるとか、そういう前提が出てきたら重い腰を上げてPowerShell覚えるかもしれないですね。
まだ後から書き足しそう。
(後日談:これとは別のPCについて行った、Bash on Ubuntu on WindowsからストアアプリのUbuntuへの環境引き継ぎの話。ここに書いた話を一部参照した。)
これはただの苦労話です。
2月末から3月末までをかけて、長らく懸案事項となっていたツリー型タブ(Tree Style Tab、TST)の大規模改修をやりました。具体的な変更の量としては、改修に取りかかる前の2.7.22からの差分 git diff 2.7.22
で約1MBありました。見た目は変えなかったのであまり代わり映えしませんし、挙動を決定づけるロジックもほぼそのままなのですが、それらが乗っかる基盤にあたる部分が入れ替わった感じです。
何を改修したのか、どういう成果があったのか、という事を説明するために、TSTのこれまでの歴史を振り返ってみます。WebExtensionsに移行した時の話ではあまり触れなかった、細かい実装の話が多めですが、誰の役に立つかは分かりません。
今やHDDより頑丈な「SSDの寿命」と耐久性の凄さ | ちもろぐを読んで「TBW」という指標の存在を初めて知り、自分が今使っている機材の寿命を知りたくなったので計算してみた。
現行機材にはSSDが2つマウントされてる。1つはシステムとデータが両方入ってるSamsung SSD 930 EVO 500GBで、公称値は200TBW。もう1つは仮想マシン置き場にしているSamsung SSD 680 EVO 250GBで、公称値は150TBW。CrystalDiskInfoで総書き込み量と使用時間を調べて計算したら、前者はだいたい残り2年9ヵ月の命、後者は使用頻度が低いせいで残り654年の命と出た。後者はともかく前者は機材更新に備えておかないといけない……
メーカー公称値のTBWとCrystalDiskInfoで表示される数字からの計算が面倒だったので、フォームを埋めるだけで計算してくれるような物を用意してみました。
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に気に入らないところがあってイラッてなったときに自分で手を動かして解決したい人」という立場から「こうだったらいいのに」という事を書き留めておきますと、
という風な事を自分は思っています。
ちょっと前に話題になったChromeの拡張機能のAPIの新バージョンの案の概要を把握するために、変更点のまとめの部分だけを読んでみた。全訳するのも大変なので、適宜つまみながら。
APIや権限の仕組みに対して大規模な変更を行う物なので、マニフェストバージョンを3に上げる。拡張機能が実際に使用しているAPIや権限の中には、パフォーマンス、セキュリティ、プライバシー、および人間工学的な観点から、ユーザー体験を低下させている物が多数ある。新しいマニフェストバージョンではそういった負の影響を与える要素を一掃し、新しいAPIや機能だけを使えるようにする予定である。拡張機能の作者達に向け、移行を容易にするための明確な手順と、新基準に拡張機能を移行するに足る追加のインセンティブを用意するつもりである。
activeTab
スタイルの、実行時にのみアクセスが許可されるモデルへ移行する。permissions
配下でまとめて指定していたのを host_permissions
に分離する。webRequest
は、リソースの読み込みをブロックする使い方を制限する。declarativeNetRequest
を設ける。browserAction
と pageAction
を単一の action
APIに統合する。chrome://favicon
に関する権限をchrome.favicon
APIに移す。tabs
, pageCapture
, tabCapture
および desktopCapture
を単一のcapture
APIに集約する。以上、翻訳とメモの中間みたいな物でした。
この中で特に webRequest
と declarativeNetRequest
に関わる部分は、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ベースの製品もみんなおじゃんになっちゃいましたみたいな未来もあるんじゃないかくらいに悲観的に考えてるので、やっぱりその路線も無しというのが今の自分の考えです。
ただの苦労話です。
ツリー型タブをWebExtensionsに移行してからこっち、ずーーーーーっと悩まされてる事がある。それは、TSTのサイドバー上のタブとFirefox本体のタブの並び順が一致しなくなる事があるという問題。
何故そういう事が起こるのかというと、色々な背景があるのですが……
tabs.onMoved
で通知されるのを待って、通知された情報に基づいてツリーを更新するということを考えていた。runtime.sendMessage()
でタブの移動を行う指示をバックグラウンドページとサイドバーの間でやり取りして、イベントの通知を待たずに先にツリーだけ更新するようにした。で、タブを一つ一つゆっくり操作している場面(僕の普段の使い方)ではこれで問題無かったんですが、このやり方には、リンクからタブをまとめて開くとかブックマークレットを使うとかしてTSTのあずかり知らぬ所で複数のタブが一気に開かれた場合に、TSTのツリーとFirefoxのタブの順番の同期が崩れやすくなってしまうという、大きな大きな副作用がありました。
tabs.onCreated
やtabs.onMoved
などのイベントがそれぞれ非同期で送られてくる。こういった感じでもうシッチャカメッチャカで、こんな状況の中でタブの並び順やら存在確認やらを厳密に把握して破綻の無いように管理するなんて、どだい無理なわけです……全部のイベントをキューに積んでシーケンシャルに処理していけば安定はするだろうけど、そうしたら死ぬほど遅くなるだろうし。いまですら遅い遅いと言われているのに、これ以上遅くなったらどうなることか、考えるだけでもそら恐ろしい。
それでも何もしないわけにはいかないので、とりあえず、挿入中のタブがある時は最低限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
(置き換え)という形で最小の編集手順を導き出してくれました。タブの並べ替えでは「タブがなくなる」という事は前提としてあり得ないため、insert
とreplace
のうち挿入箇所にあたる部分だけを編集情報として使っています。これのお陰で、いままでは無駄に何度もタブを行ったり来たりさせていたのが、場合によってははるかに高速に並べ替えが完了するようになってくれました。
レガシーなやり方を捨ててモダンな仮想DOMへの移行のきっかけになるはずが、何だかんだで結局、部分的にとはいえ似たような事を自前でやるようにしてしまったということで、なんだかなあ……と頭を抱えているのが「今ココ」ということで、特にオチはありません。
(まあ、仮に仮想DOMに全面的に設計を刷新したとしても、tabs.move()
でFirefoxのタブの並び順を制御する部分はきっとそのまま使い続ける事ができそうではあるので、今回やった事も完全に無駄というわけではないかな、と……)
MicrosoftがEdgeの次期バージョンをChromiumベースにすると正式に発表した事を受けて発表されたMozillaの声明文について、自分が風邪やら何やらでゲンナリしている間にGoodbye, EdgeHTML (日本語訳) - Qiitaという訳が既に出ていたので激しく今更なのですが、自分でもえっちらおっちら訳してみたので、せっかくだから置いておきます。
さようなら、EdgeHTML
Microsoftは公式に、インターネット用の独立した共有のプラットフォームの維持を断念しました。Chromiumの採用により、Microsoftはオンライン生活の支配権をより一層Googleに譲り渡します。
これは実利と無関係の情緒的な話のように聞こえるかもしれませんが、そうではありません。「ブラウザエンジン」――GoogleのChromiumとMozillaのGecko Quantum――は、私達がオンラインで何をできるかの大部分を実質的に決定づける開発者向けのソフトウェア部品です。それらは、私達が消費者として目にする物、私達がコンテンツを見る時の安全性、Webサイトやサービスが私達に対して行う事(訳注:位置情報の取得、デスクトップ通知の表示、などの事か)をどれだけ制御できるかといった、基本的な能力を決定づけます。Microsoftの決定は、私達ユーザー個々人に何ができるかという事をベンダ側で一方的に決定してしまえる能力を、Googleに対してより多く与えるものです。
ビジネスの観点から、Microsoftの決定は充分に納得のいく物と言えます。Googleは私達のオンライン生活の基盤のコントロールをほぼ完全に握っており、この分野でGoogleに競合し続ける事はビジネス上有益ではないでしょう。私達に一度は与えられた自由と選択肢の提供を諦めたとしても、Microsoftの株主達の利益は保たれるでしょう。Googleは非常に多才なスタッフを雇用しユニークな資産を独占する、すさまじい競合相手です。Googleの検索・広告・スマートフォン・そしてデータ収集における横断的な支配力は、彼ら以外の残りのプレイヤーに対して大きく傾斜した、Google有利のプレイフィールドをもたらしています。
社会的、市民的、そして個人的な権利の観点から、基本的なオンラインの基盤のコントロールをたった1つの企業に譲り渡す事は、恐ろしい事です。これが、なぜMozillaが存在するかという理由です。私達は、ビジネス上の好機があるからGoogleに競合するのではありません。インターネットとオンライン生活の健全性というものが、競争と選択に依存するからです。それらは、一般の消費者自身がより良い物を求めて行動を起こす事を自己決定できる、という事に依存しています。
Microsoftの決定はFirefoxの繁栄をより困難にするでしょうか? おそらく、そうでしょう。Googleをより強力にする事は、様々な面で危険です。そしてその答えの大部分は、サービス・Webサイトを作ろうとするWeb開発者や業界・企業が何をするかに依存します。もしChromiumのような1つの製品が充分なマーケットシェアを持っているなら、Web開発者や業界・企業にとって、サービスやWebサイトがChromium以外のブラウザで動作するかどうか気にかけないでいる事が容易になるでしょう。それは、Firefoxがリリースされるより以前の、Microsoftが2000年代初頭にブラウザのシェアで寡占状態にあった時に起こった事です。そして、それはまた起こるでしょう。
もし<ruby>今日<rt>こんにち</rt></ruby>のオンライン生活で何が起こっているか気になるのであれば、Firefoxにも注意を払って下さい。Firefoxは18ヶ月前よりも劇的に改善されています――Firefoxは速度とパフォーマンスの点で再び引けを取らなくなっています。1週間ほど既定のブラウザとしてFirefoxを試してみて下さい、そしてそれから判断して下さい。Firefoxを強くする事がオンライン生活の問題のすべてを解決する訳ではありません――ブラウザは様々な要素の中のごく一部に過ぎません。しかし、もしFirefoxがあなたにとって良い製品だと気付いたら、あなたがFirefoxを使う事がFirefoxを強くします。あなたがFirefoxを使う事は、Web開発者と業界・企業がChrome以外の事を考える事を手助けします。そしてそれはFirefoxとMozillaがインターネット上の生活をより良くする手助けとなります――より多くの選択肢、より多くのセキュリティの選択肢、より多くの競争によって。
参考までに、本件についての日本語で書かれた記事へのリンクもいくつか示しておきます。
ロストテクノロジーAdvent Calendar要にXULRunnerの話を書いた直後に、Gecko自体ロストテクノロジーになっちゃうねこれっていう感じの発表があったというのは、何とも皮肉な話です。
ロストテクノロジーAdvent Calendar 5日目に予告無しで飛び入り参加のPiroと申します。
アンテナの高い皆さんにとって、開発環境の重要なファクターであるテキストエディタの最低ラインはATOMかVisualStudio Codeでしょうか。では、これらがElectronというChromiumベースの実行環境上で動作するHTML/CSS/JavaScriptで書かれたアプリであるという話を聞いたことはないでしょうか。
Webベースの技術で実用的なローカルアプリを作れるなんて素晴らしい! そこに目をつけるとはさすがGutHub! と思いますか? しかし実際の所は、そういう試み自体は過去から何度もあったのです。WebkitベースでFlashも取り入れて当時のWebのリッチな体験をそのままローカルに持ってこようとしたAdobe AIR、HTMLとJScript/VBScriptのミックスでWindowsローカルアプリを作ろうとしたHTML Application(.hta)。この記事で語るXULRunnerも、そんな試みの中の一つです。
By the fixed bug 1500479, following new features become available on Firefox 65 and later.
previousTabId
for activeInfo
object notified to listeners of tabs.onActivated
.successorTabId
for tabs returned by tabs.get()
, tabs.query()
, and other APIs.
tabs.update()
.tabs.onUpdated
, and there is no alternative listening API like tabs.onHighlighted
.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.
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経由でこの挙動に介入する方法がなかったため、例えば「タブを閉じたら、必ずそのタブの直前に見ていたタブにフォーカスを移す」というような事をアドオンで実現しようとすると、
という手順を踏む必要がありました。これは見た目に美しくない(一瞬無関係のタブがフォーカスされてしまう)のもさることながら、現在のFirefoxの初期設定である「Ctrl-Tab/Ctrl-Shift-Tabで最近フォーカスされた順にタブのフォーカスを切り替える」という挙動にも悪影響を与えます。
拙作アドオンのツリー型タブも、ツリーの最後の子を閉じたら、右隣のタブ(=下にある別のツリーの親タブ)ではなく1つ前の兄弟タブまたは親タブにフォーカスを移すという機能があり、これを実現するにあたっては前述の点がずっと未解決のままでした。今回のAPI追加によって、ようやくこの問題を解決する目処が立ったと言えそうです。