📜 ⬆️ ⬇️

Cross-domain queries in Opera UserJS

Unlike the Greasemonkey extension in Mozilla, Opera does not provide an analogue of the GM_xmlhttpRequest function for cross-domain requests (XDR). This, of course, severely limits the capabilities and scope of UserJS. Using XDR, for example, you can implement an Last.fm scrobbler for various online music players (such as vkontakte.ru or MySpace).

However, cross-domain queries can be made to work in Opera with tricks with iframes and window.name transport. Under the cut, I'll show you how to do it and present a simple library that implements all witchcraft.

Generally speaking, the following techniques are used for cross-domain queries:


If anyone is interested, someday I will write in detail about these classical approaches. But they are already written in many places.
')
When writing UserJS, in general, we do not have access to either the server, on the page of which the script is launched, or to the web service. Therefore, we cannot use any of the above techniques in their pure form. But there is a way to overcome these limitations.

The essence of the method


It would seem that everything is simple: the request is made from iframe from the domain of the web service, and the main page with the frame communicates using the window.name transport. Recall that the window.name property, once set, retains its value when traveling through a window across a domain.

Now more. So, suppose we write UserJS for domain.ru , which wants to make an asynchronous request to a web service on the ws.org domain. Requests to the web service will be sent to the UserJS running in the iframe for a document from the ws.org domain (say, ws.org/dummy.gif : which particular URL is not important). And in order to pass the request arguments, it is necessary in advance, before the page opens from the remote domain, to set window.name on the frame in the string containing these parameters. Thus, the UserJS on ws.org will receive the request arguments from its window.name and send the necessary XMLHttpRequest to ws.org . It is already possible for him: a request within the ws.org domain. Then the result of execution is thrust again into the window.name frame, and the frame will be redirected to any page on domain.ru (for example, domain.ru/dummy2.gif ), where UserJS is running again, which starts the result result handler in the main window.
Of course, you need to choose dummy.gif documents and dummy2.gif , which have the correct caching headers, because every request passes through them.

On the diagram, it looks like this:
uml

By the way, it is necessary to remember that each browser window (and iframe is a window) executes a separate javascript stream. To run the handler in the context of the main window's thread, you can use something like the window.parent.setTimeout(parent.handler, 0) construct. The point, I think, is clear.

Application


I implemented this method as a self-made library to make last.fm scrobbler for vkontakte.ru .

Implementation can be viewed on pastebin . On line 58 was a pastebin's glitch glitch, so I commented out it. It, of course, must be uncommented when used.

All the work is done by the object Requester . Requester.request sends the request. He needs to pass the address of the web service page, on which the request will subsequently be executed, and the address on his domain (that is, dummy.gif and dummy2.gif from the example). The request method creates an iframe, passes the parameters, and translates the iframe to dummy.gif . It returns the Deferred-object, on which you can attach callback and errback (errback will be called upon timeout). UserJS at ws.org/dummy.gif can get passed parameters from Requester.getArguments() and return data using Requester.returnData() . With token, Requester verifies that the data is meant for it. That is, if there is a possibility of several scripts on one web service, you should change the token to any other.

A working script using Requester is here .

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


All Articles