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

Side by Side Diff: ios/web/net/crw_cert_verification_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: Threads are hard. Created 5 years, 3 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "ios/web/net/crw_cert_verification_controller.h"
6
7 #include "base/mac/bind_objc_block.h"
8 #import "base/memory/ref_counted.h"
9 #import "base/memory/scoped_ptr.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "ios/web/net/cert_verifier_block_adapter.h"
12 #include "ios/web/public/browser_state.h"
13 #include "ios/web/public/web_thread.h"
14 #include "net/cert/cert_verify_result.h"
15 #include "net/ssl/ssl_config_service.h"
16 #include "net/url_request/url_request_context.h"
17 #include "net/url_request/url_request_context_getter.h"
18
davidben 2015/09/01 22:30:38 namespace {
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 Done.
19 // This class takes ownerhip of block and releases it on UI thread, even if
davidben 2015/09/01 22:30:38 Nit: ownerhip -> ownership
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 Done.
20 // |BlockHolder| is destructed on a background thread.
21 template <class T>
22 class BlockHolder : public base::RefCounted<BlockHolder<T>> {
davidben 2015/09/01 22:30:39 RefCountedThreadSafe
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 Done.
23 public:
24 // Takes ownership of |block|, which must not be null.
25 explicit BlockHolder(T block) : block_([block copy]) { DCHECK(block_); }
davidben 2015/09/01 22:30:39 I probably wouldn't bother templating this since i
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 I will use BlockHolder for another public method o
26
27 // Calls underlying block with the given variadic arguments.
28 template <typename... Arguments>
davidben 2015/09/01 22:30:39 Ditto.
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 Acknowledged.
29 void call(Arguments... Args) {
davidben 2015/09/01 22:30:38 Style: Call?
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 Both |Call| and |call| are correct names according
30 block_(Args...);
31 }
32
33 private:
34 BlockHolder() = delete;
35 friend class base::RefCounted<BlockHolder>;
36
37 // Releases the given block, must be called on UI thread.
38 static void ReleaseBlock(id block) {
39 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
40 [block release];
41 }
42
43 // Releases underlying |block_| on UI thread.
44 ~BlockHolder() {
45 if (web::WebThread::CurrentlyOn(web::WebThread::UI)) {
46 ReleaseBlock(block_);
47 } else {
48 web::WebThread::PostTask(web::WebThread::UI, FROM_HERE,
49 base::Bind(&BlockHolder::ReleaseBlock, block_));
50 }
51 }
52
53 T block_;
davidben 2015/09/01 22:30:38 I assume automatic reference-counting doesn't kick
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 Fortunately for this CL we don't support ARC :)
54 };
davidben 2015/09/01 22:30:38 } // namespace
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 Done.
55
56 @interface CRWCertVerificationController () {
57 // Cert verification object which wraps |net::CertVerifier|. Must be created,
58 // used and destroyed on IO Thread.
59 scoped_ptr<web::CertVerifierBlockAdapter> _certVerifier;
60
61 // URLRequestContextGetter for obtaining net layer objects.
62 net::URLRequestContextGetter* _contextGetter;
63 }
64
65 // Cert verification flags. Must be used on IO Thread.
66 @property(nonatomic, readonly) int certVerifyFlags;
67
68 // Creates _certVerifier object on IO thread.
69 - (void)createCertVerifier;
70
71 // Verifies the given |cert| for the given |host| and calls |completionHandler|
72 // on completion. |completionHandler| cannot be null and will be called
73 // synchronously or asynchronously on IO thread.
74 - (void)verifyCert:(const scoped_refptr<net::X509Certificate>&)cert
75 forHost:(NSString*)host
76 completionHandler:(void (^)(net::CertVerifyResult, int))completionHandler;
77
78 @end
79
80 @implementation CRWCertVerificationController
81
82 #pragma mark - Superclass
83
84 - (void)dealloc {
85 DCHECK(!_certVerifier); // This is not a thread safe check.
davidben 2015/09/01 22:30:39 What's this comment for?
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 Removed.
86 [super dealloc];
87 }
88
89 #pragma mark - Public
90
91 - (instancetype)initWithBrowserState:(web::BrowserState*)browserState {
92 DCHECK(browserState);
93 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
94 self = [super init];
95 if (self) {
96 _contextGetter = browserState->GetRequestContext();
97 DCHECK(_contextGetter);
98 [self createCertVerifier];
99 }
100 return self;
101 }
102
103 - (void)decidePolicyForCert:(const scoped_refptr<net::X509Certificate>&)cert
104 host:(NSString*)host
105 completionHandler:(void (^)(web::CertAcceptPolicy))handler {
106 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
107 // completionHandler of |verifyCert:forHost:completionHandler:| is called on
108 // IO thread and then bounses back to UI thread. As a result all objects
davidben 2015/09/01 22:30:39 Nit: bounces
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 Done.
109 // captured by completionHandler may be realeases on either UI or IO thread.
davidben 2015/09/01 22:30:38 Nit: released
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 Done.
110 // Since |handler| can potentially capture multiple thread unsafe objects
111 // (like Web Controller) |handler| itself should never be released on
112 // background thread and |BlockHolder| ensures that.
113 __block scoped_refptr<BlockHolder<void (^)(web::CertAcceptPolicy)>>
114 handlerHolder(new BlockHolder<void (^)(web::CertAcceptPolicy)>(handler));
115 [self verifyCert:cert
116 forHost:host
117 completionHandler:^(net::CertVerifyResult result, int error) {
118 web::CertAcceptPolicy policy = web::CERT_ACCEPT_POLICY_ERROR;
119 if (error == net::OK) {
120 policy = web::CERT_ACCEPT_POLICY_ALLOW;
121 } else if (net::IsCertStatusError(result.cert_status)) {
122 // TODO(eugenebut): Check CertPolicyCache for user's decision.
123 policy = net::IsCertStatusMinorError(result.cert_status)
124 ? web::CERT_ACCEPT_POLICY_ALLOW
125 : web::CERT_ACCEPT_POLICY_DENY;
126 }
127
128 dispatch_async(dispatch_get_main_queue(), ^{
129 handlerHolder->call(policy);
130 });
131 }];
132 }
133
134 - (void)shutDown {
135 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
136 web::WebThread::PostTask(web::WebThread::IO, FROM_HERE, base::BindBlock(^{
137 // This block captures |self| delaying its deallocation and possible causing
138 // dealloc to happen on IO thread (which is fine for this class).
139 _certVerifier.reset();
140 }));
141 }
142
143 #pragma mark - Private
144
145 - (int)certVerifyFlags {
146 DCHECK(web::WebThread::CurrentlyOn(web::WebThread::IO));
147 DCHECK(_contextGetter);
148 // |net::URLRequestContextGetter| lifetime is expected to be at least the same
149 // or longer than |BrowserState| lifetime.
150 net::URLRequestContext* context = _contextGetter->GetURLRequestContext();
151 DCHECK(context);
152 net::SSLConfigService* SSLConfigService = context->ssl_config_service();
davidben 2015/09/01 22:30:38 Style: ssl_config_service
Eugene But (OOO till 7-30) 2015/09/02 20:17:45 This is Objective-C method and for that reason sho
davidben 2015/09/03 18:34:27 Oh, I see. This is camelCase + first word happens
Eugene But (OOO till 7-30) 2015/09/03 18:59:05 Yes, this is not something that is very intuitive.
153 DCHECK(SSLConfigService);
154 net::SSLConfig config;
155 SSLConfigService->GetSSLConfig(&config);
156 return config.GetCertVerifyFlags();
157 }
158
159 - (void)createCertVerifier {
160 web::WebThread::PostTask(web::WebThread::IO, FROM_HERE, base::BindBlock(^{
161 net::URLRequestContext* context = _contextGetter->GetURLRequestContext();
162 _certVerifier.reset(new web::CertVerifierBlockAdapter(
163 context->cert_verifier(), context->net_log()));
164 }));
165 }
166
167 - (void)verifyCert:(const scoped_refptr<net::X509Certificate>&)cert
168 forHost:(NSString*)host
169 completionHandler:(void (^)(net::CertVerifyResult, int))completionHandler {
170 DCHECK(completionHandler);
171 __block scoped_refptr<net::X509Certificate> blockCert = cert;
172 web::WebThread::PostTask(
173 web::WebThread::IO, FROM_HERE, base::BindBlock(^{
174 // WeakNSObject does not work across different threads, hence this block
175 // retains self.
176 if (!_certVerifier) {
177 completionHandler(net::CertVerifyResult(), net::ERR_FAILED);
178 return;
179 }
180
181 web::CertVerifierBlockAdapter::Params params(
182 blockCert.Pass(), base::SysNSStringToUTF8(host));
183 params.flags = self.certVerifyFlags;
184 params.crl_set = net::SSLConfigService::GetCRLSet();
185 // OCSP response is not provided by iOS API.
186 _certVerifier->Verify(params, completionHandler);
187 }));
188 }
189
190 @end
OLDNEW
« no previous file with comments | « ios/web/net/crw_cert_verification_controller.h ('k') | ios/web/public/test/test_browser_state.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698