Cross Domain Requests in Opera UserJS
However, cross-domain queries can be made to work in Opera using tricks with iframes and window.name transport. Under the cut, I will show how to do this and present a simple library that implements all the witchcraft.
Generally speaking, the following techniques are used for cross-domain queries:
- Proxying requests. If we own a server whose pages want to access a remote web service, we can implement a script on our server that proxies requests to it. Thus, on the client side, the requests will look like a call to their domain, but in fact, the results of the query on the remote server will be returned.
The disadvantages of this approach, in addition to the need to control the server on the requesting domain, include the load on the incoming channel of our server and the ability to ban our proxy by IP. In addition, user data passes through our server, so the end user must trust us. - Requests via Flash. In the case where we own a server that provides a web service, we can place an XML policy file on it that allows their XDR from some domains. Cons: Web service control required, Flash required.
- The use of various substitutes for asynchronous requests, for example, the dynamic generation of elements
script. Web service control required. In addition, a more or less serious change to its code is required to return the correct javascript. - Using Cross-Origin Resource Sharing . Again, control over the web service is required, and in addition this specification, as far as I know, is not supported anywhere else.
If anyone is interested, someday I will write in detail about these classic approaches. However, a lot has already been written about them.
When writing UserJS in the general case, we do not have access to either the server on whose page the script is launched, or to the web service. Therefore, we cannot apply 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 an iframe from the web service domain, and the main page communicates with the frame using window.name transport. Recall that the window.name property, once set, retains its value when the window travels across the domain border.
Now in more detail. So, suppose we write UserJS for a domain
domain.ruthat wants to make an asynchronous request to a web service on a domain ws.org. Requests to the web service will be sent by UserJS running in the iframe for a document from a domain ws.org(for example, ws.org/dummy.gifwhich specific URL is not important). And in order to pass the request arguments, it is necessary in advance, before the page from the remote domain opens, installwindow.namein the frame to a string containing these parameters. This way, UserJS on ws.org will get the request arguments from its window.name and forward the necessary XMLHttpRequest to ws.org. It is already possible for him: a request within the ws.org domain. Then, the execution result is pushed back into the window.nameframe, and the frame will be redirected to any page on domain.ru(for example domain.ru/dummy2.gif), where UserJS is run again, which launches the query result handler in the main window. Of course, you need to select documents
dummy.gifand dummy2.gifthat have the correct cache headers installed, because each request goes through them. On the diagram, it looks something like this:

By the way, you must 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 thread, you can use something like this design
window.parent.setTimeout(parent.handler, 0). The point, I think, is clear.Application
I implemented this method in the form of a self-made library to make last.fm a scrobbler for vkontakte.ru .
The implementation can be viewed on pastebin . On line 58 there was a pastebin backlight glitch, so I commented on it. Of course, it must be uncommented when used.
The object does all the work
Requester. Requester.requestsends a request. He needed to pass the page address of the web service, which will subsequently be executed the request and the address at your domain (that is, dummy.gifand dummy2.gifthe example). The method request creates an iframe, passes parameters, and translates the iframe to dummy.gif. It returns a Deferred object, on which you can hook callback and errback (errback will be called at timeout). Userjs onws.org/dummy.gifcan get the passed parameters y Requester.getArguments()and return data using Requester.returnData(). Using token, Requester checks that the data is intended for him. That is, if there is a possibility of several scripts on one web service, it is worth changing token to any other. A working script using
Requester is here .