2012年7月20日金曜日

svgとcanvasの連携におけるfirefoxとchromeの非互換性

DOM オブジェクトを Canvas に描画する
https://developer.mozilla.org/ja/HTML/Canvas/Drawing_DOM_objects_into_a_canvas
に記述されている内容について いろいろ考えていたら,外部ドメインの画像の取扱いに伴うセキュリティの確保がfirefoxとchromeとで異なるタイミングで行われているという結論に至ったのでまとめてみよう.

問題となるユースケースは「異なるドメインの画像をcanvas要素に書き込み,その画像を外部に取り出そう」とする場合である.これはパッと見判りにくいが,canvas機能を経由すると,画像を含む様々な情報をひとまとめにして外部に送信可能な状態にできることから,セキュリティ上の懸念が発生する.

このような操作をcanvas要素に対して直接行った場合,origin-cleanフラグにより自動的にtoDataURLやgetImageDataメソッドの利用が不可能となるため先程のような問題は発生しない.

では一旦svgを介した場合はどうか?通常svg文書においては異なるドメインでの画像も自由に挿入・表示することが可能である.従ってsvg文書を画像データとしてcanvas要素に書き込む場合にセキュリティホールになりうるケースが発生する.流れとしてはこうだ.
  1. svg文書に異なるドメインの画像を挿入する.
  2. 上のsvgをimg要素に読み込ませる.
  3. このimg要素をcanvas要素に描画する.
  4. canvas要素からtoDataURLメソッドを実行してpng画像を取得する.
結論から言うと,firefox・chromeのどちらにおいても問題は発生しない.しかしそのアプローチは全く異なる.
  • firefoxの場合
    firefoxではimg要素で読み込まれたsvgは「Secure Animated Mode」として動作する.つまり外部リソースとして判定された画像はそもそもimg要素に表示されないのだ.従って先ほどのフローにおいても目的の画像がカンバスに描画されない以外は特に問題なく処理が完了する.
  • chromeの場合
    chromeの場合img要素で読み込まれたsvgは「Animated Mode」として動作する.従って別のドメインに属する画像もimg要素に描画されることとなる.が,chromeではsvg画像をcanvas要素に描き込んだ場合,(それがどのようなsvgであっても,どこにあっても)origin-cleanフラグがfalseに設定される.従って3までは意図した通り,外部ドメインの画像をカンバスに描画することができるが,最後の画像を抽出する段になってエラーとなる.
  • その他のブラウザ(未調査)
なるほど, 何れにせよ目的は達成されている.先ほどのmozillaの記事ではdataスキームに絡んだchromeの動作のバグじゃないかとも記述されているが,実際にはこのようなケースに対応するための仕様じゃないかと思う.

svgとcanvasを連携させるケースはそれほど存在しないかもしれないが,このような非互換性も存在するためクロスブラウザ環境下では中々実現することが難しいことを憶えておこう.

0 件のコメント:

コメントを投稿