Send information from one browser window to another - javascript

I have a SPA that I cannot leave due to the fact that if the user leaves/refreshes, some information might be lost.
I want to implement the Instagram API, however the API requires that you browse to a different URL, login, receive a code in your URL, and then get redirected back.
Since I cannot do this directly from my site, I must open a new window to do this.
How can I retrieve the code from the URL in a separate window to send back to my site in the original window?
I have looked at websockets (need a server, so no) and WebRTC (on localhost, did not seem to work) already with no luck. Any suggestions?

If the API allows using an iframe, you can watch what's happening inside the iframe or communicate from inside the iframe using parent.instagramLogin(data) (where instagramLogin is a function you defined outside the iframe).
An alternative option is to automatically close the login tab once the login is finished, and when the main tab is focused again (window.onfocus) send an ajax request to check if the login was completed. (and of course keep checking every time the event fires until you get a result or until it becomes irrelevant.)
Update:
I found a reliable way to communicate between open tabs, using BroadcastChannel if supported, otherwise storage event from localStorage. You can find the details here, and someone in this link even made a small library to make it quick and easy.

Related

Load a website in the background and once done redirect to the loaded website

I'm searching for a method to say:
<a href="http://example.com>click me</a>
<script>
If the <a> was clicked, don't redirect immediately, but instead, load http://example.com in the background, and once that is done, redirect the user to http://example.com
</script>
So this way, the user will wait inside my website, instead of waiting in the other website.
respectful right?
I know that the people will ask why do you want to do that. Please I'm just testing something..
What I think is: that it's maybe impossible using Javascript only, but I think that we can do it using some backend, I don't mind if you reply with nodejs or php, I like the more advanced boys.
So this way, the user will wait inside my website, instead of waiting in the other website.
respectful right?
Doesn't sound like it to me. People would likely rather see that next page loading. You might be surprised to know that a lot of people don't have great internet connections, and can read the text of a site well before the rest of it loads. Even if you could pull this off, you'd be breaking that behavior for them.
Fortunately, what you're asking to do isn't possible. If you were in control of the site, you could use the Fetch API or AJAX to load content in the same page context, but that doesn't sound like it applies here.
You cannot load example.com in background as browser which loads the example.com is on user side.
You could use a hidden div and load example.com into it and show that div once loading is completed but that would mean the user has not left your website at all.
As soon as hyperlink is clicked the browser starts their handshake with that other site and you lose the control of what happens between users browser and the server of example.com

Python 3 script cannot open AND close browser window for login with OAuth API

INTRODUCTION
As you will see below, I already tried 3 methods, mainly from what I could find here on stackoverflow. But I am in a dead end.
I am trying to built a Python 3 script that would make requests to the Spotify API. But first, I need to authenticate via OAuth, and more particularly using the 'Authorization Code' flow, to get an "endless" access. See here. Basically the process consist in those main steps:
GET request to https://accounts.spotify.com/authorize endpoint with several parameters including:
the client_id of my registered app (found on my Spotify Dev Dashbord)
the redirect_uri
(user's login if not already logged in)
(user's authorization for my app if not already authorized)
redirected to redirect_uri: https://example.com/callback?code=XYZ
get the XYZ Authorization Code and pass it back to the main script for next step
[ POST request to https://accounts.spotify.com/api/token endpoint to get an access_token ] -> we won't be covering that point in this post, neither the following steps.
Because of the need for the user's credentials and most of all the need for user's authorization, I have to open a browser window. The thing is that I can't get to manage that window how I would like to from my Python 3 script.
ATTEMPT #1
First of all, I have been very inspired from examples given here and more particularly by this one in JavaScript.
INTRODUCTION step 1. is dealt with a webbrowser.open_new_tab(url). Once my app is authorized, Chrome (my default browser) is redirected to localhost. Indeed, my Python 3 script runs a "one-time-only" SimpleHTTPRequestHandler server which waits for the request. When received, it gets the Authorization Code from the window.path, then sends back some HTML code to browser with a window.close(). This last bit of code works when the app is already authorized, but not when the Spotify login page or the Authorization page appears in between. The window won't close in this case. I came to understand that only a window opened via window.open() can be programmatically closed via window.close(). I have attempted many other variations at this point like window.open('','_self').close();. All failed to close the window if the app is not already authorized and user is not already logged in.
QUESTION 1: Why won't it work? And why does it even work when already logged in + authorized?
QUESTION 2: I am thinking that the login window somehow changes the window... But How can I verify that? Chrome console won't help, I don't even get an error for the window.close.
QUESTION 3: Is there a way to keep a handle to the opened window and pass it back to the callback javascript?
ATTEMPT #2
Combining selenium and chromedriver I could successfully open and close that window:
browserdriver.execute_script("window.open('%s', '_self');" % url)
window.close()
But the thing is that selenium seems to be more intended for unit testing. So, I could not get it to open a Chrome window using Chrome default profile when already in use in another open Chrome session/instance. It works correctly only when I make a temp user data folder, but by doing so, the login credentials cannot be retrieved from default profile (nor saved), which does not suit me.
QUESTION 4: I have seen a workaround that consists in copying the whole user data folder somewhere and use it to open Chrome, so it has write access to the default profile. This does not suits me... Do you see another solution?
ATTEMPT #3
Back to using webbrowser. The main script now opens a browser that does not directly make the GET request of INTRODUCTION step 1. (previously mentioned url in ATTEMPT #2 step 1. ). It makes a request to localhost that delivers some HTML code to browser with a window.open(url, '_self'). But later, in the callback javascript, 'window.close()` won't work again. Even if user's already logged in and the app authorized! (it worked in ATTEMPT #1 in this particular case)
QUESTION 5: Why is that? the window.open() is even explicit in this case, whereas it was not in ATTEMPT #1 because hidden in the webbrowser class.
If I use window.open(url), I can close the new window with window.close() later on. But the first window remains open, and here again, a new problem: the new window is a blocked popup because it is opened by script and therefore cannot be tracked down to a user action (unlike the example given in INTRODUCTION which uses a "Login" button).
QUESTION 6: How could I open a single browser window, not a blocked popup, and close it, while managing to retrieve the Authorization Code?
Any more ideas?
Note: I am not interested in a solution with a simple copy of the URI the browser redirected to, and then paste in Python interpreter to retrieve the Authorization Code provided by the Spotify Accounts service (as does Spotipy for example).

iframe not active unless receives user interaction

I've been working on a requirement that involves a website fetching/manipulating data stored on a different domain. There didn't seem a way except for enabling CORS on the other server to allow me to get and modify data from a different domain. However, that caused some issues with Office 365 apps and I had to take a different approach.
The approach is to use postMessage to talk to a hidden iframe (not a good approach, but I was insisted to use it) on the page that is running on the target domain. The source page posts message along with information about the REST call to the hidden iframe which makes a requests on behalf of the parent page and uses postMessage to return back the results.
Everything works fine except for when the website is being used on an iPhone. Turned out placing alert calls in the script running inside the target iframe makes it to work but removing the alert calls sort of disables the target iframe from making those cross-origin network calls.
My theory is that it is due to the security of mobile Safari that in order to make cross-origin calls from an iframe running on a different domain, the user needs to provide their consent by interacting at least once with the embedded iframe. Does that sound correct?
The comment by diodeus-james-macfarlane is the closest that we could go but the iframe being hidden, there was no way we could have placed a control for the user to interact with, even if that was only for it to work.
To my surprise, turning off a setting on the SharePoint site made it work. The setting was around mobile view compatibility and without that, the iframe is able to make HTTP requests, send and receive messages to and from the parent webpage.

How to keep js function run between different pages?

I wonder how sites like SoundCloud work: you play a song and it keeps playing even if you move to another page without stopping
Any suggestions?
The only way I can think of is to build your app, or at least the parts of it that need to bo continuous, as a single page.
In practice, this means that only one HTML document is loaded. When, say, a link is pressed, the browser action is intercepted and prevented and the browser behaviour is faked by javascript.
Consider a website consisting of pages A and B. Normally, when a link pointing to B is activated, the URL is changed and the browser calls the server, requesting B. In a single-page application, however, this is interrupted by a javascript function, which changes the URL using the History API, and then displays B in a way that doesn't require a new document being synchronously fetched from the server.
There's a couple of ways to do it.
Navigate to a new page
If you do that, a whole new JS execution context is created for the new page, so you can't keep the function running. What you can do however is to "resume" execution in the new page. For this you need to save the state of the old page either on the server or in some client storage that persists between page changes (cookies, localStorage, etc).
Fake navigation
This is the most user friendly way - you turn your website into a web application. You no longer have multiple pages, so when user wants to change what he sees in the browser (like go to a new song), the app simply changes the appropriate area with the desired content. This is a complex topic that should probably be researched in itself, not explained in a SO answer. Go ahead and google "single page application" and you should find plenty of resources for it.
Technically you never change the page when you are using souncloud. You always stay on the same page and only the parts get changed which are actually changing, so you never reload the whole page. That's why they can keep the music playing: They just never remove or change the actual player. If you are wondering why the URL in your browser is changing if you never leave the page: They manipulate your history entries.
If you are interested in creating an application that behaves similar you should checkout frameworks like Ember.js or Angular.js. TodoMVC Gives a nice overview of those frameworks.

Is it possible to hide/close an iframe from within itself or on server side?

Suppose I have a page that I am writing a javascript plugin for on the domain first.com. The javascript plugin injects an iframe pointing to a login page (of domain second.com) into the first.com page and displays it as a popup so that the user can login.
Is there anyway for me to hide/close the iframe after the user logs in with it? I can inject any javascript necessary into the first.com page and I control both the client and server side code on the login page within the iframe.
The main issue is that the iframe cannot access it's parent window to hide itself and the parent window cannot see any changes made in the contents of the iframe because of the same origin policy. Is there anyway around this or should I just lose the iframe idea and instead open a new window?
If the developer of second.com can be convinced to load an iframe in their login page, which loads a page at first.com, the the inner iframe can call javascript on the outer, since they are both from first.com. You can pass parameters in this way too, through the url of the inner iframe. An example here.
I think the issue you're running into is the browser stopping the cross-domain communication from happening. There is a way to sign your javascript but it is pretty much breaking the browser security model and isn't suggested unless absolutely necessary.
Is there any way that the login form is based on URL submition? You could create a simple sign in form and use AJAX to get your response back to ensure a successful login. This solution depends on having a RESTful login and again, I'm not sure about the implementation of your second.com.
If you're wondering about how to use the ajax to submit a form, I'd check this out (it is in jQuery but it applies to just about any framework.) View the source on that and see if that could work in your situation.

Categories

Resources