| 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 |