🏊♂️
クロスドメインの中にiframeで埋め込んだ同一ドメインにpostMessage()する方法
かなりニッチな状況だが、こんなことがあった。
状況
ドメイン名が異なるサイトを<iframe />で埋め込み、そのサイトのさらに中に同一ドメインを<iframe />で埋め込んだ。親windowと孫windowが同一ドメインで、子ドメインだけ別ドメイン。
やりたいこと
親windowと孫windowとの間で双方向でやり取りがしたい!
通常であればpostMessage()を使う。
問題
だが、問題は子windowがクロスドメインだということ。
クロスドメインだとpostMessage()してもエラーになってしまう。
解決策
色々調べた結果解決策を見つけた!! のでシェア。
孫windowから親windowへのpostMessage()
これはシンプル。
親windowはブラウザのトップに存在しているので指定し易い。
window.top.postMessage({hoge:'hoge'})
親windowから孫windowへのpostMessage()
こちらが厄介だった。
親windowから見て孫windowを取得するにはどうしても別ドメインである子windowを経由するしかないと思っていた。
子windowを介さず、親windowが孫windowを取得する方法。探したらあった。postMessage()を活用する。
ドキュメントをよく読むと、「配信されるイベント」の項目に、配信されたメッセージを取得できると書いてある。
その中のsourceが
メッセージを送った window オブジェクトへの参照。
まさに求めていたもの。
これを用いるとサンプルコードはこうなる。
grandchild.js
window.top.postMessage({messageType:registGrandchildWindow})
parent.js
let grandchildWindow = {}
const onMessage = (event) => {
if (event.origin === location.origin && event.data) {
switch (event.data.messageType) {
case 'registGrandchildWindow':
grandchildWindow = event.source
break
}
}
}
window.addEventListener('message', onMessage, false)
/* 中略 */
grandchildWindow.postMessage({hoge:hoge})
やっていることは以下の通り。
- 孫windowから親windowにpostMessage()
- 受け取ったmessageのsourceから孫windowを取得
- 孫window.postMessage()
if (event.origin === location.origin && event.data) {
ここは今回とは直接関係ないが不正なメッセージを除外するために入れている。
ドキュメントはよく読もう!
Discussion