OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #include "net/base/cert_verifier.h" | 5 #include "net/base/cert_verifier.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "base/lock.h" | |
9 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
10 #include "base/stl_util-inl.h" | 9 #include "base/stl_util-inl.h" |
| 10 #include "base/synchronization/lock.h" |
11 #include "base/threading/worker_pool.h" | 11 #include "base/threading/worker_pool.h" |
12 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
13 #include "net/base/x509_certificate.h" | 13 #include "net/base/x509_certificate.h" |
14 | 14 |
15 #if defined(USE_NSS) | 15 #if defined(USE_NSS) |
16 #include <private/pprthred.h> // PR_DetachThread | 16 #include <private/pprthred.h> // PR_DetachThread |
17 #endif | 17 #endif |
18 | 18 |
19 namespace net { | 19 namespace net { |
20 | 20 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 | 138 |
139 return base::WorkerPool::PostTask( | 139 return base::WorkerPool::PostTask( |
140 FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::Run), | 140 FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::Run), |
141 true /* task is slow */); | 141 true /* task is slow */); |
142 } | 142 } |
143 | 143 |
144 // Cancel is called from the origin loop when the CertVerifier is getting | 144 // Cancel is called from the origin loop when the CertVerifier is getting |
145 // deleted. | 145 // deleted. |
146 void Cancel() { | 146 void Cancel() { |
147 DCHECK_EQ(MessageLoop::current(), origin_loop_); | 147 DCHECK_EQ(MessageLoop::current(), origin_loop_); |
148 AutoLock locked(lock_); | 148 base::AutoLock locked(lock_); |
149 canceled_ = true; | 149 canceled_ = true; |
150 } | 150 } |
151 | 151 |
152 private: | 152 private: |
153 void Run() { | 153 void Run() { |
154 // Runs on a worker thread. | 154 // Runs on a worker thread. |
155 error_ = cert_->Verify(hostname_, flags_, &verify_result_); | 155 error_ = cert_->Verify(hostname_, flags_, &verify_result_); |
156 #if defined(USE_NSS) | 156 #if defined(USE_NSS) |
157 // Detach the thread from NSPR. | 157 // Detach the thread from NSPR. |
158 // Calling NSS functions attaches the thread to NSPR, which stores | 158 // Calling NSS functions attaches the thread to NSPR, which stores |
159 // the NSPR thread ID in thread-specific data. | 159 // the NSPR thread ID in thread-specific data. |
160 // The threads in our thread pool terminate after we have called | 160 // The threads in our thread pool terminate after we have called |
161 // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets | 161 // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets |
162 // segfaults on shutdown when the threads' thread-specific data | 162 // segfaults on shutdown when the threads' thread-specific data |
163 // destructors run. | 163 // destructors run. |
164 PR_DetachThread(); | 164 PR_DetachThread(); |
165 #endif | 165 #endif |
166 Finish(); | 166 Finish(); |
167 } | 167 } |
168 | 168 |
169 // DoReply runs on the origin thread. | 169 // DoReply runs on the origin thread. |
170 void DoReply() { | 170 void DoReply() { |
171 DCHECK_EQ(MessageLoop::current(), origin_loop_); | 171 DCHECK_EQ(MessageLoop::current(), origin_loop_); |
172 { | 172 { |
173 // We lock here because the worker thread could still be in Finished, | 173 // We lock here because the worker thread could still be in Finished, |
174 // after the PostTask, but before unlocking |lock_|. If we do not lock in | 174 // after the PostTask, but before unlocking |lock_|. If we do not lock in |
175 // this case, we will end up deleting a locked Lock, which can lead to | 175 // this case, we will end up deleting a locked Lock, which can lead to |
176 // memory leaks or worse errors. | 176 // memory leaks or worse errors. |
177 AutoLock locked(lock_); | 177 base::AutoLock locked(lock_); |
178 if (!canceled_) { | 178 if (!canceled_) { |
179 cert_verifier_->HandleResult(cert_, hostname_, flags_, | 179 cert_verifier_->HandleResult(cert_, hostname_, flags_, |
180 error_, verify_result_); | 180 error_, verify_result_); |
181 } | 181 } |
182 } | 182 } |
183 delete this; | 183 delete this; |
184 } | 184 } |
185 | 185 |
186 void Finish() { | 186 void Finish() { |
187 // Runs on the worker thread. | 187 // Runs on the worker thread. |
188 // We assume that the origin loop outlives the CertVerifier. If the | 188 // We assume that the origin loop outlives the CertVerifier. If the |
189 // CertVerifier is deleted, it will call Cancel on us. If it does so | 189 // CertVerifier is deleted, it will call Cancel on us. If it does so |
190 // before the Acquire, we'll delete ourselves and return. If it's trying to | 190 // before the Acquire, we'll delete ourselves and return. If it's trying to |
191 // do so concurrently, then it'll block on the lock and we'll call PostTask | 191 // do so concurrently, then it'll block on the lock and we'll call PostTask |
192 // while the CertVerifier (and therefore the MessageLoop) is still alive. | 192 // while the CertVerifier (and therefore the MessageLoop) is still alive. |
193 // If it does so after this function, we assume that the MessageLoop will | 193 // If it does so after this function, we assume that the MessageLoop will |
194 // process pending tasks. In which case we'll notice the |canceled_| flag | 194 // process pending tasks. In which case we'll notice the |canceled_| flag |
195 // in DoReply. | 195 // in DoReply. |
196 | 196 |
197 bool canceled; | 197 bool canceled; |
198 { | 198 { |
199 AutoLock locked(lock_); | 199 base::AutoLock locked(lock_); |
200 canceled = canceled_; | 200 canceled = canceled_; |
201 if (!canceled) { | 201 if (!canceled) { |
202 origin_loop_->PostTask( | 202 origin_loop_->PostTask( |
203 FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::DoReply)); | 203 FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::DoReply)); |
204 } | 204 } |
205 } | 205 } |
206 | 206 |
207 if (canceled) | 207 if (canceled) |
208 delete this; | 208 delete this; |
209 } | 209 } |
210 | 210 |
211 scoped_refptr<X509Certificate> cert_; | 211 scoped_refptr<X509Certificate> cert_; |
212 const std::string hostname_; | 212 const std::string hostname_; |
213 const int flags_; | 213 const int flags_; |
214 MessageLoop* const origin_loop_; | 214 MessageLoop* const origin_loop_; |
215 CertVerifier* const cert_verifier_; | 215 CertVerifier* const cert_verifier_; |
216 | 216 |
217 // lock_ protects canceled_. | 217 // lock_ protects canceled_. |
218 Lock lock_; | 218 base::Lock lock_; |
219 | 219 |
220 // If canceled_ is true, | 220 // If canceled_ is true, |
221 // * origin_loop_ cannot be accessed by the worker thread, | 221 // * origin_loop_ cannot be accessed by the worker thread, |
222 // * cert_verifier_ cannot be accessed by any thread. | 222 // * cert_verifier_ cannot be accessed by any thread. |
223 bool canceled_; | 223 bool canceled_; |
224 | 224 |
225 int error_; | 225 int error_; |
226 CertVerifyResult verify_result_; | 226 CertVerifyResult verify_result_; |
227 | 227 |
228 DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker); | 228 DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 cur_request_callback_ = NULL; | 472 cur_request_callback_ = NULL; |
473 | 473 |
474 // Call the user's original callback. | 474 // Call the user's original callback. |
475 callback->Run(result); | 475 callback->Run(result); |
476 } | 476 } |
477 | 477 |
478 } // namespace net | 478 } // namespace net |
479 | 479 |
480 DISABLE_RUNNABLE_METHOD_REFCOUNT(net::CertVerifierWorker); | 480 DISABLE_RUNNABLE_METHOD_REFCOUNT(net::CertVerifierWorker); |
481 | 481 |
OLD | NEW |