MozillaのGreasemonkey拡張機能とは異なり、Operaはクロスドメインリクエスト(XDR)のGM_xmlhttpRequest関数の類似物を提供しません。 もちろん、これはUserJSの範囲と範囲を大きく制限します。 たとえば、XDRを使用すると、さまざまなオンラインミュージックプレーヤー(vkontakte.ruやMySpaceなど)にLast.fm scrobblerを実装できます。
ただし、iframeとwindow.nameトランスポートを使用して、Operaでクロスドメインクエリを機能させることができます。 カットの下で、これを行う方法を示し、すべての魔術を実装するシンプルなライブラリを提示します。
一般的に、クロスドメインクエリには次の手法が使用されます。
- プロキシリクエスト。 ページがリモートWebサービスにアクセスするサーバーを所有している場合、サーバーにリクエストをプロキシするスクリプトを実装できます。 したがって、クライアント側では、要求はドメインへの呼び出しのように見えますが、実際には、リモートサーバーでのクエリの結果が返されます。
このアプローチの欠点は、要求元のドメインでサーバーを制御する必要性に加えて、サーバーの着信チャネルの負荷とIPによってプロキシを禁止する機能が含まれます。 さらに、ユーザーデータはサーバーを通過するため、エンドユーザーは私たちを信頼する必要があります。 - フラッシュ経由のリクエスト。 Webサービスを提供するサーバーを所有している場合は、いくつかのドメインからのXDRを許可するXMLポリシーファイルをそのサーバーに配置できます。 短所:Webサービスコントロールが必要、Flashが必要。
script要素の動的生成など、非同期リクエストのさまざまな代替を使用します。 Webサービスの制御が必要です。 さらに、正しいjavascriptを返すには、多少なりとも深刻なコードの変更が必要です。- クロスオリジンリソースシェアリングの使用 。 繰り返しますが、Webサービスの制御が必要です。さらに、この仕様は、私が知る限り、他のどこでもサポートされていません。
誰かが興味を持っているなら、いつかこれらの古典的なアプローチについて詳しく書きます。 しかし、それらについてはすでに多くのことが書かれています。
一般的なケースで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ドキュメントを選択する必要があります。これは、各リクエストがそれらを通過するためです。
図では、次のようになります。

ところで、各ブラウザウィンドウ(および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を使用した作業スクリプトは
こちらです。