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 5ae787dbf20cce84f9157427b54cd3def3be2cab..7ab0b1915f16c3d8d7b49255b4e7ba5b0cd7ab51 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 |
@@ -9,8 +9,10 @@ |
#include "base/ios/ios_util.h" |
#include "base/ios/weak_nsobject.h" |
#include "base/json/json_reader.h" |
+#include "base/mac/bind_objc_block.h" |
#import "base/mac/scoped_nsobject.h" |
#include "base/macros.h" |
+#import "base/memory/scoped_ptr.h" |
#include "base/strings/sys_string_conversions.h" |
#include "base/values.h" |
#import "ios/net/http_response_headers_util.h" |
@@ -19,7 +21,10 @@ |
#import "ios/web/navigation/crw_session_entry.h" |
#include "ios/web/navigation/navigation_item_impl.h" |
#include "ios/web/navigation/web_load_params.h" |
+#include "ios/web/net/cert_verifier_block_adapter.h" |
+#include "ios/web/public/browser_state.h" |
#include "ios/web/public/web_client.h" |
+#include "ios/web/public/web_thread.h" |
#import "ios/web/public/web_state/js/crw_js_injection_manager.h" |
#import "ios/web/public/web_state/ui/crw_native_content_provider.h" |
#import "ios/web/public/web_state/ui/crw_web_view_content_view.h" |
@@ -38,6 +43,9 @@ |
#import "ios/web/web_state/web_view_internal_creation_util.h" |
#import "ios/web/webui/crw_web_ui_manager.h" |
#import "net/base/mac/url_conversions.h" |
+#include "net/cert/cert_verify_result.h" |
+#include "net/ssl/ssl_config_service.h" |
+#include "net/url_request/url_request_context.h" |
#if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) |
#include "ios/web/public/cert_store.h" |
@@ -134,6 +142,12 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
// CRWWebUIManager object for loading WebUI pages. |
base::scoped_nsobject<CRWWebUIManager> _webUIManager; |
+ |
+ // Backs up property with the same name. |
+ scoped_ptr<web::CertVerifierBlockAdapter> _certVerifier; |
+ |
+ // URLRequestContextGetter for obtaining net layer objects. |
+ net::URLRequestContextGetter* _contextGetter; |
} |
// Response's MIME type of the last known navigation. |
@@ -154,6 +168,13 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
@property(nonatomic, readonly) int certGroupID; |
#endif // #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW) |
+// Cert verification flags. Must be called on IO Thread. |
stuartmorgan
2015/08/20 20:42:21
s/called/used/
Eugene But (OOO till 7-30)
2015/08/20 22:03:52
Done.
|
+@property(nonatomic, readonly) int certVerifyFlags; |
+ |
+// Cert verification object which wraps net::CertVerifier. Must be called on |
stuartmorgan
2015/08/20 20:42:21
same
Eugene But (OOO till 7-30)
2015/08/20 22:03:52
Done.
|
+// IO Thread. |
+@property(nonatomic, readonly) web::CertVerifierBlockAdapter* certVerifier; |
+ |
// Returns the WKWebViewConfigurationProvider associated with the web |
// controller's BrowserState. |
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider; |
@@ -249,6 +270,13 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
// Attempts to handle a script message. Returns YES on success, NO otherwise. |
- (BOOL)respondToWKScriptMessage:(WKScriptMessage*)scriptMessage; |
+// Verifies the given |cert| for the given |host| and calls |completionHandler| |
+// on completion. |completionHandler| can not be null and will be called |
stuartmorgan
2015/08/20 20:42:21
cannot
Eugene But (OOO till 7-30)
2015/08/20 22:03:52
Done.
|
+// asynchronously on the main thread. |
+- (void)verifyCert:(const scoped_refptr<net::X509Certificate>&)cert |
+ forHost:(NSString*)host |
+ completionHandler:(void (^)(net::CertVerifyResult, int))completionHandler; |
+ |
// Used to decide whether a load that generates errors with the |
// NSURLErrorCancelled code should be cancelled. |
- (BOOL)shouldAbortLoadForCancelledError:(NSError*)error; |
@@ -278,7 +306,13 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
#pragma mark CRWWebController public methods |
- (instancetype)initWithWebState:(scoped_ptr<web::WebStateImpl>)webState { |
- return [super initWithWebState:webState.Pass()]; |
+ DCHECK(webState); |
+ web::BrowserState* browserState = webState->GetBrowserState(); |
+ self = [super initWithWebState:webState.Pass()]; |
+ if (self) { |
+ _contextGetter = browserState->GetRequestContext(); |
+ } |
+ return self; |
} |
- (BOOL)keyboardDisplayRequiresUserAction { |
@@ -320,6 +354,15 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
[super setPageDialogOpenPolicy:policy]; |
} |
+- (void)close { |
+ // _certVerifier must be deleted on the same thread where it was created. |
+ if (_certVerifier) { |
+ web::WebThread::DeleteSoon(web::WebThread::IO, FROM_HERE, |
+ _certVerifier.release()); |
+ } |
+ [super close]; |
+} |
+ |
#pragma mark - |
#pragma mark Testing-Only Methods |
@@ -579,6 +622,30 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
} |
#endif |
+- (int)certVerifyFlags { |
+ DCHECK(web::WebThread::CurrentlyOn(web::WebThread::IO)); |
+ DCHECK(_contextGetter); |
+ net::URLRequestContext* context = _contextGetter->GetURLRequestContext(); |
+ DCHECK(context); |
+ net::SSLConfigService* SSLConfigService = context->ssl_config_service(); |
+ DCHECK(SSLConfigService); |
+ net::SSLConfig config; |
+ SSLConfigService->GetSSLConfig(&config); |
+ return config.GetCertVerifyFlags(); |
+} |
+ |
+- (web::CertVerifierBlockAdapter*)certVerifier { |
+ DCHECK(web::WebThread::CurrentlyOn(web::WebThread::IO)); |
+ if (!_certVerifier) { |
+ DCHECK(_contextGetter); |
+ net::URLRequestContext* context = _contextGetter->GetURLRequestContext(); |
+ DCHECK(context); |
+ _certVerifier.reset(new web::CertVerifierBlockAdapter( |
+ context->cert_verifier(), context->net_log())); |
+ } |
+ return _certVerifier.get(); |
+} |
+ |
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider { |
DCHECK(self.webStateImpl); |
web::BrowserState* browserState = self.webStateImpl->GetBrowserState(); |
@@ -952,6 +1019,35 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
: [super selectorToHandleJavaScriptCommand:command]; |
} |
+- (void)verifyCert:(const scoped_refptr<net::X509Certificate>&)cert |
+ forHost:(NSString*)host |
+ completionHandler:(void (^)(net::CertVerifyResult, int))completionHandler { |
+ DCHECK(completionHandler); |
+ __block scoped_refptr<net::X509Certificate> blockCert = cert; |
+ web::WebThread::PostTask( |
+ web::WebThread::IO, FROM_HERE, base::BindBlock(^{ |
+ // WeakNSObject does not work across different threads, hence this block |
+ // retains self. |
+ if ([self isBeingDestroyed]) { |
+ completionHandler(net::CertVerifyResult(), net::ERR_FAILED); |
+ return; |
+ } |
+ |
+ web::CertVerifierBlockAdapter::Params params( |
+ blockCert.Pass(), base::SysNSStringToUTF8(host)); |
+ params.flags = self.certVerifyFlags; |
+ params.crl_set = net::SSLConfigService::GetCRLSet(); |
+ // OCSP response is not provided by iOS API. |
+ |
+ self.certVerifier->Verify(params, |
+ ^(net::CertVerifyResult result, int error) { |
+ dispatch_async(dispatch_get_main_queue(), ^{ |
+ completionHandler(result, error); |
+ }); |
+ }); |
+ })); |
+} |
+ |
- (BOOL)shouldAbortLoadForCancelledError:(NSError*)error { |
DCHECK_EQ(error.code, NSURLErrorCancelled); |
// Do not abort the load if it is for an app specific URL, as such errors |
@@ -1290,8 +1386,25 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) { |
completionHandler: |
(void (^)(NSURLSessionAuthChallengeDisposition disposition, |
NSURLCredential *credential))completionHandler { |
- NOTIMPLEMENTED(); |
- completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil); |
+ if (![challenge.protectionSpace.authenticationMethod |
+ isEqual:NSURLAuthenticationMethodServerTrust]) { |
+ completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); |
+ return; |
+ } |
+ |
+ SecTrustRef trust = challenge.protectionSpace.serverTrust; |
+ scoped_refptr<net::X509Certificate> cert = web::CreateCertFromTrust(trust); |
+ [self verifyCert:cert |
+ forHost:challenge.protectionSpace.host |
+ completionHandler:^(net::CertVerifyResult, int error) { |
+ if (error == net::OK) { |
+ // Cert is valid. |
+ } else { |
+ // Cert is invalid or its state is unknown. |
+ } |
+ NOTIMPLEMENTED(); |
+ completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil); |
+ }]; |
} |
- (void)webViewWebContentProcessDidTerminate:(WKWebView*)webView { |