最近のChromeはWeb MIDI APIといってMIDIキーボード等の楽器を接続し、その入力が取れる。

Chrome拡張でもそれは使える。
inputタグにフォーカスしている時に楽器からの入力をキャプチャして、パスワードを生成&入力するChrome拡張を作ってみた。

https://github.com/shokai/webmidi-password-generator

パスワードは覚えるのが難しいけど曲のフレーズとかなら覚えやすいだろ、多分・・という気持ちを形にした。

といっても見た目に派手な動きがあるわけじゃなくてUSBコネクタにMIDIデバイス刺して演奏したらいきなりinputタグにパスワードが入力されてる状態になるので、blogで説明は難しい。

こんな感じでMIDIメッセージを受信してパスワードっぽい文字列が生成される。2回演奏して、ちゃんと同じパスワードが出てる。

これの問題はあらかじめパスワードを記憶させておいて取り出せるわけじゃないので、28c813172158みたいな到底覚えられない文字列になってしまう事で、作りながらうすうす気づいてたけどまあ自分でも使う気になれない。ビミョーすぎる。
パスワード覚えなくていいソリューションを作ってもパスワード覚えること前提のサービスやデバイスが世の中にたくさんあるから利便性の面でどうしても無理がある。使うなら完全移行しないとならないのが面倒くさい。

MIDIのメッセージは標準化されているものだから、別のMIDIキーボードと別のPCで同じフレーズを演奏したらちゃんと同じパスワードが入力できる、という点は良いとは思う。


久しぶりにChrome拡張を作ったら簡単だった

なんだか以前作った時より簡単になった気がする。
あまりしっかり差を把握していないんだけど、以前はもっとゴチャゴチャ色々なファイルを作らなければならなかったような。

Chrome拡張が簡単になったというより、browserifyでnpmのライブラリやnode中でpure jsで書かれているライブラリをそのままChrome拡張に持っていけるのですっきりしたのかも。

MIDIデバイスを開いて入力読んで現在ブラウザで開いているHTMLを少し書きなおすぐらいなら、
簡単なmanifest.jsonを書いて、その中で指定したjavascript1つに全部やらせればいい。

ようするにgreasemonkeyでやってたような事はmanifest.jsonとmain.js(と必要であればアイコン画像)さえ配置すればさくっとできる。browserifyのおかげでグローバル汚染せずにjQuery等を持ってくる事もできる。

こんな感じで書いてる。
npmでインストールしたjqueryと、Web MIDI APIからパスワード作って”password”イベントを発火してくれるライブラリをbrowserifyで1ファイルに固める。

main.es6
"use strict";
import PasswordGenerator from "./password_generator";
import $ from "jquery";

var target = null;
$("input")
.on("focus", function(e){
target = e.target;
})
.on("focusout", function(e){
target = null;
});

var passgen = new PasswordGenerator(8);
passgen.on("password", function(pass){
console.log(pass.raw);
console.log(`password => ${pass.string}`);
if(target){
target.value = pass.string;
}
});

Web MIDI APIはインタフェースにPromise、iterator、TypedArrayなどのES6の機能が使われている。ChromeでもES6が動くのでES6でいきなり書けばいいかなと思ったけど、Arrow Function等いくつかのES6の機能が動いたり動かなかったりして混乱したのでbrowserify+babelifyでES5に変換した。


Chrome拡張のインストール

拡張は昔は1ファイルに固めないと動かなかった気がするけど、最近は[ウィンドウ]→[拡張機能]→[パッケージ化されていない拡張機能を読み込む]でディレクトリを指定して読み込んでくれるので手軽。