diff --git a/src/ios/CDVWKWebViewEngine.m b/src/ios/CDVWKWebViewEngine.m index e7e05122..2c1936fc 100644 --- a/src/ios/CDVWKWebViewEngine.m +++ b/src/ios/CDVWKWebViewEngine.m @@ -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 @@ -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"); @@ -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]; @@ -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; @@ -475,17 +496,25 @@ - (id)loadRequest:(NSURLRequest *)request if ([self.webServer isRunning]) { return [(WKWebView*)_engineWebView loadRequest:request]; } else { - NSString* errorHtml = [NSString stringWithFormat: - @"" - @"Error" - @"
" - @"

The App Server is not running.

" - @"

Close other apps and try again.

" - @"
" - @"" - ]; - 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: + @"" + @"Error" + @"
" + @"

Error

" + @"

Unable to load app.

" + @"
" + @"" + ]; + return [self loadHTMLString:errorHtml baseURL:request.URL]; } - (id)loadHTMLString:(NSString *)string baseURL:(NSURL*)baseURL @@ -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 @@ -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 diff --git a/src/ios/GCDWebServer/Core/GCDWebServer.m b/src/ios/GCDWebServer/Core/GCDWebServer.m index 4e8f306f..ebb83268 100644 --- a/src/ios/GCDWebServer/Core/GCDWebServer.m +++ b/src/ios/GCDWebServer/Core/GCDWebServer.m @@ -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); } @@ -713,13 +714,13 @@ - (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; @@ -727,6 +728,24 @@ - (BOOL)hasSocketError:(int)socket { 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"); @@ -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]]; + } } }