Skip to content

Commit

Permalink
fix: Add more server checks before loading urls or reloading (#211)
Browse files Browse the repository at this point in the history
Add  more server ckecks before loading urls or reloading, also check for socket
  • Loading branch information
jcesarmobile authored and mlynch committed Nov 9, 2018
1 parent 9c0eeea commit 60eff2f
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 22 deletions.
74 changes: 56 additions & 18 deletions src/ios/CDVWKWebViewEngine.m
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ @interface CDVWKWebViewEngine ()
@property (nonatomic, readwrite) CGRect frame;
@property (nonatomic, strong) NSString *userAgentCreds;
@property (nonatomic, assign) BOOL internalConnectionsOnly;

@property (nonatomic, readwrite) NSString *CDV_LOCAL_SERVER;
@end

Expand Down Expand Up @@ -353,6 +354,14 @@ - (void)pluginInitialize
addObserver:self
selector:@selector(onAppWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onSocketError:)
name:@"socketUnknownError" object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onSocketError:)
name:@"socketInUseError" object:nil];

NSLog(@"Using Ionic WKWebView");

Expand Down Expand Up @@ -417,7 +426,11 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
if (context == KVOContext) {
if (object == [self webView] && [keyPath isEqualToString: @"URL"] && [object valueForKeyPath:keyPath] == nil){
NSLog(@"URL is nil. Reloading WKWebView");
[(WKWebView*)_engineWebView reload];
if ([self.webServer isRunning]) {
[(WKWebView*)_engineWebView reload];
} else {
[self loadErrorPage:nil];
}
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
Expand All @@ -426,11 +439,19 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N

- (void)onAppWillEnterForeground:(NSNotification *)notification {
if ([self shouldReloadWebView]) {
NSLog(@"%@", @"CDVWKWebViewEngine reloading!");
[(WKWebView*)_engineWebView reload];
if ([self.webServer isRunning]) {
NSLog(@"%@", @"CDVWKWebViewEngine reloading!");
[(WKWebView*)_engineWebView reload];
} else {
[self loadErrorPage:nil];
}
}
}

- (void)onSocketError:(NSNotification *)notification {
[self loadErrorPage:nil];
}

- (BOOL)shouldReloadWebView
{
WKWebView* wkWebView = (WKWebView*)_engineWebView;
Expand Down Expand Up @@ -475,17 +496,25 @@ - (id)loadRequest:(NSURLRequest *)request
if ([self.webServer isRunning]) {
return [(WKWebView*)_engineWebView loadRequest:request];
} else {
NSString* errorHtml = [NSString stringWithFormat:
@"<html>"
@"<head><title>Error</title></head>"
@" <div style='font-size:2em'>"
@" <p>The App Server is not running.</p>"
@" <p>Close other apps and try again.</p>"
@" </div>"
@"</html>"
];
return [self loadHTMLString:errorHtml baseURL:request.URL];
return [self loadErrorPage:request];
}
}

- (id)loadErrorPage:(NSURLRequest *)request
{
if (!request) {
request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.CDV_LOCAL_SERVER]];
}
NSString* errorHtml = [NSString stringWithFormat:
@"<html>"
@"<head><title>Error</title></head>"
@" <div style='font-size:2em'>"
@" <p><b>Error</b></p>"
@" <p>Unable to load app.</p>"
@" </div>"
@"</html>"
];
return [self loadHTMLString:errorHtml baseURL:request.URL];
}

- (id)loadHTMLString:(NSString *)string baseURL:(NSURL*)baseURL
Expand Down Expand Up @@ -744,7 +773,11 @@ - (void)webView:(WKWebView*)theWebView didFailNavigation:(WKNavigation*)navigati

- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
{
[webView reload];
if ([self.webServer isRunning]) {
[webView reload];
} else {
[self loadErrorPage:nil];
}
}

- (BOOL)defaultResourcePolicyForURL:(NSURL*)url
Expand Down Expand Up @@ -815,14 +848,19 @@ - (void) webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigat

-(void)getServerBasePath:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:self.basePath] callbackId:command.callbackId];
[self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:self.basePath] callbackId:command.callbackId];
}

-(void)setServerBasePath:(CDVInvokedUrlCommand*)command
{
NSString * path = [command argumentAtIndex:0];
[self setServerPath:path];
[(WKWebView*)_engineWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.CDV_LOCAL_SERVER]]];
NSString * path = [command argumentAtIndex:0];
[self setServerPath:path];
NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.CDV_LOCAL_SERVER]];
if ([self.webServer isRunning]) {
[(WKWebView*)_engineWebView loadRequest:request];
} else {
[self loadErrorPage:request];
}
}

-(void)setServerPath:(NSString *) path
Expand Down
33 changes: 29 additions & 4 deletions src/ios/GCDWebServer/Core/GCDWebServer.m
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ - (int)_createListeningSocket:(BOOL)useIPv6
*error = GCDWebServerMakePosixError(errno);
}
GWS_LOG_ERROR(@"Failed binding %s listening socket: %s (%i)", useIPv6 ? "IPv6" : "IPv4", strerror(errno), errno);
[[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"socketInUseError" object:nil]];
close(listeningSocket);
}

Expand Down Expand Up @@ -713,20 +714,38 @@ - (BOOL)hasSocketError:(int)socket {
int error = 0;
socklen_t len = sizeof(error);
int retval = getsockopt(socket, SOL_SOCKET, SO_ERROR, &error, &len);

if (retval != 0 ) {
/* there was a problem getting the error code */
GWS_LOG_ERROR(@"error getting socket error code: %s\n", strerror(retval));
return YES;
}

if (error != 0) {
GWS_LOG_INFO(@"Socket error: %s on socket %d\n", strerror(error), socket);
return YES;
}
return NO;
}

- (int)socketError:(int)socket {
int error = 0;
socklen_t len = sizeof(error);
int retval = getsockopt(socket, SOL_SOCKET, SO_ERROR, &error, &len);

if (retval != 0 ) {
/* there was a problem getting the error code */
GWS_LOG_ERROR(@"error getting socket error code: %s\n", strerror(retval));
return retval;
}

if (error != 0) {
GWS_LOG_INFO(@"Socket error: %s on socket %d\n", strerror(error), socket);
return error;
}
return 0;
}

- (void)_didEnterBackground:(NSNotification*)notification {
GWS_DCHECK([NSThread isMainThread]);
GWS_LOG_DEBUG(@"Did enter background");
Expand All @@ -744,8 +763,14 @@ - (void)_willEnterForeground:(NSNotification*)notification {
}

if ([self isRunning] && ([self hasSocketError:ipv4ListeningSocket] || [self hasSocketError:ipv6ListeningSocket])) {
[self _stop];
[self _start:nil];
// If error is -1 (unknown) its probably because of port being used by other app, so don't restart in this case as it will fail
if ([self socketError:ipv4ListeningSocket] != -1 && [self socketError:ipv6ListeningSocket] != -1) {
[self _stop];
[self _start:nil];
} else {
_options = nil;
[[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"socketUnknownError" object:nil]];
}
}
}

Expand Down

0 comments on commit 60eff2f

Please sign in to comment.