現在、すべてのホストへのアクセスを可能にするマニフェストを使用して Chrome 拡張機能を開発しています。バックグラウンド スクリプトは、すべてのフレームにコンテンツ スクリプトを挿入します。DOM が読み込まれると、トップ ページ/フレームのコンテンツ スクリプトが DOM ツリーをたどり始めます。Walker が iframe に遭遇すると、その iframe のウィンドウ (おそらくクロスオリジン) に関連付けられた特定のコンテンツ スクリプトにメッセージを送信して作業を開始し、このメッセージにシリアル化されたデータを含める必要があります。親ウィンドウは実行を中断し、子がウォークを完了するのを待ち、シリアル化されたデータとともに完了したことを示すメッセージを送り返します。その後、親はその作業を続行します。この問題に対して 2 つのアプローチを試みました。
frameElement.contentWindow.postMessage
: これはほとんどの場合に機能しますが、常に機能するとは限りません。iframe ウィンドウに関連付けられたコンテンツ スクリプト メッセージ イベント リスナーがメッセージを受信しないことがあります。原因は確認できていませんが、リスナーが を呼び出す前に接続されたリスナーだと思いますevent.stopImmediatePropagation()
。たとえば、yahoo のホームページ ( https://www.yahoo.com ) で、iframe ソースhttps://s.yimg.com/rq/darla/2-9-に関連付けられたコンテンツ スクリプトにメッセージを投稿すると、9/html/r-sf.html、メッセージが受信されません。これは広告関連の iframe です。メッセージのブロックは意図的なものである可能性があります。メッセージが投稿されたときにエラーは発生せず、「*」の targetOrigin を使用しています。chrome.runtime.sendMessage
: バックグラウンド ページにメッセージを送信することはできますが、メッセージをリレーするフレームをバックグラウンド ページに伝える方法がわかりません。親ウィンドウ コンテンツ スクリプトは、DOM ウォークで検出された子フレーム要素に関連付けられたクロム拡張 frameId を認識していません。そのため、バックグラウンド ページにメッセージの送信方法を伝えることができません。
ポイント 2 については、stackoverflow で見つけた 2 つの手法を試しました。
- この質問で説明されている概念の使用: 親ウィンドウで、配列内の iframe の位置を決定
window.frames
し、このインデックスを使用してバックグラウンド ページにメッセージを投稿します。バックグラウンド ページは、メッセージ データ内の目的のインデックスを使用して、すべてのフレームにメッセージをポストします。window.parent.frames 配列内のウィンドウ オブジェクトの位置を検出した iframe のみが、メッセージから受信したインデックスと一致し、そのウォークが続行されます。これは正常に機能しますが、非同期メッセージング プロセス中に配列が変更される可能性がありwindow.frames
ます (メッセージの送信後に iframe が削除されると、インデックス値が目的のフレームと一致しなくなる可能性があります)。 - ポイント 1 のインデックス値の代わりに
frameElement.name
、親ウィンドウで使用します。window.name
同じメッセージング手法を使用して、名前を子 iframe に送信し、その値と比較します。iframe要素の作成時にwindow.name
値を取得すると思います。frameElement.name
ただし、フレーム要素の作成を制御していないため、name 属性は多くの場合空の文字列であり、iframe 要素をウィンドウに一意に一致させることに依存することはできません。
DOM ツリーのウォークで見つかった iframe 要素に関連付けられたコンテンツ スクリプトにメッセージを確実に送信する方法はありますか?