Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Add more server checks before loading urls or reloading #211

Merged
merged 1 commit into from
Nov 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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