読者です 読者をやめる 読者になる 読者になる

別ウインドウで表示中の Web ページに対するクロスドメインスクリプト実行

Web ブラウザで別ウインドウ表示中の Web ページ(別ドメイン)のスクリプトを実行する方法を探ってみた。

セキュリティの関係上、Web ブラウザは別ドメインのページに対する DOM アクセスを許可しないため、通常の方法では実現できそうに無いが、セキュリティ設定を甘く(ActiveX コントロールの実行を許可等)した IE では、以下の方法で実施できる事が判明。

  • WSH のシェルオブジェクト "Shell.Application" を使って script 要素を appendChild する

利用条件が限定的なため、あまり使い道は無さそうだが、イントラネット内の Web アプリケーション間の連携などで多少は使えるかと思う。

準備

とりあえず、スクリプト実行側の HTML ファイルを作成し、ローカルファイルを IE で直接開いておく。

file:///d:/cross_domain_script/called_script.html
<html>
<head>
<script type="text/javascript">

    function test() {
        alert("別ウインドウからの実行");
    }

</script>
</head>
<body>
</body>
</html>

クロスドメインスクリプト実行

先ほどとは別の IE を立ち上げ以下のページを表示し(Web サーバー経由で取得)、"call script" ボタンを押下すると、called_script.html 側で test() が実行される。

処理内容は以下。

  1. Shell.Application オブジェクト生成
  2. ウインドウを列挙してスクリプト実行対象の IE を取得
  3. スクリプト実行対象 IE の document.body に script 要素を appendChild
http://localhost:8080/script_call.html
<html>
<head>
<script type="text/javascript">
    function callScript() {
        try {
            var shell = new ActiveXObject("Shell.Application");
            var appList = shell.Windows();

            for (var i = 0; i < appList.Count; i++) {
                var app = appList.item(i);

                //app が取得できない場合があったため、まず app の存在確認
                if (app && 
                    //IE の判定
                    app.FullName.match(/iexplore.exe$/i) && 
                    //スクリプト実行対象ページの判定
                    app.LocationName == "called_script.html") {

                    //スクリプト要素の作成
                    var script = app.document.createElement("script");
                    script.type="text/javascript";
                    //スクリプトの処理内容を設定
                    script.text = "test();";

                    //called_script.html の body に script 要素を追加
                    app.document.body.appendChild(script);
                }
            }
        }
        catch (e) {
            alert(e.message);
        }
    }
</script>
</head>
<body>
<input type="button" onclick="callScript()" value="call script" />
</body>
</html>