So I'm writing my first app, and have a quick question about blocking other domains in UIWebView. I would like to restrict navigation to my website, and my partner website only. So, if there happens to be a link on my site that links to Google, I'd like for a popup message to occur and say "You can't go there!" or something. I'm not sure how to go about this. I've never played with UIWebView before and am pretty new to programming in general.
Any help is greately appreciated, thanks!
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *host = [request.URL host];
if ([host isEqualToString:"oralb.com"] || [host isEqualToString:"other.com"]) {
// Add any of your own domains in the above line
return YES;
}
return NO;
}
You need to make your controller class the delegate of the web view. Then implement this method in the controller:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
In this method you can examine the request to see if its URL is acceptable. If it is, return YES, if not, show your alert and return NO.
To test the domain you can request the host from the URL of the request.
Related
Can I get a UIWebView to query my custom function to get NSData* for any resource it needs loaded?
The UIWebViewDelegate function shouldStartLoadWithRequest doesn't get triggered for every resource being loaded, such as CSS for example.
What I need is a function (that I have control over) that gets called every time a resource is requested. In my wxWidgets application, I make use of the wxWebViewHandler class and its GetFile method.
Hope it help for you
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest: (NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if ( navigationType == UIWebViewNavigationTypeLinkClicked ) {
// here deside whether you go futher or not accoding to return yes or no
return NO;
}
return YES;
}
I'd like to open new web pages in new UIWebViews. For example, when you go to Google that would count as one web page, but when you click on Google Images within Google it would count as a new web page.
All new web pages will be loaded in new UIWebViews and will be put in a History array that contains all the UIWebViews.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if (navigationType == UIWebViewNavigationTypeBackForward) {
// The UIWebView already exists for that page in the history array, call it and display it.
}
else if (navigationType == UIWebViewNavigationTypeFormResubmitted) {
// No problem, load it in the current UIWebView.
}
else if (navigationType == UIWebViewNavigationTypeFormSubmitted) {
// It's a new page, load it in a new UIWebView.
}
else if (navigationType == UIWebViewNavigationTypeLinkClicked) {
// It's a new page, load it in a new UIWebView
}
else if (navigationType == UIWebViewNavigationTypeReload) {
// Just reload the current UIWebView.
}
else if (navigationType == UIWebViewNavigationTypeOther) {
// There's no way this is a new page. Do nothing.
}
}
As you probably have guessed, it didn't work. All you have to do is follow this path:
Go to http://www.9gag.com
Click the share on twitter icon under any post.
The link to share on twitter will look something like this:
https://twitter.com/intent/tweet?original_referer=http%3A%2F%2F9gag.com%2Fgag%2FaRQpqj2%3Fref%3Dt.mw&source=tweetbutton&text=I%20don%27t%20throw%20the%20word%20%27genius%27%20around%20loosely%2C%20but...&url=http%3A%2F%2F9gag.com%2Fgag%2FaRQpqj2%3Fref%3Dt.mw&via=9GAG
Although, someone would expect this link to be of type LinkClicked because you clicked the twitter icon to go there, it's actually of type Other, any desktop web browser will consider this link to be a pop up and would have opened it in a new window. Safari on iOS opens this link in a new tab. I would like to open it in a new UIWebView but the problem is that there's nothing differentiating an ad request from a pop up request in the UIWebView's delegate.
How is Safari doing it?
EDIT: The answer bellow is exactly the problem with UIWebView. It fools everyone into thinking that the delegate is the answer, when in fact you can do nothing without hacking your way through, even the simplest stuff.
EDIT 2: I have checked with other browsers as well like Mercury and they get this right. They understand that Twitter is a pop up and they open it in a new tab. So, this is not Apple's fault.
Set the delegate of your first web view to your view controller.
After that, add the following code to your view controller.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSLog(#"%#", request.URL);
NSLog(#"%#", [request.URL scheme]);
if ([[request.URL scheme] isEqualToString:#"http"])
{
// Create web view here, because you're catching all requests
// Don't forget to set the delegate.
NSLog(#"Create new web view with %#", request.URL);
return NO;
}
return YES;
}
As you can see, you should replace the part where I added the NSLog. You're probably going to want to create a new web view at that point, and add it to the current view as a subview.
Why would you want to check on LinkClicked and not catch all requests?
My goal is to allow UIWebView load initial link, but disallow any further navigation.
I saw question:
Disable hyperlinks in UIWebView
So, I wired referenced webView property from interface builder.
I specified that my UIViewController uses UIWebViewDelegate:
#interface LegalViewController : UIViewController<UIWebViewDelegate>
In the code, on viewDidLoad, I do following:
mFirstLoad = TRUE;
webView.delegate = self;
And I have following code:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if (!mFirstLoad)
return FALSE;
mFirstLoad = FALSE;
return TRUE;
}
shouldStartLoadWithRequest is called both initial call and when I click on the link. However, even if shouldStartLoadWithRequest returns FALSE, UIWebView still proceeds and loads a new page.
I see this problem on iOS Simulator 6.0
How can I fix this behavior?
return NO based on type to exclude links
return !(navigationTpe==UIWebViewNavigationTypeLinkClicked);
Is it possible your boolean is getting reset somehow? What happens if you just return NO for (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType?
Here is the same thing which I wrote in comments:
I think I found the reason for the problem. I am not sure how to properly call it (not a big expert on HTML and Javascript). However the link has following code : "<a href="/something" data-transition="flip"</a> As result, callback is called, but it looks like results of this callback is ignored.
As result most likely solution is here: Remove hyperlinks in uiwebview
For security reasons, I used to use an anonymizer on mobile safari. However It was a bit annoying. If I searched for something and clicked on a link, then google returns an error message. You can try.. http://proxy2974.my-addr.org/myaddrproxy.php/http/www.google.com.au/ (search for something and click on a link -- it works fine if you test it on desktop browsers.. however it will return http://proxy2974.my-addr.org/myaddrproxy.php/http/url if you try it on iPhone or iPhone simulator)
So I decided to make my own. What I am doing is to get the URL from the text field and pass it through the anonymizer's link like urlString = [NSString stringWithFormat:#"http://proxy2974.my-addr.org/myaddrproxy.php/http/%#", urlString];
However I am still facing the same problem.. When I click on a link on google, it returns an error.. So what I want to do is to get the clicked link, stop loading the page (before it returns an error), then pass it through the anonymizer.. How can I do that? Thanks..
- (BOOL)webView:(UIWebView *) sender shouldStartLoadWithRequest:(NSURLRequest *) request navigationType:(UIWebViewNavigationType) navigationType {
NSLog(#"req: %#",request.URL.absoluteString);
return YES;
}
req: http://proxy2974.my-addr.org/url?sa=t&source=web&cd=1&ved=0CFMQFjAA&url=%2Fmyaddrproxy.php%2Fhttp%2Fwww.perthnow.com.au%2Ffun-games%2Fleft-brain-vs-right-brain%2Fstory-e6frg46u-1111114517613&ei=GXAsUMaUA7H44QTys4HYDA&usg=AFQjCNGB_zOrrEZC0SKx813XGHB1xi_AlA
req: http://proxy2974.my-addr.org/myaddrproxy.php?proxy_url_sjla67z78f8viz4=url&sa=t&source=web&cd=1&ved=0CFMQFjAA&url=%2Fmyaddrproxy.php%2Fhttp%2Fwww.perthnow.com.au%2Ffun-games%2Fleft-brain-vs-right-brain%2Fstory-e6frg46u-1111114517613&ei=GXAsUMaUA7H44QTys4HYDA&usg=AFQjCNGB_zOrrEZC0SKx813XGHB1xi_AlA
req: http://proxy2974.my-addr.org/myaddrproxy.php/http/url
Implement this delegate method to retrieve a clicked link in UIWebView:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
if(navigationType == UIWebViewNavigationTypeLinkClicked)
{
NSLog(#"req: %#",request.URL.absoluteString);
}
}
implement
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType;
in your uiwebview delegate
In an app I'm writing I think it would be best if the user can tap on a UILabel and I can see what word they tapped on. Is there anyway I can do this?
you can do it use a UIWebview
use
- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL;
and code the whole message then wrap the link to
[webView.loadHTMLString:#"Google" baseURL:nil];
then in the delegate method
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
you will know which word you tapped
if ( [request.URL.scheme compare:FeverProtocolIdentifier] == NSOrderedSame )
{
NSString *word = request.URL.resourceSpecifier;
}
I don't think this is very easy. I would probably use an OHAttributedLabel rather than a UILabel and add a method to the OHAttributedLabel code to return the information you need. If you look at the linkAtPoint method in OHAttributedLabel.m, you can see what you'll need to do. I would duplicate that method, naming the new one characterOffsetAtPoint perhaps, and then return the index that the existing code calculates at line 340.