Index: ios/web/web_state/ui/crw_wk_web_view_web_controller.mm |
diff --git a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm |
index c77f15bce9fadc62ccb29dfc177eabadb8bd922c..91c0383cb32df88ff5aab126a2cffbad1988fe43 100644 |
--- a/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm |
+++ b/ios/web/web_state/ui/crw_wk_web_view_web_controller.mm |
@@ -51,6 +51,30 @@ NSString* GetRefererFromNavigationAction(WKNavigationAction* action) { |
NSString* const kScriptMessageName = @"crwebinvoke"; |
NSString* const kScriptImmediateName = @"crwebinvokeimmediate"; |
+// Utility functions for storing the source of NSErrors received by WKWebViews: |
+// - Errors received by |-webView:didFailProvisionalNavigation:withError:| are |
+// recorded using WKWebViewErrorSource::PROVISIONAL_LOAD. These should be |
+// aborted. |
+// - Errors received by |-webView:didFailNavigation:withError:| are recorded |
+// using WKWebViewsource::NAVIGATION. These errors should not be aborted, as |
+// the WKWebView will automatically retry the load. |
+NSString* const kWKWebViewErrorSourceKey = @"ErrorSource"; |
+typedef enum { NONE = 0, PROVISIONAL_LOAD, NAVIGATION } WKWebViewErrorSource; |
+NSError* WKWebViewErrorWithSource(NSError* error, WKWebViewErrorSource source) { |
+ DCHECK(error); |
+ base::scoped_nsobject<NSMutableDictionary> userInfo( |
+ [error.userInfo mutableCopy]); |
+ [userInfo setValue:@(source) forKey:kWKWebViewErrorSourceKey]; |
Eugene But (OOO till 7-30)
2015/06/23 21:27:14
s/setValue/setObject
kkhorimoto
2015/06/24 20:01:42
Done.
|
+ return [NSError errorWithDomain:error.domain |
+ code:error.code |
+ userInfo:userInfo]; |
+} |
+WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
+ DCHECK(error); |
+ return static_cast<WKWebViewErrorSource>( |
+ [error.userInfo[kWKWebViewErrorSourceKey] integerValue]); |
+} |
+ |
} // namespace |
@interface CRWWKWebViewWebController () <WKNavigationDelegate, |
@@ -412,10 +436,18 @@ NSString* const kScriptImmediateName = @"crwebinvokeimmediate"; |
self.webScrollView.zoomScale = zoomScale; |
} |
-- (BOOL)shouldAbortLoadForCancelledURL:(const GURL&)cancelledURL { |
+- (BOOL)shouldAbortLoadForCancelledError:(NSError*)cancelledError { |
+ DCHECK_EQ(cancelledError.code, NSURLErrorCancelled); |
// Do not abort the load if it is for an app specific URL, as such errors |
// are produced during the app specific URL load process. |
- return !web::GetWebClient()->IsAppSpecificURL(cancelledURL); |
+ const GURL errorURL = |
+ net::GURLWithNSURL(cancelledError.userInfo[NSURLErrorFailingURLErrorKey]); |
+ BOOL isAppSpecificURL = web::GetWebClient()->IsAppSpecificURL(errorURL); |
+ // Don't abort NSURLErrorCancelled errors originating from navigation, as the |
Eugene But (OOO till 7-30)
2015/06/23 21:27:14
Early return here:
if (isAppSpecificURL)
return
kkhorimoto
2015/06/24 20:01:42
Done.
|
+ // WKWebView will automatically retry these loads. |
+ WKWebViewErrorSource source = WKWebViewErrorSourceFromError(cancelledError); |
+ BOOL isFromNavigation = source == NAVIGATION; |
+ return !isFromNavigation && !isAppSpecificURL; |
} |
#pragma mark Private methods |
@@ -1013,6 +1045,7 @@ NSString* const kScriptImmediateName = @"crwebinvokeimmediate"; |
withError:(NSError *)error { |
[self discardPendingReferrerString]; |
+ error = WKWebViewErrorWithSource(error, PROVISIONAL_LOAD); |
#if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) |
if (web::IsWKWebViewSSLError(error)) |
[self handleSSLError:error]; |
@@ -1056,7 +1089,8 @@ NSString* const kScriptImmediateName = @"crwebinvokeimmediate"; |
- (void)webView:(WKWebView *)webView |
didFailNavigation:(WKNavigation *)navigation |
withError:(NSError *)error { |
- [self handleLoadError:error inMainFrame:YES]; |
+ [self handleLoadError:WKWebViewErrorWithSource(error, NAVIGATION) |
+ inMainFrame:YES]; |
} |
- (void)webView:(WKWebView *)webView |