iframe内でGreasemonkeyを実行させない方法
2010/06/16(水) 15:47 Greasemonkey親記事へこのエントリーをはてなブックマークに追加

Greasemonkeyで@includeをhttp://*など広い範囲に指定しているとき、実行されるページにインラインフレーム(iframe)があると、そのiframe内でもGreasemonkeyスクリプトは実行されるのでややこしい事があります。

例えば、iframe pageのページにはiframeが2つあるので、下のようなスクリプトだと3回もlogが表示されるためiframeの存在に気づかないとスクリプトがバグってるのかと誤解します。
// ==UserScript==
// @name           iframe test
// @namespace      http://efcl.info/
// @include        http://*
// ==/UserScript==
GM_log("テスト");
GM_log(location.href); // URLを表示すると意味が分かりやすい。
そのため、iframe内では実行させないようにすると、無駄な気遣いが減って(無駄なスクリプトの実行も)スクリプトの開発が楽になります。
以下がiframe内ではGreasemonkeyスクリプトを実行させない対処を入れたものです。
// ==UserScript==
// @name           iframe test
// @namespace      http://efcl.info/
// @include        http://*
// ==/UserScript==
new function(){
    // iframe内では実行させない
    if (window != unsafeWindow.top) {
        return;
    }
    GM_log("テスト");
    GM_log(location.href);
}()
iframeがクロスドメインのものだとwindow.topでは何か(Security Manager vetoed action)言われるのでunsafeWindowを使っています。
わざわざ無名関数で全体を囲っているのはGreasemonkey スクリプト全体を無名関数で囲う意味でも説明しましたが、いきなりreturnをする事があるのでそうしています。(ただし@unwrapを付けてない場合はあんまり関係ない)
このスクリプトだとiframe pageでGreasemonkeyを実行しても一回だけの表示になると思います。
murky-satyr によるとtry...catchでつぶしてしまった方がunsafeWindowを使わずに済むので安全だそうです。
    try { if(top !== self) throw 0 }catch([]){ return }// iframe内ならreturn
    GM_log("テスト");
iframe内でGreasemonkeyが実行されて困るのはWordpressやDinkypageなどのリッチエディタを使用しているページでGreasemonkeyが勝手に要素を加えるとエディタ内にそれが入ってしまうという問題があるため、必要なもの以外はiframe内で実行させない方がいいです。

名前:  非公開コメント   

  • TB-URL  http://efcl.info/adiary/047/tb/