JavaScript と iframe で注意点
メインのHTML(親frame)の中に子のiframeをつくるとき、その2つのframeの操作について
ぶっちゃけ、そんな都合のいい話はない、というお話。
SameOriginPolicy (同一ドメインポリシー)
- 操作しようとする2つのwindowやframeのoriginが違う時のポリシー。
- originは、プロトコルxホストxポート の組合せ。
http://sugilog.hatenablog.com/ と、 http://sugilogtest.hatenablog.com/ はoriginが異なる。 http://sugilog.hatenablog.com/ と、 http://hatenablog.com/ はoriginが異なる。 http://sugilog.hatenablog.com/ と、 https://hatenablog.com/ はoriginが異なる。 http://sugilog.hatenablog.com/ と、 http://hatenablog.com:81/ はoriginが異なる。
- SameOriginPolicyに反するときは、以下のような操作ができない。
- 親frameから、iframeのDOMを操作する。またはその逆。
var iframe = parentFrame.frames[0] iframe.document; // この時点でエラー iframe.document.getElementById("hoge"); 上でエラーしてるので、こんなことはできるわけもない。
- 親frameから、iframeの何かしらの情報をみる。またはその逆。
var iframe = parentFrame.frames[0] iframe.location; // この時点ではエラーしない。 iframe.location.href;; // この時点でエラー。
組合せに対する対処
- ホスト、ポートが同一で、プロトコルのみが違う場合は、ちゃんと合わせる。(基本)
- プロトコル、ホストが同一で、ポートのみが違う場合は、なんでわざわざポートを変えるかを再検討。(ケースとしては少ない)
- プロトコル、ポートが同一で、ホストが全く違う場合は、諦める。
サブドメインレベルの違いに対する対応方法
- このあたりに書いてある。 http://stackoverflow.com/questions/1364776/can-i-access-contents-of-an-iframe-from-a-subdomain-if-i-use-www-on-the-main-do
- document.domainは、以下の条件に合致する場合は値をセット出来る(例外が起きない)。
- 現在と全く同じ値(変化しない、というべき)
- サブドメインを取り除いたドメイン。(
sugilog.hatenablog.com => hatenablog.com
)
- これを使って、サブドメインレベルでの違いは、document.domainに値をセットして、クッションさせてSameOriginPolicyを抜ける。
nonsecure content
- SameOriginPolicy がどうしても切り抜けられないとしたら、iframeとその中身を自前でつくる、という方法も取れる。
var iframe = document.createElement("iframe"); document.body.appendChild(iframe); iframe.contentWindow.document.open(); iframe.contentWindow.document.write("<html><head></head><body>TEST</body></html>"); iframe.contentWindow.document.close();
ただし、それをやると、IEに怒られる。(SSLのページの時)
This page contains both secure and nonsecure items
なぜか
- src要素がないから。
- モダンブラウザだと(これは仕様か?)でないが、IE6,7,8だとでる。
- インターネットオプションを変えればでなくもなるが、それはユーザーの対応の話。
副作用もある。
- document.open()は基本的に危険であること。
- まちがえて、参照するwindowが、親frameのwindowになっていた場合、ページ全体が真っ白になる。
じゃあどうするのか?
- iframeを使わないことを考える。 =>
<script>
で必要なデータを読み込む。- SameOriginPolicyあたりの話は、frameやwindowの話で、
<script>
は対象外。 - JSONPとかの話になっていく。
- SameOriginPolicyあたりの話は、frameやwindowの話で、
そもそも論過ぎるが、ブラウザのポリシーの話に立ち入ることになるので、そもそも論で考え直す。
さいごに
というか、2つのドメイン使うことないし、とか、そういうのは、流してください。 自分の中でもレアケースです。