abroa01 commented on issue #1355:
URL: https://github.com/apache/cordova-ios/issues/1355#issuecomment-3206769454

   ## Update on our findings
   
   We've been investigating this issue and have successfully implemented a 
workaround that's preventing the white screen problem in our app. I wanted to 
share our findings with the community.
   
   ### What we discovered
   
   Looking at the logs when the WebKit process crashes, we can confirm that 
`webViewWebContentProcessDidTerminate` IS being called in our case:
   
   ```
   0x112009420 - [PID=15090] WebProcessProxy::didClose: (web process 0 crash)
   0x113834e18 - [pageProxyID=19, webPageID=20, PID=15090] 
WebPageProxy::processDidTerminate: (pid 15090), reason=Crash
   CDVWebViewEngine: Inside webViewWebContentProcessDidTerminate - Web content 
process terminated, reloading with cached URL
   CDVWebViewEngine : Inside webViewWebContentProcessDidTerminate - using 
cached good URL for process termination reload: 
http://localhost:12280/?cdvToken=...
   ```
   
   However, we also see that `shouldReloadWebView` is still being called 
periodically and returning 0 (false), confirming the original bug about the 
flawed nil checking logic:
   
   ```
   CDVWebViewEngine shouldReloadWebView::
   CDVWebViewEngine shouldReloadWebView title: Meteor App
   CDVWebViewEngine shouldReloadWebView location: 
http://localhost:12280/register
   CDVWebViewEngine shouldReloadWebView reload: 0
   ```
   
   <img width="2892" height="1154" alt="Image" 
src="https://github.com/user-attachments/assets/7d4c9957-802e-4a26-898c-09325663a0c6";
 />
   
   ### Our solution: Last good URL caching mechanism
   
   We've implemented a URL caching approach that stores successful page loads 
and uses them during recovery scenarios. Here are the key changes to 
`CDVWebViewEngine.m`:
   
   #### 1. Cache successful navigations
   ```objc
   - (void)webView:(WKWebView*)webView 
didFinishNavigation:(WKNavigation*)navigation
   {
       // Always cache successful URL loads
       if (webView.URL && ![webView.URL.absoluteString 
isEqualToString:@"about:blank"] && ![webView.URL.absoluteString 
isEqualToString:@""]) {
           self.lastGoodURL = webView.URL;
           NSLog(@"CDVWebViewEngine cached good URL: %@", 
webView.URL.absoluteString);
       }
       
       [[NSNotificationCenter defaultCenter] postNotification:[NSNotification 
notificationWithName:CDVPageDidLoadNotification object:webView]];
   }
   ```
   
   #### 2. Enhanced recovery in webViewWebContentProcessDidTerminate
   ```objc
   - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView
   {
       NSLog(@"CDVWebViewEngine: Inside webViewWebContentProcessDidTerminate - 
Web content process terminated, reloading with cached URL");
       
       NSURL* currentURL = webView.URL;
       NSURL* url;
       
       if (self.lastGoodURL) {
           url = self.lastGoodURL;  // Priority 1: Last known good URL
           NSLog(@"CDVWebViewEngine : Inside 
webViewWebContentProcessDidTerminate - using cached good URL for process 
termination reload: %@", url.absoluteString);
       } else if (currentURL && ![currentURL.absoluteString 
isEqualToString:@"about:blank"] && ![currentURL.absoluteString 
isEqualToString:@""]) {
           url = currentURL;  // Priority 2: Current URL
           NSLog(@"CDVWebViewEngine : Inside 
webViewWebContentProcessDidTerminate - using current page URL for process 
termination reload: %@", url.absoluteString);
       } else {
           url = [((CDVViewController*) self.viewController) appUrl];  // 
Priority 3: App URL
           NSLog(@"CDVWebViewEngine : Inside 
webViewWebContentProcessDidTerminate - using fallback app URL for process 
termination reload: %@", url.absoluteString);
       }
       
       NSURLRequest* appReq = [NSURLRequest requestWithURL:url 
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
       [webView loadRequest:appReq];
   }
   ```
   
   #### 3. Same approach for onAppWillEnterForeground
   ```objc
   - (void) onAppWillEnterForeground:(NSNotification*)notification {
       if ([self shouldReloadWebView]) {
           NSLog(@"%@", @"CDVWebViewEngine reloading!");
           
           WKWebView* wkWebView = (WKWebView*)_engineWebView;
           NSURL* currentURL = wkWebView.URL;
           
           NSURL* url;
           if (self.lastGoodURL) {
               url = self.lastGoodURL;
               NSLog(@"CDVWebViewEngine using cached good URL for reload: %@", 
url.absoluteString);
           } else if (currentURL && ![currentURL.absoluteString 
isEqualToString:@"about:blank"] && ![currentURL.absoluteString 
isEqualToString:@""]) {
               url = currentURL;
               NSLog(@"CDVWebViewEngine using current page URL for reload: %@", 
url.absoluteString);
           } else {
               url = [((CDVViewController*) self.viewController) appUrl];
               NSLog(@"CDVWebViewEngine using fallback app URL for reload: %@", 
url.absoluteString);
           }
           
           NSURLRequest* appReq = [NSURLRequest requestWithURL:url 
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
           [wkWebView loadRequest:appReq];
       }
   }
   ```
   
   #### 4. Additional safety in shouldReloadWebView
   ```objc
   - (BOOL)shouldReloadWebView:(NSURL*)location title:(NSString*)title
   {
       BOOL title_is_nil = (title == nil) || [title isEqualToString:@""];
       BOOL location_is_blank = [[location absoluteString] 
isEqualToString:@"about:blank"];
       
       BOOL reload = (title_is_nil || location_is_blank);
       
       // Debug logs showing the evaluation
       NSLog(@"CDVWebViewEngine shouldReloadWebView::");
       NSLog(@"CDVWebViewEngine shouldReloadWebView title: %@", title);
       NSLog(@"CDVWebViewEngine shouldReloadWebView location: %@", [location 
absoluteString]);
       NSLog(@"CDVWebViewEngine shouldReloadWebView reload: %u", reload);
       
       return reload;
   }
   ```
   
   ### What the logs prove
   
   From our test session logs:
   1. **WebKit process crashes**: `WebProcessProxy::didClose: (web process 0 
crash)`
   2. **Our handler fires immediately**: `CDVWebViewEngine: Inside 
webViewWebContentProcessDidTerminate`
   3. **Successfully recovers using cached URL**: `using cached good URL for 
process termination reload: http://localhost:12280/?cdvToken=...`
   4. **App reloads without white screen** ✓
   
   
   
   
   This recovery mechanism triggered multiple times during our testing (you can 
see multiple crash/recovery cycles in the logs), and the app successfully 
recovered each time.
   
   ### Results
   
   With these changes, our app now successfully recovers from WebKit process 
terminations without showing the white screen. The app reloads to the last 
known good state instead of getting stuck.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@cordova.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@cordova.apache.org
For additional commands, e-mail: issues-h...@cordova.apache.org

Reply via email to