jcubic / sysend.js Goto Github PK
View Code? Open in Web Editor NEWWeb application synchronization between different tabs
License: MIT License
Web application synchronization between different tabs
License: MIT License
Hi,
I've been playing around with your library and was curious about the code. I have noticed that when you use postMessage for cross domain comunication you specify "*" as target (lines 406 and 516). This might be a securiy issue because from what I understand malicious sites could receive the message
From
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#security_concerns
Always specify an exact target origin, not *, when you use postMessage to send data to other windows. A malicious site can change the location of the window without your knowledge, and therefore it can intercept the data sent using postMessage.
Since the domain where to send the event is known when postMessage is called, wouldn't it be better to just specify it as postMessage parameter?
change conent to content
Hi, great library.
It would be nice if we can tell sysend to use localStorage instead of BroadcastChannel throgh options.
The use case is offline web application that run from filesystem.
Thanks
There is no longer a primary page when all are closed.
Possible solution
Hi,
I'm really pleased that I found sysend.js - it's helping to solve a problem of communication between multiple tabs in the browser.
But can you suggest a way to use sysend.js so that the broadcaster of a request can wait for a response from a receiver, or timeout if no response is received?
Thanks for any suggestions.
Kevin
Hello, is it possible to support receiving message in the same window? I'm looking at a scenario where a browser window also receives the same message that it sends/broadcasts out. Thank you!
This workaround seems to work OK.
https://stackoverflow.com/questions/47543856/does-broadcastchannel-work-on-the-same-page
This demo page includes a broken link to https://terminal.jcubic.pl/sysend.php?_=.
One thing that would be nice to see as an additional set of features would be window/tab detection as a primary selection.
.track("primary", () => {
//
// create persistent message connection to server ...
})
.track("primaryClose", (last /* boolean, true if this is the last connected window/tab */) => {
// window close event
if (last) {
// let server know user is going offline - no more connection(s) in this session.
}
// cleanup connection
})
Great lib. Thanks.
The isPrimary() function definition is missing for typescript.
After fixing #34 tracking feature doesn't work anymore on the main demo.
It would be cool is to add ID of the window that got opened. And maybe a function that returns all ids of the other windows. And also a way to send message only for a given window.
This is an extension of #20
Where do I need to add the proxy.html in a React Project. Or can I just add the script tag to the index.html file?
When upgrading from 1.9.0 to 1.11.1, all event broadcasts seem to be unresponsive. What is the reason?
It would be cool and most likely possible to create something like a multi-desktop monitor setup but with browser windows that are displayed next to each other.
Not working with angular $window.location.href.
Create something inspired by https://bgstaal.github.io/multipleWindow3dScene/
I can't import it as a normal module in WebPack. It would be nice if we don't need to use something like exports-loader
(if I'm not mistaken) in order to use this awesome library. Thoughts on this?
This is a continuation of failed PR #30 the code for this experiment is on the devel branch.
When this will be ready it should allow using sysend on CodePen for Cross-Domain communication.
This can be implemented like this:
function sendToPrimary(data) {
return sysend.list().then(list => {
return list.find(window => window.primary);
}).then(primary => {
sysend.post(primary.id, data);
});
}
It can be handy to allow:
sysend.post('primary', data);
Go to https://jcubic.pl/sysend.php and open console. You will see the next errors:
sysend.php:1 Mixed Content: The page at 'https://jcubic.pl/sysend.php' was loaded over HTTPS, but requested an insecure script 'http://jcubic.pl/sysend.js'. This request has been blocked; the content must be served over HTTPS.
Mixed Content: The page at 'https://jcubic.pl/sysend.php' was loaded over HTTPS, but requested an insecure resource 'http://terminal.jcubic.pl/iframe.html'. This request has been blocked; the content must be served over HTTPS.
It would be nice if there are types for TypeScript.
If users use cross-domain communication, attackers can create an iframe and listen to any messages sent from the app and also send messages to the app. This happens only in the same browser so this is low impact.
Example exploit, if you upload this file to any domain, you can intercept messages from http://jcubic.pl/sysend.php
sysend.proxy('http://jcubic.pl');
window.addEventListener('message', (e) => {
console.log(e);
});
sysend.js currently requires a proxy to send messages between two different domains, but it seems that it is possible to send messages between domains (without a proxy) using Window.postMessage().
Would it be possible to use Window.postMessage() for cross-domain communication, instead of using a proxy?
IT would be nice to allow to have:
sysend.off('foo').on('foo', () => {
}).proxy('https://jcubic.pl');
It seems that the demo stopped working:
https://jcubic.pl/sysend-demo/
the second iframe is not reactive.
If you open a cross-domain page two tracking open events are invoked.
When using the main demo on a real domain, it shows duplicated ids in the list()
API.
My usage examples.
Perhaps using it this way is not considered correct.
System A
Trigger the following method execution by clicking the button.
sysend.proxy(`${ip}:8080/proxy/proxy.html`)
sysend.broadcast('msg', { 'register': 'test' })
System B
sysend.proxy(`${ip}:8090/proxy/proxy.html`)
sysend.on('msg', function (e) {
console.log(e)
})
I opened the console and found that many iframes with the same address were created.
For example, the following image.
However, when I trigger a click event on the button in System A, I do not execute the "sysend.proxy" method.
So, System B cannot receive the value transmitted by System A through the broadcast method.
Creating multiple iframes seems to cause the on method to be triggered multiple times.
Can we create only one iframe with the same address to avoid issues from occurring.
Perhaps I should make a note that the version number I am using is 1.16.3.
I haven't tested the latest version, I'm not sure if this problem also exists.
I'm not quite sure if every time the broadcast method is used, the proxy method needs to be triggered once, or if the global only needs to initialize the proxy method once.
I tried triggering the proxy method only once globally and then using broadcast to pass values, but this feature seems to be ineffective.
Hello! The source code includes unexpected arrow function. As long as node_modules dir is not transpiled by default it causes runtime error in browsers that don't support arrow functions such as IE11. It would be nice to replace it with regular function
iframe.addEventListener('load', () => {
resolve();
}, true);
Thanks in advance!
Could you demonstrate/document how to import and use your library in VUE or React pls. Thanks
When calling proxy method, the injected iframe element still takes place in DOM, I see the current hiding method is using the next props for the iframe's style -
width: 0;
height: 0;
border: none;
Using display: none;
instead solves the problem for me,
but I'm still trying to figure out if it can mess up any other functionality and if so, is there another solution?
Add examples of
track()
post()
list()
There are a few people that contributed it would be nice to add them to README.
Hi,
I'm using the version 1.12.1 with typescript and the function "proxy" doesn't work as expected or maybe I'm using it in the wrong way but I think that problem is due to the definition of type in the interface Sysend.d.ts
proxy(args?: string[]): void;
that have an array of string as param but in the library the function proxy need a string as url
`proxy: function() {
[].slice.call(arguments).forEach(function(url) {
if (typeof url === 'string' && host(url) !== window.location.host) {
domains = domains || [];
domains.push(origin(url));
....
}`
so if I use proxy in this way
sysend.proxy(["url1","url2"])
the
[].slice.call(arguments)
give me an array as foreach element and the if condition is never true.
It's no possible to pass other params to the proxy function to have the urls in arguments because of typescript definition so the only workarond that I have found is to use
sysend.proxy([]).bind(null,"url1","url2")()
to have a true condition but you know is not the best one :)
thanks for help ;)
So I've created this app:
sysend.on('input', text => {
console.log({text});
input.value = text;
});
input.addEventListener('input', () => {
console.log(input.value);
sysend.broadcast('input', input.value);
});
but it doesn't synchronize from page to iframes. It only works for iframes to the main page.
Probably because iframe works in proxy mode, not as an app.
It should work somehow, so you can demo the library.
Tried in Angular, When open new tab it return true on new opened tab
All articles should be in Readme for better SEO of those articles.
So when you open at least two tabs with the same url (say localhost:8080/en-us
) and broadcasted an event on one of the tabs nothing happens. But if you put the other tab on another page (say localhost:8080/ja-jp
) it works.
https://github.com/jcubic/sysend.js/blob/master/sysend.js#L54
This is working (different urls).
EDIT: I created a pull request that fixes this issue but I still can't figure how to make IE not fire the event on the tab where that event was made when they have the same URL. Maybe this is an an IE bug. You may have better ideas.
Currently not possible to have a single proxy page and communicate in both directions for cross-domain scenarios. For example, sending "broadcast" from the domain w/ the proxy page will be received on the page w/o a proxy. The reverse will not be received. Creating a PR to resolve this.
Hi @jcubic,
Could you please publish the version 1.3.5 on npm? For now, it's still 1.3.4. The version 1.3.5 is crucial because it fixes broken JSON.
I am looking forward to your release. Thank you.
Hey Awesome library,
i want to open a new url and want to inject some JS into it ( can’t use iframe in my case )
Plan is to use this library for communication
But first i have to inject js, Atleast this library into that website, is it possible ?
Because i don't have access to that website
So options are, either i manually inject js or i use extension to do it automatically
Do we have another option which don't requires manual work and can be handled programatically ?
This can be a cool thing to create.
Something like this:
function request(id) {
return new Promise(resolve => {
});
}
it should work similarly to fetch. The other tab should listen to a single request and post it to the origin tab. The request should reject when it will timeout.
There should be a way to send array instead of just objects as message.
This is mostly a thread to share my experiences with the issues with my cross-domain setup using sysend.js, which stopped working several months ago, but I only now was able to dig in to it and figure out what was happening.
When I tested your built-in cross-domain demo (https://jcubic.pl/sysend-demo/) it still worked, so at first, I thought the issue was due to something with my setup (I only load one iframe since that seemed to be enough for me to get full functionality, see #29 & #37). So I first updated to the latest version of sysend, and when I still had issues, next changed my setup to be configured with dual iframes, but ultimately had the same issues. Lastly, I tried toggling the enforcement of using the localStorage
feature via sysend.useLocalStorage()
, but no differences.
Switching to evaluating the roots of the problem, broadcastChannel.postMessage
would never propagate from an iframe window to a tab with the same domain when that iframe was rendered under a page with a different domain. The same holds true for any localStorage
events (all of the localStorage
data was completely different and isolated, even though the tab and iframe were from the same origin).
In my case my two sites are different domain origins entirely (a.subdomain1.com
vs b.subdomain2.com
), where as your cross-domain demo are both under the same domain, just one is a subdomain (jcubic.pl
vs terminal.jcubic.pl
) which is why I suspect the demo still works, although I couldn't find any documentation anywhere for that exception. I did try the setup for my domains with different subdomains but under same main domain, and it did work, but unfortunately I can't make that change in production since it'll break a lot of users access (on both sites) to various resources (too many hardcoded URL's in emails).
Ultimately, the issue is due to a new feature coming down the pipe in browsers, storage/state propagation. I investigated Chrome specifically since that's what we work with internally, so the situation for Firefox or Edge could be different. For Chrome, this feature started in Chrome Beta 113, but was officially available in the production release of Chrome 115 (I'm on 117 atm), which was released back in July '23 I think, which kind of lines up with when I suspect this issue started to occur for me. FYI, I believe that they are rolling out this feature to users slowly, so not all users on latest Chrome version may be affected by it.
For Chrome, there is a way to register in an Origin Trial and submit a form which essentially will generate you a code that you then embed in your site (as a meta tag, or a http header in some cases). You have to provide it your top-level site domain and specify some other settings (i.e. subdomain wildcard, third-party script injection, usage count, etc). Ultimately, this allowed me to restore this functionality to my site in the latest chrome browser version without needing all users to disable a chrome feature flag or anything like that, HOWEVER, this code/trial will expire (supposedly) by Sept 2024 (link), which if anything, at least gives me a year to figure out an alternative (or actually migrate to using same domain origin). I'm hoping that they enable some sort of way to enable a whitelist of allowed domains to have unpartioned cross-origin access to these resources before the trial expiration date.
If anyone has any other suggestions or knows more about this, I'm all ears. But until then, I hope this helps someone else.
Other useful links:
https://developer.chrome.com/en/docs/web-platform/origin-trials/#take-part-in-an-origin-trial
https://developer.chrome.com/docs/web-platform/origin-trial-troubleshooting/
https://developer.chrome.com/docs/web-platform/third-party-origin-trials/
https://chromeenterprise.google/policies/atomic-groups/#ThirdPartyStoragePartitioningSettings
Credit to @yangon99's comment which was my first hint of the source of the issue being related to the new storage partitioning feature.
I wish I could use sysend.js to make the BroadcastChannel API work across domains, like this:
var bc = new sysend.BroadcastChannel('test_channel');
bc.postMessage('This is a test message.'); /* post a message to every domain */
bc.onmessage = function (ev) { console.log(ev); } /* receive a message from any domain */
Does sysend.js have such a feature?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.