BookmarkletでXMLなエラーページにHTMLを召喚する

始まりは突然に

ブックマークレット。それは他人のサイトに勝手にjsをコンニチワさせる手段。 そんなことして何が嬉しいのか?当然の疑問である。

ここで、条件を追加しよう

  • 君はソフトウェアを配布したい
  • でもホスティングはしたくない。なぜ?そりゃ金の切れ目が縁の切れ目だからさ
  • 外部サーバーと連携したい。外部のデータがないと美味しくないからね

成果物

さあ、ここにBookmarkletがある

togetter.com

  • このBookmarkletCOCOA接触アプリで濃厚接触した情報から接触日がなんとなく分かるツールだ
  • 厚生労働省スマホアプリCOCOA向けにAppleGoogleが作った感染確認者が同意登録したTEKを配布Zipファイルで配布している
  • アプリはこのAzureのBlobストレージからZipファイルをもらってスマホ内に持つRPIキーと秘密の方法で比較する
  • 結果、キーの一致が確認されると接触数をアプリは通知する
  • この時、ファイルのTEKの含まれるハッシュ値アプリから取り出すことが出来る
  • ブックマークレットではzipを取得し、ファイルのsha256のhexを取得し、一致確認をする。

これをアプリでやるのは簡単だ。だが、アプリはストアに登録せねばならない。上納金と真名をストア運営者に払ってだ。 そんな最低なことはしたくないので、Web、自由のフロンティアWeb、FLOSSブラウザでやるのである。 だが、アプリでは簡単な事がセキュリティがオリジン単位に分かれる事で担保されるWebブラウザではなかなか厳しい。 が、乗り越えるたのである。

よってその軌跡をここに記述しておきたい。

リポジトリ

github.com

ここのリポジトリの指示に従ってbookmarkletを発動させれば良い

各種制約
  • ブラウザはクロスオリジンでデータ取得するには取得元がCORSに対応している必要が有る→今回は純粋なBlobストレージなので対応してない
  • ブックマークレットはURLのサイズに規定され、上限が23kbあたりにFirefoxSafariがある。Chromium系はMB級でもOK。なお旧EdgeとIEは2013bである。
  • XML画面のエラー画面はHTMLではないのでそのままではHTML要素を使えない=CSSなし、スタイルなし、scriptタグ、iframeタグも只のタグ
  • Zipを解凍して出てくるファイルはProtocol Bufferなのでバイナリファイル。
機序

次のような機序で動いている

  • 400か404のエラーXML画面を開く※どのAPIサービスにもあるよね!
  • bookmarkletを起動
  • 既存の要素を全部消す。※DOM操作APIは有効
  • HTMLのNameSpaceでhtml要素からhead、body、iframeを作成
  • iframeではブックマークレット配布リポジトリのGithubPagesを開く
  • GithubPagesはブックマークレット展開サイトとpostMessage APIを使って通信※RestAPI的なラッパーを作成
  • ブックマークレットはfetchAPIで同じドメインにあるzipファイルを頂いてくる
  • iframeのpostMessageと組み合わせて、iframe内からは任意のブックマークレット展開先のドメインのファイルを取れるように作っておく。
  • GithubPagesのjsには容量制限はないのでVue.js+vuetifyで作ったWebpackで固めた3MB程度のjsを置く。
  • Zip解凍はzlibjsでできるがWebpackで上手く動かないので別呼び出しとする。
  • Protocol Bufferのライブラリも使って中身を見る。
ナニが画期的なのか

次の点で自由度が確認できたので書いておく

  • XMLなエラーページもHTML要素を召喚できる!
  • iframeの全画面表示で事実上、乗っ取れる
  • postMessageで任意のファイルをCORS有無に関係なくクロスオリジンを気にせず自動で取ってこれる。

目指す地平線

これにWebRTCが加われば、静的ホスティングサービス(GithubPages)があればブラウザと何処へだって行ける! 目指すはスマホを集合させたアプリサーバーに依存しないサービス提供! 金の切れ目が縁の切れ目にならない、誰にも止められない自由を手に入れられる!