Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(760)

Unified Diff: ios/web/web_state/ui/crw_wk_web_view_web_controller.mm

Issue 1230033005: WKWebView: Added cert verification API to web controller. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Release Web Controller on the main thread. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ios/web/public/test/test_browser_state.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2ece2f9c3284e0fda828defa09a1c8dab4ed8b6c..ae33e177ff03246a2e1e77c5cc0499f5039e4d44 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"
#include "url/url_constants.h"
#if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW)
@@ -135,6 +143,13 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
// CRWWebUIManager object for loading WebUI pages.
base::scoped_nsobject<CRWWebUIManager> _webUIManager;
+
+ // Cert verification object which wraps |net::CertVerifier|. Must be created,
+ // used and destroyed on IO Thread.
+ scoped_ptr<web::CertVerifierBlockAdapter> _certVerifier;
+
+ // URLRequestContextGetter for obtaining net layer objects.
+ net::URLRequestContextGetter* _contextGetter;
}
// Response's MIME type of the last known navigation.
@@ -159,6 +174,12 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
@property(nonatomic, readonly) int certGroupID;
#endif // #if !defined(ENABLE_CHROME_NET_STACK_FOR_WKWEBVIEW)
+// Cert verification flags. Must be used on IO Thread.
+@property(nonatomic, readonly) int certVerifyFlags;
+
+// Creates _certVerifier object on IO thread.
+- (void)createCertVerifier;
+
// Returns the WKWebViewConfigurationProvider associated with the web
// controller's BrowserState.
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider;
@@ -254,6 +275,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| cannot be null and will be called
+// asynchronously on IO 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;
@@ -283,7 +311,14 @@ 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();
+ [self createCertVerifier];
+ }
+ return self;
}
- (BOOL)keyboardDisplayRequiresUserAction {
@@ -325,6 +360,20 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
[super setPageDialogOpenPolicy:policy];
}
+- (void)close {
+ // _certVerifier must be accessed only on IO thread.
+ web::WebThread::PostTask(web::WebThread::IO, FROM_HERE, base::BindBlock(^{
+ _certVerifier.reset();
+ // This block will be destroyed on IO thread, so make sure that self is
+ // deallocated on the main thread.
+ [self retain];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self release];
+ });
davidben 2015/08/24 21:23:02 I don't think this works. The block itself retains
stuartmorgan 2015/08/24 21:29:43 Ugh, right. Someday I hope to actually learn to re
davidben 2015/08/24 21:33:42 And that's why we //net folks are so allergic to r
stuartmorgan 2015/08/24 22:44:02 A common pattern for us is explicit teardowns that
+ }));
+ [super close];
+}
+
#pragma mark -
#pragma mark Testing-Only Methods
@@ -592,6 +641,29 @@ WKWebViewErrorSource WKWebViewErrorSourceFromError(NSError* error) {
}
#endif
+- (int)certVerifyFlags {
+ DCHECK(web::WebThread::CurrentlyOn(web::WebThread::IO));
+ DCHECK(_contextGetter);
+ // Context Getter's life time is expected to be at least the same or longer
+ // than |BrowserState| lifetime in which case it is safe to assume that
+ // _contextGetter is alive at least until -close is called.
stuartmorgan 2015/08/24 20:34:24 DCHECK(_certVerifier) so that the requirement that
Eugene But (OOO till 7-30) 2015/08/24 21:18:07 Sure.
+ 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();
+}
+
+- (void)createCertVerifier {
+ web::WebThread::PostTask(web::WebThread::IO, FROM_HERE, base::BindBlock(^{
+ net::URLRequestContext* context = _contextGetter->GetURLRequestContext();
+ _certVerifier.reset(new web::CertVerifierBlockAdapter(
+ context->cert_verifier(), context->net_log()));
+ }));
+}
+
- (web::WKWebViewConfigurationProvider&)webViewConfigurationProvider {
DCHECK(self.webStateImpl);
web::BrowserState* browserState = self.webStateImpl->GetBrowserState();
@@ -963,6 +1035,29 @@ 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 (!_certVerifier) {
+ 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.
+ _certVerifier->Verify(params, completionHandler);
+ }));
+}
+
- (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
@@ -1308,8 +1403,28 @@ 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) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (error == net::OK) {
+ // Cert is valid.
+ } else {
+ // Cert is invalid or its state is unknown.
+ }
+ NOTIMPLEMENTED();
+ completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace,
+ nil);
+ });
+ }];
}
- (void)webViewWebContentProcessDidTerminate:(WKWebView*)webView {
« no previous file with comments | « ios/web/public/test/test_browser_state.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698