tejacques / crosstab

A utility library for cross-tab communication using localStorage.
Apache License 2.0
364 stars 58 forks source link

Broken inter-tab communication in IE when tab is an iframe #26

Open gothy opened 9 years ago

gothy commented 9 years ago

Digging into it revealed that localStorage in IE seems to be absolutely broken by design. http://kntajus.blogspot.com/2014/08/local-storage-fundamentally-broken-in.html https://connect.microsoft.com/IE/feedback/details/811546/ie11-localstorage-events-fire-twice-or-not-at-all-in-iframes Even better! https://connect.microsoft.com/IE/feedback/details/812563/ie-11-local-storage-synchronization-issues

Rising the PING_TIMEOUT or even all the timeouts didn't work. So here's a starting point to see the problem:

tejacques commented 8 years ago

@gothy did you ever come up with a solution to get around this? I'm looking into this again now that I'm making a push for 0.3.0 and 1.0.0.

There was one comment on the first posted MS issue that looked promising:

Posted by prumbles on 6/12/2014 at 12:38 PM

If you have an Iframe in domain A, but the parent page is in domain B,
you can still use localStorage to retrieve messages from another window
in domain A. But you can't use the localStorage "storage" event in IE11 -
you have to poll every 500 milliseconds or so and check if the localStorage
item has changed. This is how I worked around this issue.

And two comments on the second posted MS issue that looked promising:

Posted by Kiyokura on 4/27/2015 at 5:29 PM

I found a workaround (IE11 on Win8.1).

Add the following code, update of other tabs is synchronized well:
----
window.addEventListener("storage", function (e) {
  // Dummy
}, false);

Posted by Vageesh Dwivedi on 3/4/2015 at 6:14 AM

I also faced a similar issue.

Scenario : window 1 is domain.com and has an iframe of domainx.com,
window 2 is domainx.com. I wanted localstorage based communication
between window 1's iframe and window 2.

The listener and polling technique didn't work and indexedDB workaround
was too big for this small problem. After a few hacks, the localStorage keys
were synced when i did -

localStorage.setItem('dummy', 'dummyvalue');
localStorage.removeItem('dummy');

in iframe on window 1.

I've finally got a good vm setup so I can test this more easily now. I'm also going to try and create some IE-specific tests and see if I can automate testing for these cases. I'm hoping that I can replicate it with the following on sauce labs:

Based on the screenshots in the Microsoft issue, I have serious doubts about the quality of the screenshots and reproductions on the official issue page. For example, one user "reproduced" this issue by trying to call localStorage.setItem('key', 'value'), and then showed it was "value" in one iframe, and null in the other. This is a really bad test because that is a protected property on localStorage. It's a function that returns the value for the specified key index. The other screenshots had similar issues. For example, another one showed that viewing the localStorage object in the console didn't display all of the keys, but the length of localStorage was correct. Calling localStorage.key(1) and localStorage.key(2) returns the correct results in all iframes in that scenario.

What I think is going on is that it's not sending the events, but that the data is accessible. If I can reproduce that behavior then I think I'm just going to go with a polling solution specifically for IE10/11.

tejacques commented 8 years ago

I was able to confirm that localStorage does sync across the windows / tabs, it just doesn't receive the storage events. I also couldn't get the behavior to exhibit on a single page. So far I've had to manually create a second tab.

I'll try the workarounds to see if they have any effect at all. I think they probably won't, but it's worth trying. Based on this I think the polling solution is the right way to go. The trickiest part about this is that I don't want to do unnecessary work in the common case (that is, not expecting crosstab to run in an iframe on a different domain).

I think I will probably make it explicit, so you'd have to call a function, crosstab.pollForIE(), as well as adding some documentation for why that exists. Otherwise it can get fairly expensive, especially because you need to take precautions to make sure no events were missed.

gothy commented 8 years ago

Hi @tejacques No, we've ended up moving some state to the server and forget all this madness :)