Opera UserJSのクロスドメインリクエスト

MozillaのGreasemonkey拡張機能とは異なり、Operaはクロスドメインリクエスト(XDR)のGM_xmlhttpRequest関数の類似物を提供しません。 もちろん、これはUserJSの範囲と範囲を大きく制限します。 たとえば、XDRを使用すると、さまざまなオンラインミュージックプレーヤー(vkontakte.ruやMySpaceなど)にLast.fm scrobblerを実装できます。

ただし、iframeとwindow.nameトランスポートを使用して、Operaでクロスドメインクエリを機能させることができます。 カットの下で、これを行う方法を示し、すべての魔術を実装するシンプルなライブラリを提示します。

一般的に、クロスドメインクエリには次の手法が使用されます。


誰かが興味を持っているなら、いつかこれらの古典的なアプローチについて詳しく書きます。 しかし、それらについてはすでに多くのことが書かれています。

一般的なケースでUserJSを記述する場合、スクリプトが起動されるページのサーバーまたはWebサービスへのアクセス権はありません。 したがって、上記の手法を純粋な形で適用することはできません。 しかし、これらの制限を克服する方法があります。

メソッドの本質


すべてが単純なように思えます。リクエストはWebサービスドメインのiframeから行われ、メインページはwindow.nameトランスポートを使用してフレームと通信します。 window.nameプロパティは、一度設定すると、ウィンドウがドメインの境界を越えて移動するときにその値を保持することを思い出してください。

より詳細に。 したがって、 domain.ruドメインのWebサービスに非同期要求を行いたいdomain.ruドメインのdomain.ruを作成するとします。 Webサービスへのリクエストは、ドメインws.orgからのドキュメント(たとえば、 ws.org/dummy.gif / ws.org/dummy.gif :重要ではない特定のURL)のiframeで実行されているUserJSによって送信されます。 また、リクエスト引数を渡すには、リモートドメインのページが開く前に、これらのパラメーターを含む行のフレームにwindow.nameを設定する必要があります。 したがって、ws.orgのUserJSは、そのwindow.nameから要求引数を受け取り、必要なXMLHttpRequestをws.orgます。 彼にとってはすでに可能です:ws.orgドメイン内のリクエスト。 次に、実行結果はフレームのwindow.nameバックされ、フレームはdomain.ru任意のページ(たとえばdomain.ru/dummy2.gif )にリダイレクトされ、そこでUserJSが再び実行され、メインウィンドウでクエリ結果ハンドラーが起動されます。
もちろん、正しいキャッシュヘッダーがインストールされているdummy.gifおよびdummy2.gifドキュメントを選択する必要があります。これは、各リクエストがそれらを通過するためです。

図では、次のようになります。
UML

ところで、各ブラウザウィンドウ(およびiframeはウィンドウ)が個別のjavascriptストリームを実行することを覚えておく必要があります。 メインウィンドウスレッドのコンテキストでハンドラーを実行するには、このwindow.parent.setTimeout(parent.handler, 0)コンストラクトのようなものを使用できます。 その点は明らかだと思います。

申込み


last.fmをvkontakte.ruのscrobblerにするために、このメソッドを自作ライブラリの形で実装しました

実装はpastebinで確認できます。 58行目では、ペーストビンのバックライトにグリッチがあったため、コメントしました。 もちろん、使用するときにはコメントを外す必要があります。

Requesterオブジェクトがすべての作業を行います。 Requester.request送信します。 彼は、要求が後で実行されるWebサービスページのアドレスと、自分のドメインのアドレス(例のdummy.gifおよびdummy2.gif )をdummy2.gifがあります。 requestメソッドはiframeを作成し、パラメーターをdummy.gif 、iframeをdummy.gifます。 コールバックとerrbackをフックできるDeferredオブジェクトを返します(タイムアウト時にerrbackが呼び出されます)。 ws.org/dummy.gifのws.org/dummy.gifは、渡されたパラメーターをRequester.getArguments()から取得し、 Requester.getArguments()を使用してデータを返すことができます。 トークンRequesterを使用すると、データが自分Requester確認します。 つまり、1つのWebサービスに複数のスクリプトが存在する可能性がある場合、トークンを他のWebサービスに変更する価値があります。

Requesterを使用した作業スクリプトはこちらです。

Source: https://habr.com/ru/post/J55825/


All Articles