OperaなどのXMLを使用したサブドメインでのクロスドメインスクリプティング機能

最近、ユーザースクリプト(Firefox、Chrome、Operaブラウザー)の作成作業が行われました。このスクリプトでは、レベル3ドメインからシニアレベル2ドメインにあるXMLドキュメントにアクセスする必要があります。 この作業により、ブラウザの動作、特にOperaの動作のいくつかの機能が明らかになり、その理由は完全には理解されていません。 ただし、このようなスクリプト(サブドメイン内のXMLドキュメントの読み取りと書き込み)が必要になる場合があるため、実用的な結果を共有し、未解決の質問を示したいと思います。



タスク条件。



非厳密なDoctype(過渡的)を持つHTMLページがあり、XMLからデータを受信する必要があります。さらに、XHTMLであるかのようにスクリプトを変更して書き込むことはできません。 たとえば、XMLを実装してもHTMLページを変更することはできませんが、すべてのアクションは、オンロード時に起動されるユーザースクリプトによってのみ管理します。 最初に考えたのは、XMLHttpRequestを使用し、必要に応じてDOMを再構築する古典的なタスクである、単純なものは何もないことです。



はい、XMLが同じドメインにある場合、これ以上簡単なことはありません。 しかし、ドメインは異なるため、ここでのAJAXリクエストは可能ですが、難しい冗長な方法で:1)既存の単純なHTMLをサブドメインからフレームに読み込み、2)AJAXスクリプトをスクリプトに入力、3)AJAXでXMLを読み込み、4 )受信したサブドメインからスクリプトを読み取ります。 単一のXMLフレームで1回の読み取りで対応できるのに、なぜ2回読み取りを行うのですか? コードをフレームにロードする必要はなく、読むだけでも簡単です。 したがって、複雑なメソッドに付随するメソッドとしてAJAXを除外し、シンプルにするようにします。



ご存じのように、サブドメインのJSデータとDOMドキュメントの読み取りは、最上位ドメインに等しいサブドメインのdocument.domainを指定することで実行できます。



document .domain = '.' ;





実際、FFとChromeでは、このスキームでの作業には特殊性がなく、それについて書くことはできませんが、Operaでは奇妙な未解決の問題がありました(おそらくXMLから?)それは単にバイパスされましたが、実験的に観察されています それらとFirefoxのいくつかの副作用について-この記事。



スクリプトはカスタムであるため、IEは調査で何の関係もありませんでした。



スクリプトの実例は、 Firefox + GreeaseMonkey、Chrome、またはOperaで表示でき、記事 (最新バージョン1.3)で説明されているスクリプトをインストールできます。



スクリプトのプロセス。



本質だけについて話します-クロスドメインアクセスの問題に関連するスクリプトのその部分について。



XMLHttpでAJAXを完全に放棄したため、XMLをロードするフレームを作成する必要があります。



if (! document .getElementsByName( 'ifr' ).length){ //

var ifr= document .createElement( 'iframe' );

ifr.setAttribute( 'name' , 'ifr' );

ifr.src = 'http://habrahabr.ru/api/profile/' +username+ '/' ;

ifr.style.display= 'none' ;

document .body.appendChild(ifr);

}






XMLの構造は次のとおりです。



<? xml version ="1.0" ? >

< habrauser >

< login > spmbt </ login >

< karma > 24 </ karma >

< rating > 59.3 </ rating >

< ratingPosition > 1038 </ ratingPosition >

</ habrauser >






次に、外部フレームでonloadイベントをキャッチできないため、XML構造を読み取るための定期的な試行のカウンターをオンにします。 (実際には、Operaではコードと説明が低くなる可能性がありますが、読み取りテストではさらに悪い結果が得られました。



win.habrKarmView.ii=20; //

win.habrKarmView.ww = setInterval(showValue, 300);






ここから楽しみが始まります。 まず、エラーが発生しないようにするには、ツリーをサッパーとして段階的に確認する必要があります(もちろん、 try-catchでエラーをキャッチできます)。



var f = document .getElementsByName( 'ifr' );

if (f && f[0] && f[0].contentDocument && f[0].contentDocument.getElementsByTagName( 'login' )

&& f[0].contentDocument.getElementsByTagName( 'login' )[0]

&& f[0].contentDocument.getElementsByTagName( 'karma' )[0]){

if ( (f[0].contentDocument.u == username || !f[0].contentDocument.u) && self.opera

|| !self.opera && f[0].contentDocument.getElementsByTagName( 'login' )[0].childNodes[0].nodeValue == username ){

... showValue - XML ...

}

}






2番目のifステートメントで 、「Opera」部分と非Opera部分を分離する必要があったのはなぜですか? Operaでは、変数uをXMLドキュメントに書き込むことができたためです。



if (self.opera) document .getElementsByName( 'ifr' )[0].contentDocument.u = username;





FFはこれを行うことができませんでした(理由- 質問は開いています )が、条件の2番目の部分があるため、本当にしたくありませんでした。 Operaの問題は何ですか?



問題( 2番目の質問 )は奇妙で説明が不十分でした。 事前に書かれたのではなく、ノードによって、2番目の方法でログインを読み取ろうとして、ログインgetElementsByTagName( 'login')[0]を持つノードの存在を取得しましたが、.childNodesの欠如-ログインのテキストを取得しました。 つまり XMLが次の形式であるかのように



< habrauser >

< login />

< karma > 24 </ karma >

< rating > 59.3 </ rating >

< ratingPosition > 1038 </ ratingPosition >

</ habrauser >






getElementsByTagName( 'habrauser')[0] .childNodes [1]([1]-改行の場所にテキストノードがあるため)の読み取りのような遅延もダンスも役に立たなかった。 <login />はOperaの観点からは空のように見えました。 2番目の未解決の質問はなぜですか。 (フレームでは、空ではなく、ifr.style.display = 'none';と書いていない場合に見られました。)



最初のノードの振る舞いは理解できないにもかかわらず、Operaのスクリプトはこの形式のままにしておく必要がありました-実行可能な代替案の偶然の一致により、ドキュメント内のu変数がまだあります。 しかし、一般的な用語での解決策は、 <karma>が最初にあった場合、Operaにとって不可能なタスクになります(この方法で解決した場合)。



最後に、OperaとFFの3番目の質問と機能。 「Opera WebアプリケーションのWebテクノロジー」というドキュメントで 、onloadをフレームに接続するためのハックをスパイしました。 興味深いことに、オンロード時に表示されるDOMドキュメントの表示はさらに悪化しました。 ログインだけでなく、カルマのノードも表示されませんでした。 効果は、不正確なonloadモーメントの選択とほぼ同じですが、そうではありません。ログイン[0] .firstChildノードは、常にではないにしても、長い間見られていません。 これらすべてをどうし、どのように回避するのですか? おそらくOperaは長い一連のノードチェックで「窒息」していて、どうにかしてそれらを異なる方法で行う必要があるのでしょうか 誰もこの状況に遭遇していませんか?



Operaの任意のドキュメントがノードを通してどのように見えるかは理論的な問題です。 それに答える意欲はありませんが、起こっていることの意味そのものが理解できないため、行動を予測して結果を調べる場所はありません。



有用な知識と結論。



1. Operaは、contentDocumentおよびcontentWindowを介して、フレーム内のサブドメインに新しい変数を書き込むことができます。 Firefoxはその方法を知りませんが、contentWindowを介してエラーをスローすることはありません-未定義です。 (フレーム呼び出しはdocument:getElementsByName( 'ifr')のドキュメントにあるため、contentDocumentを介して呼び出す方がより適切ですが、FFが機能せず、 キャッチされないエラーが発生するのは興味深いことです。

if (self.opera)

document .getElementsByName( 'ifr' )[0].contentDocument.u = username;








2. Operaは、ドキュメントの生成後にサブドメインでコードを実行するために、他の誰かのドキュメントのオンロードをハッキングできますが、Firefoxはできません。 (OperaはXMLをほとんど使用していませんでした。)



var ifr= document .createElement( 'iframe' );

ifr.src = 'http://habrahabr.ru/api/profile/' +username+ '/' ;

ifr.style.display= 'none' ;

ifr.onload = function (){

...;

}

document .body.appendChild(ifr);








3.ノードの存在を検証するためのOperaまたはコード。最初のテキストノードが存在しない場合、ノードに正しくアクセスする方法を見つけ出す必要があります。クロスドメイン効果がある場合、他の開発者に同様の効果が発生します。



All Articles