I am trying to create a OAuth login flow. In a Cordova app (tested only on Android), I try to load a page from my server which redirects the browser to the correct OAuth page on google's side. However, this abruptly stopped working.
If you try the url in the code below in a browser, you may want to go incognito or try some other measure to avoid autologging in. (The server creates an account to an indev service if you actually log in.)
If I write the code like this (I omit the fishing of the credentials tokens from the URL, this is the simplest reproducible example.):
function onLoad(){
document.addEventListener("deviceready", onDeviceReady, false);
}
function onDeviceReady() {
var authWindow = cordova.InAppBrowser.open("https://dev.taskapp.io/googleURI", '_blank');
authWindow.addEventListener("loadstart", function(e){
alert("Loadstart fired")
}
)
}
The webview remains empty and the message Loadstart fired appears once. If I swap '_blank' to to '_self' or '_system', the pages load and the redirects work but the events never fire. This happens only with the given page.
I am at my wit's end.
Update: the same code works like a charm on iOS. On android using window.open() also fails.
Update 2: I now understand, that _system opens the os's browser, which I obviously have no control over and that _self squishes whatever was in the webview, rendering my listeners to nothingness. _blank works once from a cleanly cloned repository and then breaks on a second build (without code change).
If I substitute the url in the cordova.InAppBrowser.open(...) to the one my server redirects from, Google's tech loads. However the final login button (which would trigger the redirection to my server, one can assume.) is dead.
Does redirecting the _blank target break things? Is this a bug? Is someone else experiencing this?
Related
I'm having some trouble with some inAppBrowser behavior in my cordova app. Here's the code:
var codePass = fooCode;
var executeScriptFunc = function(event) {
ref.executeScript({
code: codePass
}, function (value) {});
ref.removeEventListener('loadstop', executeScriptFunc);
};
var ref = cordova.InAppBrowser.open(fooObject.link, "_blank", "location=yes,enableViewportScale=yes");
ref.addEventListener('loadstop', executeScriptFunc)
The strange thing here is that the code works perfectly every time when emulated. It opens the browser and executes the script no problem. But when I try it on my actual iPhone device, it doesn't always work. The script executes maybe every other time. But it's never even that consistent.
Both the emulator and iPhone are using iOS 9.3.4. Any ideas?
If the site inside the inAppBrowser happens to be served via HTTPS, the callback for executeScript() will not work if the site employs a Content-Security-Policy HTTP response header that does not contain the gap: or gap-iab: schemes for the default-src directive. These are needed because execution of the callback function on iOS relies on an iframe that gets added to the page.
You can check whether this is the root cause for the problem by opening Safari’s Web Inspector for the inAppBrowser—it has a separate Web Inspector instance, independent of the parent application that opened it—and look out for a corresponding error message in the console. Note that you should open the console before executeScript() is run, or otherwise you might not get the error message.
Make sure also that you don't have other event handlers firing at the same time during your polling.
I had multiple pollers all firing every second and that's when I ran into the issue.
After changing the polling time so they all fired at different times, the issue went away.
Let's say I have a mobile app that listens to all "myawesomeapp" scheme links so it can open them in the app and I have a related website. Now when a page, for eg, https://myawesomeapp.com/home/ is loaded in the browser, I create an iframe dynamically and add it to the document with the src of myawesomeapp://myawesomeapp.com/home/ so that my app can try and open up that page within itself. But most modern browsers will display an insecure/mixed content warning when such a link is created from a page served over HTTPS. Is there a way around this behaviour?
Browser can't guarantee that the protocol myawesomeapp is secure (like https). So as a security consideration, it MUST warn the user that insecure content is being loaded in an otherwise secure page.
You can create a service on server to redirect to another scheme. i.e. https://website.com/deeplink/appscheme/path will redirect browser to appscheme://path.
According to this the iframe src trick doesn't work anymore.
If you want your app to automatically trigger upon landing on a web page, I found putting this that web page's <head> tag works:
<meta http-equiv="refresh" content="0; url=myprotocol:/path1" />
Where myprotocol is the "scheme" in your intent filter.
However, I am not sure if this method will also be "blocked" future versions of the browser. As the link above stated:
you should implement a user gesture to launch the app via a custom scheme, or use the “intent:” syntax
It seems to me they want intents to be triggered only by user-initiated gestures such as clicking a button, or a link. There could be security issues if a webpage can trigger intents on its own.
I guess what you want is if the user clicks a link to your site, he gets the option to open the link in your app instead of in the browser.
The way to do this in Android is registering an intent filter so your app gets launched when the user clicks a link to your domain name.
See the example intent filter here:
https://developer.android.com/guide/components/intents-common.html#Browser
This is better than using a custom scheme because the link will lead the user straight to the app, instead of loading the site in a browser which will then open the app.
This works different than in iOS, yes. To keep both compatible, you could sniff the useragent and show the iframe with the custom scheme only in iOS browsers.
Can you try this code out? Call it when the document is ready and pass to it the url of your app.
var redirect = function ( location )
{
var iframe = $('<iframe></iframe>').attr( 'src', location ).css({
width: 1,
height: 1
});
$( 'body' ).append( iframe );
iframe.remove();
iframe = null;
};
How do I check if a call to window.location failed because the given URL was invalid, etc? Is there some event I can set on the window object or on some other object that can catch this?
Finally got it to work using a "workaround" that is not a generic solution as I originally hoped:
I am using the fact that the link I am trying to open is a custom url scheme (e.g. myxx://localhost) on mobile, and if it fails, the action I want to perform is a redirection to a standard appstore URL (os-specific). The workaround tries to open the custom URL, and if it fails, the timeout function kicks in shortly after, and opens an alternative url:
setTimeout(function() { window.location=alternateUrl; }, 25);
window.location = customUrl;
The downside is that when the customURL fails, a standard safari browser shows a message box that the site could not be opened, but at least it still redirects the user to the appstore.
Not really possible, because when window.location = someURL is executed, before the URL is even tested, your document is removed from the window. You have no code remaining that could test if it worked.
If the link is on the same origin, you may issue an XMLHttpRequest to test if the page is reachable but there doesn't seem to be a way to test if a page isn't requestable just due to cross origin request or because the URL is wrong.
For a general document, I don't know any way to test if a foreign origin page is reachable (but it can be done for an image using the onload event handler).
you can check if page exists using ajax. didn't test code, but it should work.
var rekuest= new XMLHttpRequest();
rekuest.open('GET', 'http://www.thisdoesnotexits.org', true);
rekuest.send();
if (rekuest.status === "404") {alert("not exist!"); }
I'm looking to add a "tweet this" button to a site. Simple enough, right? The catch is that the site is meant to run on an embedded platform that doesn't particularly handle popup windows, so I'm trying to do everything inside the page.
I'm able to successfully create my tweet button, attach an onClick handler to it, and construct a proper twitter.com/share URL for the relevant content. All works fine when I open that URL in a new window with window.open. However, if I try to open the URL in an iframe, nothing loads inside the frame. Even loading http://twitter.com into the iframe fails in the same way. However, loading Google or any other website seems to work just fine.
Any thoughts on what I'm missing here? Thanks! --zach
Edit:
Yep, they are detecting the iframe on load and blanking the page:
if (window.top !== window.self) {
document.write = "";
window.top.location = window.self.location;
setTimeout(function(){ document.body.innerHTML='';},1);
window.self.onload=function(evt){document.body.innerHTML='';};
}
Any reasonable way to get around this, or am I stuck writing my own auth pipeline through oauth? I don't need anything from their API, just letting users tweet to their own accounts.
Twitter (like Stack Overflow) is probably using some Javascript to ensure they're not being presented in an iFrame:
if(top!=self){
//hates you
}
I ran into something similar recently, and ended up re-doing part of my app without the iFrame element.
Go and get a developper account on twitter and things are made easy for you :)
Can you simply redirect the the twitter share URL? I'm guessing they want to be careful about opening the window in iframe's to prevent malicious sites from tweeting in a user's account without giving the user a chance to first confirm their intent to send this tweet.
You said window.open worked fine for popping up the url in a new window but have you tried popping it into the parent frame?
twtWindow=window.open([url],'_parent',[specs])
#yuval Unfortunately for you, the twitter url goes to a page that has the X-FRAME-OPTIONS:SAMEORIGIN header set in the response. It's not a Javascript check. The browser will simply refuse to render the page after seeing the header. This is done to prevent a clickjacking attack, usually done to steal a user's password.
So your only other option is really to redirect your current page with window.location.href=url.
Ok, so all the rage these days is having a site like this:
mysite.com/
mysite.com/about
mysite.com/contact
But then if the user has Javascript enabled, then to have them browse those pages with Ajax:
mysite.com/#/
mysite.com/#/about
mysite.com/#/contact
That's all well and good. I have that all working perfectly well.
My question is, if the user arrives at "mysite.com/about", I want to automatically redirect them to "mysite.com/#/about" immediately if they have Javascript.
I have it working so if they arrive at "mysite.com/about", that page will load fine on its own (no redirects) and then all clicks after that load via ajax, but the pre-fragment URL doens't change. e.g. if they arrive on "mysite.com/about" and then click "contact", the new URL will be "mysite.com/about#/contact". I really don't like that though, it's very ugly.
The only way I can think of to automatically redirect a user arriving at "mysite.com/about" to "mysite.com/#/about" is to have some javascript in the header that is ONLY run if the page is NOT being loaded via ajax. That code looks like this ($ = jQuery):
$(function(){
if( !location.hash || location.hash.substr(1,1) != '/' ) {
location.replace( location.protocol+'//'+location.hostname+'/#'+location.pathname+location.search );
}
});
That technically works, but it causes some very strange behavior. For example, normally when you "view source" for a page that has some ajax content, that ajax content will not be in the source because you're viewing the original page's source. Well, when I view source after redirecting like this, then the code I see is ONLY the code that was loaded via Ajax - I've never seen anything like that before. This happens in both Firefox 3.6 and Chrome 6.0. I haven't verified it with other browsers yet but the fact that two browsers using completely different engines exhibit the same behavior indicates I am doing something bad (e.g. not just a bug with FF or Chrome).
So somehow the browser thinks the page I'm on "is" the Ajax page. I can continue to browse around and it works fine, but if I e.g. close Firefox and re-open it (and it re-opens the pages I was on), it only reloads the Ajax fragment of the page, and not the whole wrapper, until I do a manual refresh. (Chrome doesn't do this though, only Firefox). I've never seen anything like that.
I've tried using setTimeout so it does not do the redirect until after the page has fully loaded, but the same thing happens. Basically, as far as I can tell, this only works if the fragment is put there as the result of a user action (click), and not automatically.
So my question is - what's the best way to automatically redirect a Javascript capable browser from a "normal" URL to an Ajax URL? Anyone have experience doing this? I know there are sites that do this - e.g., http://rdio.com (a music site). No weirdness happens there, but I can't figure out how they're doing it.
Thanks for any advice.
This behavior is like the new twitter. If you type the URL:
http://twitter.com/dinizz
You will be redirected to:
http://twitter.com/#!/dinizz
I realize that this is done, not with javascript but in the server side. I am looking for a solution to implements this using ruby on rails.
Although I suggest you to take a look on this article: Making AJAX Applications Crawlable