Call 'action' on HTML web form in a UIWebView - iphone

I'm trying to skip the login page of a website, so I can give the user a more aesthetically appealing login page, and save their login credentials for automatic login in the future. So far I have two UITextFields, and a UIButton. The user enters their username and password, and upon pressing the UIButton their details are entered into the actual webform on the sites login page, and the subsequent 'logged-in' page is shown in a UIWebView. The webView will be hidden while the app logs the user in, and then presented when the 'logged-in' page has loaded.
I've managed to populate the webform, but simply can't actually submit it! I'm sure there's a very simple solution!
This is the code I have so far, and if there's a better way I should be doing this let me know!
-(IBAction)login:(id)sender
{
// Create js strings
NSString *loadUsernameJS = [NSString stringWithFormat:#"var username = document.getElementsByName('username')[0]; username.value='%#';", username.text];
NSString *loadPasswordJS = [NSString stringWithFormat:#"var password = document.getElementsByName('password')[0]; password.value='%#';", password.text];
// Autofill the form - this works, and I can see the values being put into the webform
[self.webView stringByEvaluatingJavaScriptFromString: loadUsernameJS];
[self.webView stringByEvaluatingJavaScriptFromString: loadPasswordJS];
// This is the method I have tried to submit the form, but nothing happens (ct100 is the ID of the form).
[self.webView stringByEvaluatingJavaScriptFromString:#"document.ct100.submit();"];
}

Below Approach might be helpful to you
Put this code inside the didFinishLoading Method Of UIWebView Protocol
Fill The USerId
[webView stringByEvaluatingJavaScriptFromString:#"document.getElementById('username').value = 'userId'"];
Fill The Password
[webView stringByEvaluatingJavaScriptFromString:#"document.getElementById('password').value = 'password'"];
Call Submit Button as below
[webView
stringByEvaluatingJavaScriptFromString:#"document.forms['login_form'].submit();"];
Herelogin_form is the Name of You Form
Note: You have to manage one thing once you have filled the Credential clicked the Submit button. you need to make some BOOL or something else for avoiding the loading repetition of UIWebView.

Try:
[webView stringByEvaluatingJavaScriptFromString:#"document.getElementById(\"ct100\").submit()"];
Your view controller needs to implement the UIWebViewDelegate protocol and set itself as the UIWebView's delegate. Returning YES from webView:shouldStartLoadWithRequest (see code below) will allow the web view to navigate to any url the your form is submitting to.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSLog(#"Allow navigation to request = %#", request);
return YES;
}

Related

facebook login on iphone leaves blank page

I created a simple test html page that contains a facebook like box. For testing purpose I uploaed the test page to my server.
On the desktop (being log out of facebook) there is the following situation:
Click on like
A popup appears with a form for login
After login the popup is closed and the like count is raised
However, using it on my iphone in chrome browser and being logged out of facebook the following happens:
Click on the like button
Redirect to the facebook login page
After login I'm redirected to a blank page.
The screenshot below shows the problem:
Is there a possibility to avoid this?
EDIT: The same happens when I try this in an iOS app using a UIWebView.
Okay, I found a solution for doing this in my iOS app for an integrated UIWebView.
When someone is not logged in to facebook a popup opens and requests a login. After logging in the user is redirected back to the page from where he hit the like button. However in the UIWebView this redirect URL leaves the user with a blank page. The solution to the problem is to intercept the redirect URL and reload the page with the like button.
So, with UIWebView one can intercept the requests before the actual webpage is loaded and react on certain URLs. The code for this look like this:
- (void)viewDidLoad
{
[super viewDidLoad];
self.webview.delegate = self;
[self.webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.example.com/facebook_like_box.html"]]];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if( [[request.URL description] rangeOfString:#"lugins/close_popup.php"].location != NSNotFound) {
// We intercepted the redirect URL of facebook after logging in. Instead of loading a blank page recall the URL of the like box
// manually on the uiwebview.
[self.webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.example.com/facebook_like_box.html"]]];
//returning NO indicates the the page is not further loaded.
return NO;
}
//Any other page should be loaded
return YES;
}

Facebook login fails in UIWebView

In my app I have to load a web page in UIWebView where user can login with Facebook. The problem is that when user clicks login, blank page appears.
Is it possible to get back to first page and be logged in?
Web page works perfectly in Safari and opens new window and after login it closes it and gets back to where it left.
EDIT: wrong URL was provided to UIWebView
I think the sample of facebook SDK for iOS does the log in way you want.
Please refer to the link:
facebook-iOS-SDK-sample: https://github.com/facebook/facebook-ios-sdk/tree/master/sample/Hackbook
Especially this part in https://github.com/facebook/facebook-ios-sdk/blob/master/sample/Hackbook/Hackbook/RootViewController.m
/**
* Show the authorization dialog.
*/
- (void)login {
HackbookAppDelegate *delegate = (HackbookAppDelegate *)[[UIApplication sharedApplication] delegate];
if (![[delegate facebook] isSessionValid]) {
[[delegate facebook] authorize:permissions];
} else {
[self showLoggedIn];
}
}
When you click on log in button, it will open a login dialog, and ask for permission. This is what it looks like: https://developers.facebook.com/docs/mobile/screenshots/ios/#iphone-native
I think the best way to implement the "facebook-related" app is to start with the Hacbook. It is really a nice and detailed sample.
If you want to reload a specific url after the facebook login popup is closed to prevent being stuck on a blank page you can use this code.
First include the UIWebViewDelegate and set your delegate somewhere in your code.
[yourwebView setDelegate:self];
Then use the shouldStartLoadWithRequest method to check request url for close_popup.php which is used by Facebook to close their popup.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *urlString = [NSString stringWithFormat:#"%#", request];
if ([urlString rangeOfString:#"close_popup.php"].location == NSNotFound) {
//The close_pop.php is not found. (Do nothing)
} else {
//Facebook closed the popup so we should load the page we now want the user to see.
NSURL*url=[NSURL URLWithString:#"http://www.example.ca/thepageyouwanttoreload.html"];
NSURLRequest*request=[NSURLRequest requestWithURL:url];
[webView loadRequest:request];
}
return YES;
}
SSL issue? As per Joanne use the facebook SDK and you get loads of extra functionality for free, including logging in via the facebook native app if its installed.

webViewDidStartLoad Request URL Not Set to URL Being Loaded

I am working on a browser that has back and forward buttons, that when tapped, should immediately display the URL of the page being loaded. Currently I do something like [webView goBack]; and then implement the delegate UIWebView method:
- (void)webViewDidStartLoad:(UIWebView *)aWebView {
NSLog(#"began loading URL: %#", aWebView.request.URL);
}
But this doesn't result in the behavior I expect.
For example, if I start out at www.google.com and then navigate to www.aol.com and then press the back button causing the web view's goBack code to be called, the NSLog will output began loading URL: http://www.aol.com/ even though it should state that google.com is being loaded. The google page will load perfectly however in the web view. What I don't understand is why the URL isn't consistent with what is being loaded. On occasion the log will spit out that aol.com is being loaded, followed by google.com, but this only happens sometimes. Is this a bug with the SDK or am I missing something?
Thanks in advance.
try in this delegate method
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSLog(#"Request Url:%d",request.URL.absoluteURL);
}
I suggest to use an array of string every time you load a new url you add it in the array and beside it define a global counter increase/deacrease based on back/forward click so you can get the url easy like this
NSString *urlString = [urlArray objectAtIndex:theCounterValue];
try:
NSString *currentURL;
currentURL = [[NSString alloc] initWithFormat:#"%#", webView.request.mainDocumentURL];

Appying our own action to Facebook Login button & closing all Facebook screens.

I am using fbconnect api in my project. When the login dialog gets opened where we entered our credentials, when we click on login button then it is redirected to the publish page how can we close the login page or post to wall page or view.
My problem is I don't want to open any page belongs to face book API, instead i want to open my own page. Any one can help or suggest.
In FBConnect there is a class FBDialog which is using UIWebView for Facebook login authentication. The FBDialog class implements the UIWebView delegate protocol. So if you want to perform your action on login button press then you can handle it in FBDialog.m in UIWebView delegate -
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
which will call when you press on login button.
You can open your own view depending upon your requirement. After successful Login following delegate method is called
- (void)session:(FBSession*)session didLogin:(FBUID)uid
{
self.usession=session;
[self postToWall];
}
Here i am calling my own custom method postToWall. Where i create publish dialog as below:
-(void)postToWall
{
FBStreamDialog *dialog=[[[FBStreamDialog alloc]init]autorelease];
dialog.userMessagePrompt=#"Enter Message to Post";
[dialog show];
}
You can create your own view in postToWall in place of FBStreamDialog OR if you want to load request of another page then load that URL in Web View of FBStreamDialog.m class.

Multiple UIWebViewNavigationTypeBackForward not only false but make inferring the actual url impossible

I have a UIWebView and a UITextField for the url. Naturally, I want the textField to always show the current document url. This works fine for urls directly input in the field, but I also have some buttons attached to the view for reload, back, and forward.
So I've added all the UIWebViewDelegate methods to my controller, so it can listen to whenever the webView navigates and change the url in the textField as needed.
Here's how I'm using the shouldStartLoadWithRequest: method:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"navigated via %d", navigationType);
//loads the user cares about
if ( navigationType == UIWebViewNavigationTypeLinkClicked
|| navigationType == UIWebViewNavigationTypeBackForward ) {
//URL setting
[self setUrlQuietly:request.URL];
}
return YES;
}
Now, my problem here is that an actual click will generate a single navigation of type "LinkClicked" followed by a dozen type "Other" (redirects and ad loads I assume), which gets handled correctly by the code, but a back/forward action will generate all its requests as back/forward requests.
In other words, a click calls setUrlQuietly: once, but a back/forward calls it multiple times.
I am trying to use this method to determine if the user actually initiated the action (and I'd like to catch page redirects too). But if the method has no way of distinguishing between an actual "back" and a "load initiated as a result of a back", how can I make this assessment?
Without this, I am completely stumped as to how I can only show the actual url and not intermediate urls. Thank you!
Ok here's what I ended up doing - not sure if this is the expected solution though. Scratch all the code from the above method and instead do this:
- (void)webViewDidStartLoad:(UIWebView *)webView {
NSString *urlString = [self.webView stringByEvaluatingJavaScriptFromString:#"document.URL"]
[self setUrlQuietly:[NSURL URLWithString:urlString]];
}
This means there's a slight delay between clicking a link etc and seeing the url show up in the textField, but it also guarantees that the textField always shows the document's actual title.
I'm not seeing the UIWebViewNavigationTypeBackForward event at all. And sometimes webViewDidStartLoad never gets called. Perhaps there have been some changes in iOS 5.
Anyway, here's my solution for keeping the title and URL up to date. Works very consistently, though the response could be a little faster.
- (void)webViewDidFinishLoad:(UIWebView *)wv
{
[self updateButtons];
titleLabel.text = [wv stringByEvaluatingJavaScriptFromString:#"document.title"];
NSURL *url = wv.request.URL;
[selectedUrl release];
selectedUrl = [url retain];
}