| 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 aa42be96a8bc1bbc14992c58d5130a30df9f8eae..8900c03b0f532def7b6931f7648eaaa41b4f1747 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,15 +9,20 @@
|
| #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"
|
| #import "ios/web/crw_network_activity_indicator_manager.h"
|
| #import "ios/web/navigation/crw_session_controller.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"
|
| @@ -35,6 +40,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"
|
| @@ -131,6 +139,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<net::CertVerifierBlockAdapter> _certVerifier;
|
| +
|
| + // URLRequestContextGetter for obtaining net layer objects.
|
| + net::URLRequestContextGetter* _contextGetter;
|
| }
|
|
|
| // Response's MIME type of the last known navigation.
|
| @@ -151,6 +165,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.
|
| +@property(nonatomic, readonly) int certVerifyFlags;
|
| +
|
| +// Cert verification object which wraps net::CertVerifier. Must be called on
|
| +// IO Thread.
|
| +@property(nonatomic, readonly) net::CertVerifierBlockAdapter* certVerifier;
|
| +
|
| // Returns the WKWebViewConfigurationProvider associated with the web
|
| // controller's BrowserState.
|
| - (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider;
|
| @@ -240,6 +261,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
|
| +// 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;
|
| @@ -269,7 +297,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 {
|
| @@ -311,6 +345,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
|
|
|
| @@ -503,6 +546,28 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
|
| }
|
| #endif
|
|
|
| +- (int)certVerifyFlags {
|
| + 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();
|
| +}
|
| +
|
| +- (net::CertVerifierBlockAdapter*)certVerifier {
|
| + if (!_certVerifier) {
|
| + DCHECK(_contextGetter);
|
| + net::URLRequestContext* context = _contextGetter->GetURLRequestContext();
|
| + DCHECK(context);
|
| + _certVerifier.reset(new net::CertVerifierBlockAdapter(
|
| + context->cert_verifier(), context->net_log()));
|
| + }
|
| + return _certVerifier.get();
|
| +}
|
| +
|
| - (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider {
|
| DCHECK(self.webStateImpl);
|
| web::BrowserState* browserState = self.webStateImpl->GetBrowserState();
|
| @@ -852,6 +917,36 @@ 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;
|
| + }
|
| +
|
| + net::CertVerifierBlockAdapter::Params params(
|
| + blockCert.Pass(), base::SysNSStringToUTF8(host));
|
| + params.flags = self.certVerifyFlags;
|
| + params.crl_set = net::SSLConfigService::GetCRLSet().Pass();
|
| + // OCSP response is not provided by iOS API.
|
| +
|
| + self.certVerifier->Verify(
|
| + params,
|
| + ^(net::CertVerifyResult certVerifyResult, int statusResult) {
|
| + dispatch_async(dispatch_get_main_queue(), ^{
|
| + completionHandler(certVerifyResult, statusResult);
|
| + });
|
| + });
|
| + }));
|
| +}
|
| +
|
| - (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
|
| @@ -1188,8 +1283,26 @@ 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 statusResult) {
|
| + bool isCertValid = statusResult == net::OK;
|
| + if (isCertValid) {
|
| + // Cert is valid.
|
| + } else {
|
| + // Cert is invalid.
|
| + }
|
| + NOTIMPLEMENTED();
|
| + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
|
| + }];
|
| }
|
|
|
| - (void)webViewWebContentProcessDidTerminate:(WKWebView*)webView {
|
|
|