CB-9888: (iOS) check & reload WKWebView

This closes #11

When an app is entering the foreground,
the WKWebView content process sometimes dies without
calling the webViewContentProcessDidTerminate delegate function.

This PR checks whether the content process has died, by
examining the title property of the WKWebView, which is nil
when the process has died.

If the process has died the WKWebView is reloaded,
which avoids the White Screen Of Death problem described
in CB-9888.
diff --git a/src/ios/CDVWKWebViewEngine.m b/src/ios/CDVWKWebViewEngine.m
index 48924de..9224e31 100644
--- a/src/ios/CDVWKWebViewEngine.m
+++ b/src/ios/CDVWKWebViewEngine.m
@@ -88,6 +88,36 @@
     }
 
     [self updateSettings:self.commandDelegate.settings];
+
+    // check if content thread has died on resume
+    NSLog(@"%@", @"CDVWKWebViewEngine will reload WKWebView if required on resume");
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(onAppWillEnterForeground:)
+               name:UIApplicationWillEnterForegroundNotification object:nil];
+}
+
+- (void) onAppWillEnterForeground:(NSNotification*)notification {
+    [self reloadIfRequired];
+}
+
+- (BOOL)reloadIfRequired
+{
+    WKWebView* wkWebView = (WKWebView*)_engineWebView;
+    NSString* title = wkWebView.title;
+    BOOL reload = ((title == nil) || [title isEqualToString:@""]);
+
+#ifdef DEBUG
+    NSLog(@"%@", @"CDVWKWebViewEngine reloadIfRequired");
+    NSLog(@"CDVWKWebViewEngine reloadIfRequired WKWebView.title: %@", title);
+    NSLog(@"CDVWKWebViewEngine reloadIfRequired reload: %u", reload);
+#endif
+
+    if (reload) {
+        NSLog(@"%@", @"CDVWKWebViewEngine reloading!");
+        [wkWebView reload];
+    }
+    return reload;
 }
 
 - (id)loadRequest:(NSURLRequest*)request
@@ -130,7 +160,7 @@
 {
     // See: https://issues.apache.org/jira/browse/CB-9636
     SEL wk_sel = NSSelectorFromString(CDV_WKWEBVIEW_FILE_URL_LOAD_SELECTOR);
-    
+
     // if it's a file URL, check whether WKWebView has the selector (which is in iOS 9 and up only)
     if (request.URL.fileURL) {
         return [_engineWebView respondsToSelector:wk_sel];
@@ -153,10 +183,10 @@
      wkWebView.configuration.preferences.javaScriptEnabled = [settings cordovaBoolSettingForKey:@"JavaScriptEnabled" default:YES];
      wkWebView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = [settings cordovaBoolSettingForKey:@"JavaScriptCanOpenWindowsAutomatically" default:NO];
      */
-    
+
     // By default, DisallowOverscroll is false (thus bounce is allowed)
     BOOL bounceAllowed = !([settings cordovaBoolSettingForKey:@"DisallowOverscroll" defaultValue:NO]);
-    
+
     // prevent webView from bouncing
     if (!bounceAllowed) {
         if ([wkWebView respondsToSelector:@selector(scrollView)]) {
@@ -249,7 +279,7 @@
         NSData* jsonData = [NSJSONSerialization dataWithJSONObject:jsonEntry
                                                            options:0
                                                              error:&error];
-        
+
         if (error == nil) {
             commandJson = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
         }
@@ -275,7 +305,7 @@
 {
     CDVViewController* vc = (CDVViewController*)self.viewController;
     [CDVUserAgentUtil releaseLock:vc.userAgentLockToken];
-    
+
     [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPageDidLoadNotification object:webView]];
 }
 
@@ -283,10 +313,10 @@
 {
     CDVViewController* vc = (CDVViewController*)self.viewController;
     [CDVUserAgentUtil releaseLock:vc.userAgentLockToken];
-    
+
     NSString* message = [NSString stringWithFormat:@"Failed to load webpage with error: %@", [error localizedDescription]];
     NSLog(@"%@", message);
-    
+
     NSURL* errorUrl = vc.errorURL;
     if (errorUrl) {
         errorUrl = [NSURL URLWithString:[NSString stringWithFormat:@"?error=%@", [message stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] relativeToURL:errorUrl];
@@ -306,7 +336,7 @@
     if ([url isFileURL]) {
         return YES;
     }
-    
+
     return NO;
 }
 
@@ -314,13 +344,13 @@
 {
     NSURL* url = [navigationAction.request URL];
     CDVViewController* vc = (CDVViewController*)self.viewController;
-    
+
     /*
      * Give plugins the chance to handle the url
      */
     BOOL anyPluginsResponded = NO;
     BOOL shouldAllowRequest = NO;
-    
+
     for (NSString* pluginName in vc.pluginObjects) {
         CDVPlugin* plugin = [vc.pluginObjects objectForKey:pluginName];
         SEL selector = NSSelectorFromString(@"shouldOverrideLoadWithRequest:navigationType:");
@@ -332,11 +362,11 @@
             }
         }
     }
-    
+
     if (anyPluginsResponded) {
         return decisionHandler(shouldAllowRequest);
     }
-    
+
     /*
      * Handle all other types of urls (tel:, sms:), and requests to load a url in the main webview.
      */
@@ -346,7 +376,7 @@
     } else {
         [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:CDVPluginHandleOpenURLNotification object:url]];
     }
-    
+
     return decisionHandler(NO);
 }
 @end