Reputation: 1974
I'm a newbie in Cocoa development.
I have read about using WebPolicyDelegate. However, I can't seem to have it work the way it should. I want the app to open external links and have it launched in a web browser like chrome or safari. This should only occur whenever the link is being clicked.
Currently, the default url of my app also opens to the web browser at the same time with what my app's webview is doing.
I've set the policyDelegate to my webview and I used the following code for its implementation:
- (void)webView:(WebView *)webView
decidePolicyForNavigationAction:(NSDictionary *)actionInformation
request:(NSURLRequest *)request
frame:(WebFrame *)frame
decisionListener:(id <WebPolicyDecisionListener>)listener
{
if ([actionInformation objectForKey:WebActionElementKey]) {
[listener ignore];
[[NSWorkspace sharedWorkspace] openURL:[request URL]];
}
else {
[listener use];
}
}
Any help would be much appreciated! :)
Upvotes: 4
Views: 5917
Reputation: 1878
Based on the answers above, I crafted following solution. I had a problem when using window.open() in a cordova-osx app (it didn't do anything). Here's my fix, if anyone has the same problem (change CDVWebViewDelegate.m like so):
- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request {
return sender; //[self externalWebView:sender];
}
#pragma mark WebPolicyDelegate
- (void) webView:(WebView*) sender decidePolicyForNavigationAction:(NSDictionary*) actionInformation request:(NSURLRequest*) request frame:(WebFrame*) frame decisionListener:(id <WebPolicyDecisionListener>) listener {
NSString* url = [[request URL] description];
NSLog(@"navigating to %@", url);
//[listener use];
NSString *scheme = [[request URL] scheme];
if ([scheme isEqualToString:@"file"])
{
[listener use];
}
else
{
[listener ignore];
[[NSWorkspace sharedWorkspace] openURL:[request URL]];
}
}
When window.open() is called in JS, createWebViewWithRequest is called in the delegate and the current WebView (sender) is returned. This then in turn calls decidePolicyForNavigationAction of the current delegate. Using the url scheme, we decide whether the request should be handled by the WebView, of an external browser (sharedWorkspace).
Upvotes: 0
Reputation: 1974
I was able to fix my problem by setting my webView as the PolicyDelegate.
[webView setPolicyDelegate:self];
and implemented the following code from : pandoraboy
- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request
{
// HACK: This is all a hack to get around a bug/misfeature in Tiger's WebKit
// (should be fixed in Leopard). On Javascript window.open, Tiger sends a null
// request here, then sends a loadRequest: to the new WebView, which will
// include a decidePolicyForNavigation (which is where we'll open our
// external window). In Leopard, we should be getting the request here from
// the start, and we should just be able to create a new window.
WebView *newWebView = [[WebView alloc] init];
[newWebView setUIDelegate:self];
[newWebView setPolicyDelegate:self];
return newWebView;
}
- (void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener {
if( [sender isEqual:webView] ) {
[listener use];
}
else {
[[NSWorkspace sharedWorkspace] openURL:[actionInformation objectForKey:WebActionOriginalURLKey]];
[listener ignore];
[sender release];
}
}
- (void)webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id<WebPolicyDecisionListener>)listener {
[[NSWorkspace sharedWorkspace] openURL:[actionInformation objectForKey:WebActionOriginalURLKey]];
[listener ignore];
}
I hope this could help others, too. :)
Upvotes: 16
Reputation: 2427
You can check your URL'Ss scheme to check if it should be opened in default browser or not.
// open local urls in our app, and external in default browser
NSString *scheme = [[request URL] scheme];
if ([scheme isEqualToString:@"file"])
{
[listener use];
}
else
{
[listener ignore];
[[NSWorkspace sharedWorkspace] openURL:[request URL]];
}
This code works for me. It is extendable: you can check for your custom schemes to do some custom actions.
Upvotes: 5