Reputation: 66650
There are multiple questions about Cross-Tab and Cross-Domain communication but I'm asking specifically about Safari. That browser since version 7 added blocking of 3rd party tracking to iframes. So localStorage event and BroadcastChannel don't work on that browser when using inside an iframe.
My question is: are there any other solutions to cross-domain communication (between iframe and page with the same origin in a different tab) for Safari?
In my library sysend.js I've added a disclaimer that the cross-domain (same with any other library) doesn't work on Safari 7+. But maybe there is some trick to making that communication work.
EDIT:
The status of Safari:
This means basically that none of the solutions to send data out of iframe to tabs of the same origin doesn't work. And iframe proxy is the only way I know of cross-domain communication.
Upvotes: 3
Views: 2184
Reputation: 52093
If the iframe is using the sandbox
attribute, you probably need to allow-same-origin
allow-same-origin: If this token is not used, the resource is treated as being from a special origin that always fails the same-origin policy (potentially preventing access to data storage/cookies and some JavaScript APIs).
You might be interested to read about the Storage Acess API (links: MDN article, W3C Community Group Draft Report) (currently supported on Edge, Firefox, and Safari).
Quoting from the MDN article:
The Storage Access API provides a way for embedded, cross-origin content to gain unrestricted access to storage that it would normally only have access to in a first-party context (we refer to this as an origin's first-party storage).
The API provides methods that allow embedded resources to check whether they currently have access to their first-party storage, and to request access to their first-party storage from the user agent.
[...]
sandboxed
<iframe>
s cannot be granted storage access by default for security reasons.
Note that to use this API in a script running in a sandboxed iframe, the iframe needs to have the following permissions: allow-storage-access-by-user-activation
, allow-scripts
, allow-same-origin
.
Window.postMessage
Note: jcubic is aware of Window.postMessage
, which I learned after reading one of his articles about his library. I am leaving this answer here for the sake of anyone else who stumbles across this question.
From the MDN page on Window.postMessage
:
The
window.postMessage()
method safely enables cross-origin communication betweenWindow
objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.Normally, scripts on different pages are allowed to access each other if and only if the pages they originate from share the same protocol, port number, and host (also known as the "same-origin policy").
window.postMessage()
provides a controlled mechanism to securely circumvent this restriction (if used properly).Broadly, one window may obtain a reference to another (e.g., via
targetWindow = window.opener
), and then dispatch aMessageEvent
on it withtargetWindow.postMessage()
. The receiving window is then free to handle this event as needed. The arguments passed towindow.postMessage()
(i.e., the "message") are exposed to the receiving window through the event object.
I believe the first paragraph could probably be improved. I'm pretty sure it really means to make a wider statement about communication across Browsing Contexts.
And in its Notes section:
Any window may access this method on any other window, at any time, regardless of the location of the document in the window, to send it a message.
So to answer your question ("are there any other solutions to cross-domain communication (between iframe and page with the same origin in a different tab) for Safari?"): caniuse says this API is supported on Safari.
The question then becomes: How do you give a reference to one Window
to another Window
? You can easily get references to iframe Window
s that are in the same browsing context, but what about when they aren't in the same browsing context? The MDN article lists window.opener
, which works in the very specific case when the page that you want to receive messages is the one from which the page you want to send messages was opened, and no configuration was done to not set window.opener
. I believe that other than that, you'd probably only be able to do this with the privileges of a browser extension to make that initial connection between browsing contexts (and I have no experience in this area). If such a thing is possible, it would mean your users / users of anything made using your JS library would need to install a browser extension to handle such a case, and I'm pretty sure each browser has different APIs for building extensions and capabilities they give to extensions (which could be a pain to build and maintain).
Upvotes: 2