強火で進め

このブログではプログラム関連の記事を中心に書いてます。

Canvas関連のプログラムをしていたときに発生するセキュリティエラー Security error" code: "1000 の意味


FirefoxCanvasタグに色々と描画をさせるプログラムをしている時に以下の様なエラーが発生しました。

Security error" code: "1000

通常のエラーとは異なり、セキュリティエラーと有ります。しかも、具体的な情報はほぼゼロ。

色々とテストした結果、何とか原因を突き止めました。再現方法以下。

1. JavaScriptが置いて有るドメインとは異なるドメインに有る画像を使って drawImage() でcavasに描画。
2. getImageData() でピクセル情報を取得する。

この 2. を行った瞬間にセキュリティエラーが発生します。

サンプルとして以下の様なプログラムを作成しました。
実際に試すにはこちらのページをFirefoxで開き、Firebugを起動して下さい。

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<script>
function test(test_type) {
	var canvas = document.getElementById("canvas");
	var ctx = canvas.getContext('2d');
	var imgA = document.getElementById("img_a");
	var imgB = document.getElementById("img_b");
	var imgC = document.getElementById("img_c");
	
	ctx.drawImage(imgA, 60, 60);
	ctx.drawImage(imgB, 110, 110);
	if (test_type == 2) {
		ctx.drawImage(imgC, 10, 10);
	}
	var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
	// モノクロ化
	for (var i = 0; i < imageData.width*imageData.height; i++) {
		var r = imageData.data[i * 4 + 0];
		var g = imageData.data[i * 4 + 1];
		var b = imageData.data[i * 4 + 2];
		var gray = r*0.299 + g*0.587 + b*0.114;
		imageData.data[i * 4 + 0] = gray;
		imageData.data[i * 4 + 1] = gray;
		imageData.data[i * 4 + 2] = gray;
	}
	ctx.putImageData(imageData, 0, 0, 10, 10, 10, 10);
}
</script>
</head>
<body style="background: gray">
<input type="button" onClick="test(1)" value="test1">
<input type="button" onClick="test(2)" value="test2">
<canvas style="background: white" id="canvas" width="200" height="200"></canvas>
<img id="img_a" src="a.png">
<img id="img_b" src="b.png">
<img id="img_c" src="http://d.hatena.ne.jp/nakamura001/files/c.png?d=y">
</body>
</html>

drawImage() でcavasに描画、 getImageData() でピクセル情報を取得し、モノクロ化した後に putImageData() でcanvasに出力するプログラムです。

a.png、b.pngはhtmlファイルが有るサーバに有るファイルですがc.pngは別のドメインに有るファイルです。

test1ボタンを押すとa.pngとb.pngを drawImage() した後にモノクロ化します。こちらは問題無く、モノクロ化に成功します。

次にtest2ボタンを押すとFirebugのコンソールにこの様な出力がされました。 getImageData() でセキュリティエラーです。

この状態で再度、test1ボタンを押しても同じくセキュリティエラーとなります。

一度、セキュリティ的に問題となったらもうブラウザをリロードするまでは getImageData() が使えなくなるみたいです。

詳しく調べたらどこかに情報が載ってるんでしょうが恐らくJSONなどと同様にクロスドメインなデータはセキュアなデータとして処理しないというルールなんでしょうね。

画像をそのまま描画するのまでは問題無いがピクセルデータを取り出しての加工はセキュリティ的に問題という判断なのでしょう。

ちなみにCSSでこのエラーが発生した場合はこちらなどが参考になると思います。

(solved) Javascriptのエラー: Security error" code: "1000 | anobota
http://haraita9283.blog98.fc2.com/blog-entry-288.html

Skype Extension for Firefox と Security error" code: "1000 - てっく煮ブログ
http://d.hatena.ne.jp/nitoyon/20091120/extention_vs_my_code

他にはvideoタグでの動画再生時に毎フレーム画像データを getImageData() を使って取得するというプログラムをローカル環境で実行した時にも発生した事があります。この時はサーバに転送してから実行したら発生しなく成りました。こっちのパターンについてはセキュリティエラー扱いに成る理由が全然分かりませんでした(Firefoxのバグかな?)。

(2010/12/07 追記)詳しく調査されてる方がおられました。

こちらのページではブラウザ毎の回避方法を解説されています。

canvas の getImageDataが少しめんどくさい(特にローカルで動かす場合) - 地平線に行く
http://d.hatena.ne.jp/chiheisen/20100815/1281885412

JavaScriptにおけるローカルファイルアクセス権限のポリシー: 雪羽の発火後忘失
http://feather.cocolog-nifty.com/weblog/2010/05/javascript-e781.html