In Chrome and Chromium for 2.5 years, there is a bug of the lack of cross-domain access to another frame from the context script (user script). What works normally in a regular page script, for example, intersite data transfer using
postMessage and that works without problems in other browsers, is sometimes considered a “security restriction” in Chrome, but in fact it is a common and
recognized bug noted with 4 th version.
It is known that such problems are solved in Chrome extensions, when they are assigned access rights, but the crux of the matter is that additional access rights for such ordinary tasks are not required, all that is needed is to bypass the bug in one browser. And then we can write the extension working in all browsers that support users scripts in one file. An example of such a task that cannot be solved by ordinary scripts is getting data on the number of “likes” from the Google Plus button (without
special authorization in Google Apps and without
server technologies ). For such and similar tasks, in which the “vendor” does not provide an API, a user script is necessary (necessary), and it does not have to be individual for each browser, as required by the extension.
An example of getting the number of “likes” from the Google+ button in userscript, which works in all browsers (except IE), is available in
HabrAjax . There, the value of “likes” is read inside the frame by the embedded script and is brought out for a more compact display right on the button surface. Footnote for 4-5-digit numbers about 50 pixels wide. hiding styles, which greatly saves space on the button. Below is a screenshot.

How to get data from a cross-domain frame in other browsers
The data is obtained quite simply using the
postMessage method supported in Firefox 3+, IE8 +, Safari4 +, Opera 9.5+, Chrome1 +. For older browsers use hacks like Iframe hash, Iframe name. In the receiver window, put the event listener "
message ":
window.addEventListener("message", receiveMessage, false);
In the window (or frame) source send a text message:
(target_window).postMessage(data, domainTarget);
The source context must point to the target window, and in the second argument, it is recommended to explicitly indicate the receiver's domain for security purposes, rather than writing a string containing an asterisk (in the sense, “any domain”). It is then that a bug pops up in Chrome in context scripts - the browser must provide an understanding of the object
(target window) .postMessage , and it happens in ordinary scripts in it. For users, Chrome has an object ambiguity bug
(target window) .postMessage if the window contains a different domain - other than the source of the message. Therefore, a “crutch” is required for a sufficiently well-shaped message transfer scheme.
')
Addition of cross-domain transfer for Chrome
On the receiver side, there are no additions, because the problem is not in it. In the source, we use script loading into the
window environment.
In the embedded script in another frame we read, waiting for the appearance, we need the data.
if(gPlusFrame){ var Tout = function(h){ var th = this; (function(){ if((h.dat = h.check() ))
And upon detection of the required data (the number of likes), a part of the above code starts, starting with “try {”. For all browsers except Chrome, create a postMessage () event in one line. For Chrome, the bug is performed as described in the winEval () function.
var winEval = function(fs, s, noOnce){
That's all the wisdom of bypassing the bug. As you can see, an additional 30-40 lines are required. There is one consolation that these lines are functions that can be useful in other places of user scripts.
If you need to transport data to the other side and you also need a user-script (if you can’t write a regular script on the page), the same addition will be needed for the second domain. It is logical to use the same procedure and the same script, adding its second domain to the meta-directive.
Frame or Script Format Requirements
The
postMessage method requires knowledge of the domain and the path to the target window. Therefore, it is required to transfer these 2 parameters to the user script in some way. They must be specified either explicitly (for example,
parent ), or taken from an accessible environment. Since the script runs in a cross-domain frame (or window) and does not have (for Chrome) access to other windows, in practice they indicate the domain in the frame URL (this is done, for example, in the Google+ button). Therefore, suppose that the target window's domain name is written in URl in the format of /. in frame with URL:
http://some-widget-site.com/abcd.php?a=1&b=2&parent=http://some-my-site.com/some-path .
Or the same, but the anchor will be added:
http://some-widget-site.com/abcd.php?a=1&b=2#parent=http://some-my-site.com/some-path .
If there is no such possibility to set the domain of the target, the script should be rewritten to specify the domain explicitly or in another way (as an option, use the same
postMessage from the top window in the user script to accept the domain name). In the following, it is assumed that the domain is specified in the
parent parameter. So, in particular, done in the Google+ button.
Note that this complex mechanism will work in all browsers, but it requires more resources, because eval () is implicitly executed, so loading the script in the [window scope] should only be done where necessary, namely, in the Chrome browser, as long as bug 20773 exists. Therefore, in the working script, a branch is made that checks
postMessage crossdomain frame and perform a bug bypass if the method is not available.
The script has a couple of useful functions that are needed in other places of the user script and could be taken as library functions:
1) loading programs into the [window scope] ([global_scope]) environment;
2) tracking the emergence of independent asynchronous data using a slow down timer.
The second procedure is not the best solution, but sometimes there is no other way to learn about the conditions independent of its script, as in the case of checking the results of a third-party widget. Reading the number of “likes” in the Google+ frame just applies to this occasion.
Ps . Admins, rename the blog GreaseMonkey, please, finally, in "User scripts".