| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "ios/web/web_state/ui/crw_wk_web_view_web_controller.h" | 5 #import "ios/web/web_state/ui/crw_wk_web_view_web_controller.h" |
| 6 | 6 |
| 7 #import <WebKit/WebKit.h> | 7 #import <WebKit/WebKit.h> |
| 8 | 8 |
| 9 #include "base/ios/ios_util.h" | 9 #include "base/ios/ios_util.h" |
| 10 #include "base/ios/weak_nsobject.h" | 10 #include "base/ios/weak_nsobject.h" |
| 11 #include "base/json/json_reader.h" | 11 #include "base/json/json_reader.h" |
| 12 #import "base/mac/scoped_nsobject.h" | 12 #import "base/mac/scoped_nsobject.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
| 15 #include "base/values.h" | 15 #include "base/values.h" |
| 16 #import "ios/net/http_response_headers_util.h" | 16 #import "ios/net/http_response_headers_util.h" |
| 17 #import "ios/web/crw_network_activity_indicator_manager.h" | 17 #import "ios/web/crw_network_activity_indicator_manager.h" |
| 18 #import "ios/web/navigation/crw_session_controller.h" | 18 #import "ios/web/navigation/crw_session_controller.h" |
| 19 #import "ios/web/navigation/crw_session_entry.h" | 19 #import "ios/web/navigation/crw_session_entry.h" |
| 20 #include "ios/web/navigation/navigation_item_impl.h" | 20 #include "ios/web/navigation/navigation_item_impl.h" |
| 21 #include "ios/web/navigation/web_load_params.h" | 21 #include "ios/web/navigation/web_load_params.h" |
| 22 #include "ios/web/net/cert_verification_cache.h" |
| 22 #import "ios/web/net/crw_cert_verification_controller.h" | 23 #import "ios/web/net/crw_cert_verification_controller.h" |
| 23 #include "ios/web/public/cert_store.h" | 24 #include "ios/web/public/cert_store.h" |
| 24 #include "ios/web/public/navigation_item.h" | 25 #include "ios/web/public/navigation_item.h" |
| 25 #include "ios/web/public/ssl_status.h" | 26 #include "ios/web/public/ssl_status.h" |
| 26 #include "ios/web/public/web_client.h" | 27 #include "ios/web/public/web_client.h" |
| 27 #import "ios/web/public/web_state/js/crw_js_injection_manager.h" | 28 #import "ios/web/public/web_state/js/crw_js_injection_manager.h" |
| 28 #import "ios/web/public/web_state/ui/crw_native_content_provider.h" | 29 #import "ios/web/public/web_state/ui/crw_native_content_provider.h" |
| 29 #import "ios/web/public/web_state/ui/crw_web_view_content_view.h" | 30 #import "ios/web/public/web_state/ui/crw_web_view_content_view.h" |
| 30 #import "ios/web/ui_web_view_util.h" | 31 #import "ios/web/ui_web_view_util.h" |
| 31 #include "ios/web/web_state/blocked_popup_info.h" | 32 #include "ios/web/web_state/blocked_popup_info.h" |
| 32 #import "ios/web/web_state/error_translation_util.h" | 33 #import "ios/web/web_state/error_translation_util.h" |
| 33 #include "ios/web/web_state/frame_info.h" | 34 #include "ios/web/web_state/frame_info.h" |
| 34 #import "ios/web/web_state/js/crw_js_window_id_manager.h" | 35 #import "ios/web/web_state/js/crw_js_window_id_manager.h" |
| 35 #import "ios/web/web_state/js/page_script_util.h" | 36 #import "ios/web/web_state/js/page_script_util.h" |
| 36 #import "ios/web/web_state/ui/crw_web_controller+protected.h" | 37 #import "ios/web/web_state/ui/crw_web_controller+protected.h" |
| 37 #import "ios/web/web_state/ui/crw_wk_web_view_crash_detector.h" | 38 #import "ios/web/web_state/ui/crw_wk_web_view_crash_detector.h" |
| 38 #import "ios/web/web_state/ui/web_view_js_utils.h" | 39 #import "ios/web/web_state/ui/web_view_js_utils.h" |
| 39 #import "ios/web/web_state/ui/wk_back_forward_list_item_holder.h" | 40 #import "ios/web/web_state/ui/wk_back_forward_list_item_holder.h" |
| 40 #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" | 41 #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" |
| 41 #import "ios/web/web_state/web_state_impl.h" | 42 #import "ios/web/web_state/web_state_impl.h" |
| 42 #import "ios/web/web_state/web_view_internal_creation_util.h" | 43 #import "ios/web/web_state/web_view_internal_creation_util.h" |
| 43 #import "ios/web/web_state/wk_web_view_security_util.h" | 44 #import "ios/web/web_state/wk_web_view_security_util.h" |
| 44 #import "ios/web/webui/crw_web_ui_manager.h" | 45 #import "ios/web/webui/crw_web_ui_manager.h" |
| 45 #include "net/cert/x509_certificate.h" | 46 #include "net/cert/x509_certificate.h" |
| 46 #import "net/base/mac/url_conversions.h" | 47 #import "net/base/mac/url_conversions.h" |
| 47 #include "net/ssl/ssl_info.h" | 48 #include "net/ssl/ssl_info.h" |
| 48 #include "url/url_constants.h" | 49 #include "url/url_constants.h" |
| 49 | 50 |
| 50 namespace { | 51 namespace { |
| 52 |
| 53 // Represents cert verification error, which happened inside |
| 54 // |webView:didReceiveAuthenticationChallenge:completionHandler:| and should |
| 55 // be checked inside |webView:didFailProvisionalNavigation:withError:|. |
| 56 struct CertVerificationError { |
| 57 BOOL is_recoverable; |
| 58 net::CertStatus status; |
| 59 }; |
| 60 |
| 51 // Extracts Referer value from WKNavigationAction request header. | 61 // Extracts Referer value from WKNavigationAction request header. |
| 52 NSString* GetRefererFromNavigationAction(WKNavigationAction* action) { | 62 NSString* GetRefererFromNavigationAction(WKNavigationAction* action) { |
| 53 return [action.request valueForHTTPHeaderField:@"Referer"]; | 63 return [action.request valueForHTTPHeaderField:@"Referer"]; |
| 54 } | 64 } |
| 55 | 65 |
| 56 NSString* const kScriptMessageName = @"crwebinvoke"; | 66 NSString* const kScriptMessageName = @"crwebinvoke"; |
| 57 NSString* const kScriptImmediateName = @"crwebinvokeimmediate"; | 67 NSString* const kScriptImmediateName = @"crwebinvokeimmediate"; |
| 58 | 68 |
| 59 // Utility functions for storing the source of NSErrors received by WKWebViews: | 69 // Utility functions for storing the source of NSErrors received by WKWebViews: |
| 60 // - Errors received by |-webView:didFailProvisionalNavigation:withError:| are | 70 // - Errors received by |-webView:didFailProvisionalNavigation:withError:| are |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 // bad SSL cert, presenting SSL interstitials and determining SSL status for | 148 // bad SSL cert, presenting SSL interstitials and determining SSL status for |
| 139 // Navigation Items. | 149 // Navigation Items. |
| 140 base::scoped_nsobject<CRWCertVerificationController> | 150 base::scoped_nsobject<CRWCertVerificationController> |
| 141 _certVerificationController; | 151 _certVerificationController; |
| 142 | 152 |
| 143 // Whether the pending navigation has been directly cancelled in | 153 // Whether the pending navigation has been directly cancelled in |
| 144 // |decidePolicyForNavigationAction| or |decidePolicyForNavigationResponse|. | 154 // |decidePolicyForNavigationAction| or |decidePolicyForNavigationResponse|. |
| 145 // Cancelled navigations should be simply discarded without handling any | 155 // Cancelled navigations should be simply discarded without handling any |
| 146 // specific error. | 156 // specific error. |
| 147 BOOL _pendingNavigationCancelled; | 157 BOOL _pendingNavigationCancelled; |
| 158 |
| 159 // CertVerification errors which happened inside |
| 160 // |webView:didReceiveAuthenticationChallenge:completionHandler:|. |
| 161 // Key is leaf-cert - host pair. This storage is used to carry calculated |
| 162 // cert status from |didReceiveAuthenticationChallenge:| to |
| 163 // |didFailProvisionalNavigation:| delegate method. |
| 164 web::CertVerificationCache<CertVerificationError> _certVerificationErrors; |
| 148 } | 165 } |
| 149 | 166 |
| 150 // Response's MIME type of the last known navigation. | 167 // Response's MIME type of the last known navigation. |
| 151 @property(nonatomic, copy) NSString* documentMIMEType; | 168 @property(nonatomic, copy) NSString* documentMIMEType; |
| 152 | 169 |
| 153 // Dictionary where keys are the names of WKWebView properties and values are | 170 // Dictionary where keys are the names of WKWebView properties and values are |
| 154 // selector names which should be called when a corresponding property has | 171 // selector names which should be called when a corresponding property has |
| 155 // changed. e.g. @{ @"URL" : @"webViewURLDidChange" } means that | 172 // changed. e.g. @{ @"URL" : @"webViewURLDidChange" } means that |
| 156 // -[self webViewURLDidChange] must be called every time when WKWebView.URL is | 173 // -[self webViewURLDidChange] must be called every time when WKWebView.URL is |
| 157 // changed. | 174 // changed. |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 } | 567 } |
| 551 return [super URLForHistoryNavigationFromItem:fromItem toItem:toItem]; | 568 return [super URLForHistoryNavigationFromItem:fromItem toItem:toItem]; |
| 552 } | 569 } |
| 553 | 570 |
| 554 - (void)setPageChangeProbability:(web::PageChangeProbability)probability { | 571 - (void)setPageChangeProbability:(web::PageChangeProbability)probability { |
| 555 // Nothing to do; no polling timer. | 572 // Nothing to do; no polling timer. |
| 556 } | 573 } |
| 557 | 574 |
| 558 - (void)abortWebLoad { | 575 - (void)abortWebLoad { |
| 559 [_wkWebView stopLoading]; | 576 [_wkWebView stopLoading]; |
| 577 _certVerificationErrors.reset(); |
| 560 } | 578 } |
| 561 | 579 |
| 562 - (void)resetLoadState { | 580 - (void)resetLoadState { |
| 563 // Nothing to do. | 581 // Nothing to do. |
| 564 } | 582 } |
| 565 | 583 |
| 566 - (void)setSuppressDialogsWithHelperScript:(NSString*)script { | 584 - (void)setSuppressDialogsWithHelperScript:(NSString*)script { |
| 567 [self evaluateJavaScript:script stringResultHandler:nil]; | 585 [self evaluateJavaScript:script stringResultHandler:nil]; |
| 568 } | 586 } |
| 569 | 587 |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 sourceURL:sourceURL | 854 sourceURL:sourceURL |
| 837 referrerPolicy:base::SysNSStringToUTF8(policy)]; | 855 referrerPolicy:base::SysNSStringToUTF8(policy)]; |
| 838 }]; | 856 }]; |
| 839 }); | 857 }); |
| 840 } | 858 } |
| 841 | 859 |
| 842 #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) | 860 #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) |
| 843 - (void)handleSSLError:(NSError*)error { | 861 - (void)handleSSLError:(NSError*)error { |
| 844 DCHECK(web::IsWKWebViewSSLError(error)); | 862 DCHECK(web::IsWKWebViewSSLError(error)); |
| 845 | 863 |
| 846 net::SSLInfo sslInfo; | 864 net::SSLInfo SSLInfo; |
| 847 web::GetSSLInfoFromWKWebViewSSLError(error, &sslInfo); | 865 web::GetSSLInfoFromWKWebViewSSLError(error, &SSLInfo); |
| 848 | 866 |
| 849 web::SSLStatus sslStatus; | 867 web::SSLStatus SSLStatus; |
| 850 sslStatus.security_style = web::SECURITY_STYLE_AUTHENTICATION_BROKEN; | 868 SSLStatus.security_style = web::SECURITY_STYLE_AUTHENTICATION_BROKEN; |
| 851 sslStatus.cert_status = sslInfo.cert_status; | 869 SSLStatus.cert_status = SSLInfo.cert_status; |
| 852 sslStatus.cert_id = web::CertStore::GetInstance()->StoreCert( | 870 SSLStatus.cert_id = web::CertStore::GetInstance()->StoreCert( |
| 853 sslInfo.cert.get(), self.certGroupID); | 871 SSLInfo.cert.get(), self.certGroupID); |
| 854 | 872 |
| 855 [self.delegate presentSSLError:sslInfo | 873 NSArray* chain = error.userInfo[web::kNSErrorPeerCertificateChainKey]; |
| 856 forSSLStatus:sslStatus | 874 NSString* host = [error.userInfo[web::kNSErrorFailingURLKey] host]; |
| 857 recoverable:NO | 875 // Verification results are cached for leaf cert, because cert chain in |
| 858 callback:nullptr]; | 876 // |didReceiveAuthenticationChallenge:| maybe different from |chain|. |
| 877 scoped_refptr<net::X509Certificate> leafCert; |
| 878 BOOL recoverable = NO; |
| 879 if (chain.count && host.length) { |
| 880 // Complete cert chain may not be available inside this method, so leaf |
| 881 // cert is used as a key to retrieve _certVerificationErrors as well as for |
| 882 // storing cert decision. |
| 883 leafCert = web::CreateCertFromChain(@[ [chain firstObject] ]); |
| 884 if (leafCert) { |
| 885 CertVerificationError error; |
| 886 if (_certVerificationErrors.get(leafCert, base::SysNSStringToUTF8(host), |
| 887 &error)) { |
| 888 SSLStatus.cert_status = error.status; |
| 889 recoverable = error.is_recoverable; |
| 890 } |
| 891 } |
| 892 } |
| 893 [self.delegate presentSSLError:SSLInfo |
| 894 forSSLStatus:SSLStatus |
| 895 recoverable:recoverable |
| 896 callback:^(BOOL proceed) { |
| 897 if (proceed) { |
| 898 // The interstitial will be removed during reload. |
| 899 [_certVerificationController |
| 900 allowCert:leafCert |
| 901 forHost:host |
| 902 status:SSLStatus.cert_status]; |
| 903 [self loadCurrentURL]; |
| 904 } |
| 905 }]; |
| 906 _certVerificationErrors.reset(); |
| 859 } | 907 } |
| 860 #endif // #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) | 908 #endif // #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) |
| 861 | 909 |
| 862 - (void)addActivityIndicatorTask { | 910 - (void)addActivityIndicatorTask { |
| 863 [[CRWNetworkActivityIndicatorManager sharedInstance] | 911 [[CRWNetworkActivityIndicatorManager sharedInstance] |
| 864 startNetworkTaskForGroup:[self activityIndicatorGroupID]]; | 912 startNetworkTaskForGroup:[self activityIndicatorGroupID]]; |
| 865 } | 913 } |
| 866 | 914 |
| 867 - (void)clearActivityIndicatorTasks { | 915 - (void)clearActivityIndicatorTasks { |
| 868 [[CRWNetworkActivityIndicatorManager sharedInstance] | 916 [[CRWNetworkActivityIndicatorManager sharedInstance] |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1393 else | 1441 else |
| 1394 #endif | 1442 #endif |
| 1395 [self handleLoadError:error inMainFrame:YES]; | 1443 [self handleLoadError:error inMainFrame:YES]; |
| 1396 | 1444 |
| 1397 [self discardPendingNavigationTypeForMainFrame]; | 1445 [self discardPendingNavigationTypeForMainFrame]; |
| 1398 } | 1446 } |
| 1399 | 1447 |
| 1400 - (void)webView:(WKWebView *)webView | 1448 - (void)webView:(WKWebView *)webView |
| 1401 didCommitNavigation:(WKNavigation *)navigation { | 1449 didCommitNavigation:(WKNavigation *)navigation { |
| 1402 DCHECK_EQ(_wkWebView, webView); | 1450 DCHECK_EQ(_wkWebView, webView); |
| 1451 _certVerificationErrors.reset(); |
| 1403 // This point should closely approximate the document object change, so reset | 1452 // This point should closely approximate the document object change, so reset |
| 1404 // the list of injected scripts to those that are automatically injected. | 1453 // the list of injected scripts to those that are automatically injected. |
| 1405 _injectedScriptManagers.reset([[NSMutableSet alloc] init]); | 1454 _injectedScriptManagers.reset([[NSMutableSet alloc] init]); |
| 1406 [self injectWindowID]; | 1455 [self injectWindowID]; |
| 1407 | 1456 |
| 1408 // The page has changed; commit the pending referrer. | 1457 // The page has changed; commit the pending referrer. |
| 1409 [self commitPendingReferrerString]; | 1458 [self commitPendingReferrerString]; |
| 1410 | 1459 |
| 1411 // This is the point where the document's URL has actually changed. | 1460 // This is the point where the document's URL has actually changed. |
| 1412 _documentURL = net::GURLWithNSURL([_wkWebView URL]); | 1461 _documentURL = net::GURLWithNSURL([_wkWebView URL]); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1443 completionHandler: | 1492 completionHandler: |
| 1444 (void (^)(NSURLSessionAuthChallengeDisposition disposition, | 1493 (void (^)(NSURLSessionAuthChallengeDisposition disposition, |
| 1445 NSURLCredential *credential))completionHandler { | 1494 NSURLCredential *credential))completionHandler { |
| 1446 if (![challenge.protectionSpace.authenticationMethod | 1495 if (![challenge.protectionSpace.authenticationMethod |
| 1447 isEqual:NSURLAuthenticationMethodServerTrust]) { | 1496 isEqual:NSURLAuthenticationMethodServerTrust]) { |
| 1448 completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); | 1497 completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); |
| 1449 return; | 1498 return; |
| 1450 } | 1499 } |
| 1451 | 1500 |
| 1452 SecTrustRef trust = challenge.protectionSpace.serverTrust; | 1501 SecTrustRef trust = challenge.protectionSpace.serverTrust; |
| 1453 scoped_refptr<net::X509Certificate> cert = web::CreateCertFromTrust(trust); | 1502 base::WeakNSObject<CRWWKWebViewWebController> weakSelf(self); |
| 1503 id handler = ^(web::CertAcceptPolicy policy, net::CertStatus status) { |
| 1504 base::scoped_nsobject<CRWWKWebViewWebController> strongSelf( |
| 1505 [weakSelf retain]); |
| 1506 if (!strongSelf) { |
| 1507 return; |
| 1508 } |
| 1509 |
| 1510 if (policy == web::CERT_ACCEPT_POLICY_RECOVERABLE_ERROR_ACCEPTED_BY_USER) { |
| 1511 // cert is invalid, but user agreed to proceed. |
| 1512 completionHandler(NSURLSessionAuthChallengeUseCredential, |
| 1513 [NSURLCredential credentialForTrust:trust]); |
| 1514 } else { |
| 1515 if (policy != web::CERT_ACCEPT_POLICY_ALLOW) { |
| 1516 // cert is invalid and user has not agreed to proceed. |
| 1517 |
| 1518 // Cache cert verification result with _certVerificationErrors storage, |
| 1519 // so it can be later reused inside |didFailProvisionalNavigation:|. |
| 1520 // didFailProvisionalNavigation: does not receive full cert chain and it |
| 1521 // will not be possible to resulculate cert status there. |
| 1522 if (SecTrustGetCertificateCount(trust)) { |
| 1523 // Leaf cert (w/o any intermidiates) is used for caching. |
| 1524 // Chain inside |didFailProvisionalNavigation:| may be different and |
| 1525 // using intermidiates will result in keys mismatch. |
| 1526 scoped_refptr<net::X509Certificate> leafCert = |
| 1527 web::CreateCertFromChain(@[ |
| 1528 static_cast<id>(SecTrustGetCertificateAtIndex(trust, 0)) |
| 1529 ]); |
| 1530 if (leafCert) { |
| 1531 BOOL is_recoverable = |
| 1532 policy == |
| 1533 web::CERT_ACCEPT_POLICY_RECOVERABLE_ERROR_NOT_ACCEPTED_BY_USER; |
| 1534 strongSelf.get()->_certVerificationErrors.set( |
| 1535 leafCert, |
| 1536 base::SysNSStringToUTF8(challenge.protectionSpace.host), |
| 1537 {is_recoverable, status}); |
| 1538 } |
| 1539 } |
| 1540 } |
| 1541 completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil); |
| 1542 } |
| 1543 }; |
| 1544 |
| 1454 [_certVerificationController | 1545 [_certVerificationController |
| 1455 decidePolicyForCert:cert | 1546 decideLoadPolicyForTrust:trust |
| 1456 host:challenge.protectionSpace.host | 1547 host:challenge.protectionSpace.host |
| 1457 completionHandler:^(web::CertAcceptPolicy policy, | 1548 completionHandler:handler]; |
| 1458 net::CertStatus status) { | |
| 1459 completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, | |
| 1460 nil); | |
| 1461 }]; | |
| 1462 } | 1549 } |
| 1463 | 1550 |
| 1464 - (void)webViewWebContentProcessDidTerminate:(WKWebView*)webView { | 1551 - (void)webViewWebContentProcessDidTerminate:(WKWebView*)webView { |
| 1465 [self webViewWebProcessDidCrash]; | 1552 [self webViewWebProcessDidCrash]; |
| 1466 } | 1553 } |
| 1467 | 1554 |
| 1468 #pragma mark WKUIDelegate Methods | 1555 #pragma mark WKUIDelegate Methods |
| 1469 | 1556 |
| 1470 - (WKWebView*)webView:(WKWebView*)webView | 1557 - (WKWebView*)webView:(WKWebView*)webView |
| 1471 createWebViewWithConfiguration:(WKWebViewConfiguration*)configuration | 1558 createWebViewWithConfiguration:(WKWebViewConfiguration*)configuration |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1550 placeholderText:defaultText | 1637 placeholderText:defaultText |
| 1551 requestURL: | 1638 requestURL: |
| 1552 net::GURLWithNSURL(frame.request.URL) | 1639 net::GURLWithNSURL(frame.request.URL) |
| 1553 completionHandler:completionHandler]; | 1640 completionHandler:completionHandler]; |
| 1554 } else if (completionHandler) { | 1641 } else if (completionHandler) { |
| 1555 completionHandler(nil); | 1642 completionHandler(nil); |
| 1556 } | 1643 } |
| 1557 } | 1644 } |
| 1558 | 1645 |
| 1559 @end | 1646 @end |
| OLD | NEW |