| 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/ocsp/nss_ocsp.h" | 5 #include "net/ocsp/nss_ocsp.h" |
| 6 | 6 |
| 7 #include <certt.h> | 7 #include <certt.h> |
| 8 #include <certdb.h> | 8 #include <certdb.h> |
| 9 #include <ocsp.h> | 9 #include <ocsp.h> |
| 10 #include <nspr.h> | 10 #include <nspr.h> |
| 11 #include <nss.h> | 11 #include <nss.h> |
| 12 #include <pthread.h> |
| 12 #include <secerr.h> | 13 #include <secerr.h> |
| 13 | 14 |
| 14 #include <string> | 15 #include <string> |
| 15 | 16 |
| 17 #include "base/basictypes.h" |
| 16 #include "base/compiler_specific.h" | 18 #include "base/compiler_specific.h" |
| 17 #include "base/condition_variable.h" | 19 #include "base/condition_variable.h" |
| 18 #include "base/histogram.h" | 20 #include "base/histogram.h" |
| 21 #include "base/lazy_instance.h" |
| 22 #include "base/lock.h" |
| 19 #include "base/logging.h" | 23 #include "base/logging.h" |
| 20 #include "base/message_loop.h" | 24 #include "base/message_loop.h" |
| 21 #include "base/singleton.h" | |
| 22 #include "base/string_util.h" | 25 #include "base/string_util.h" |
| 23 #include "base/thread.h" | 26 #include "base/thread.h" |
| 24 #include "base/time.h" | 27 #include "base/time.h" |
| 25 #include "googleurl/src/gurl.h" | 28 #include "googleurl/src/gurl.h" |
| 26 #include "net/base/io_buffer.h" | 29 #include "net/base/io_buffer.h" |
| 27 #include "net/base/load_flags.h" | 30 #include "net/base/load_flags.h" |
| 28 #include "net/http/http_request_headers.h" | 31 #include "net/http/http_request_headers.h" |
| 29 #include "net/http/http_response_headers.h" | 32 #include "net/http/http_response_headers.h" |
| 30 #include "net/url_request/url_request.h" | 33 #include "net/url_request/url_request.h" |
| 31 #include "net/url_request/url_request_context.h" | 34 #include "net/url_request/url_request_context.h" |
| 32 | 35 |
| 33 namespace { | 36 namespace { |
| 34 | 37 |
| 38 // Protects |g_request_context|. |
| 39 pthread_mutex_t g_request_context_lock = PTHREAD_MUTEX_INITIALIZER; |
| 40 static URLRequestContext* g_request_context = NULL; |
| 41 |
| 42 class OCSPIOLoop : public MessageLoop::DestructionObserver { |
| 43 public: |
| 44 // MessageLoop::DestructionObserver: |
| 45 virtual void WillDestroyCurrentMessageLoop(); |
| 46 |
| 47 void StartUsing() { |
| 48 AutoLock autolock(lock_); |
| 49 used_ = true; |
| 50 } |
| 51 |
| 52 bool used() const { |
| 53 AutoLock autolock(lock_); |
| 54 return used_; |
| 55 } |
| 56 |
| 57 // Called from worker thread. |
| 58 void PostTaskToIOLoop(const tracked_objects::Location& from_here, Task* task); |
| 59 |
| 60 void EnsureIOLoop(); |
| 61 |
| 62 private: |
| 63 friend struct base::DefaultLazyInstanceTraits<OCSPIOLoop>; |
| 64 |
| 65 OCSPIOLoop(); |
| 66 ~OCSPIOLoop(); |
| 67 |
| 68 mutable Lock lock_; |
| 69 bool used_; // Protected by |lock_|. |
| 70 // This should not be modified after |used_|. |
| 71 MessageLoopForIO* io_loop_; // Protected by |lock_|. |
| 72 |
| 73 DISALLOW_COPY_AND_ASSIGN(OCSPIOLoop); |
| 74 }; |
| 75 |
| 76 OCSPIOLoop::OCSPIOLoop() |
| 77 : used_(false), |
| 78 io_loop_(MessageLoopForIO::current()) { |
| 79 DCHECK(io_loop_); |
| 80 io_loop_->AddDestructionObserver(this); |
| 81 } |
| 82 |
| 83 OCSPIOLoop::~OCSPIOLoop() { |
| 84 // IO thread was already deleted before the singleton is deleted |
| 85 // in AtExitManager. |
| 86 { |
| 87 AutoLock autolock(lock_); |
| 88 DCHECK(!io_loop_); |
| 89 DCHECK(!used_); |
| 90 } |
| 91 |
| 92 pthread_mutex_lock(&g_request_context_lock); |
| 93 DCHECK(!g_request_context); |
| 94 pthread_mutex_unlock(&g_request_context_lock); |
| 95 } |
| 96 |
| 97 void OCSPIOLoop::WillDestroyCurrentMessageLoop() { |
| 98 // Prevent the worker thread from trying to access |io_loop_|. |
| 99 { |
| 100 AutoLock autolock(lock_); |
| 101 DCHECK_EQ(MessageLoopForIO::current(), io_loop_); |
| 102 io_loop_ = NULL; |
| 103 used_ = false; |
| 104 } |
| 105 |
| 106 pthread_mutex_lock(&g_request_context_lock); |
| 107 g_request_context = NULL; |
| 108 pthread_mutex_unlock(&g_request_context_lock); |
| 109 } |
| 110 |
| 111 void OCSPIOLoop::PostTaskToIOLoop( |
| 112 const tracked_objects::Location& from_here, Task* task) { |
| 113 AutoLock autolock(lock_); |
| 114 if (io_loop_) |
| 115 io_loop_->PostTask(from_here, task); |
| 116 } |
| 117 |
| 118 void OCSPIOLoop::EnsureIOLoop() { |
| 119 AutoLock autolock(lock_); |
| 120 DCHECK_EQ(MessageLoopForIO::current(), io_loop_); |
| 121 } |
| 122 |
| 123 base::LazyInstance<OCSPIOLoop> g_ocsp_io_loop(base::LINKER_INITIALIZED); |
| 124 |
| 35 const int kRecvBufferSize = 4096; | 125 const int kRecvBufferSize = 4096; |
| 36 | 126 |
| 37 // All OCSP handlers should be called in the context of | 127 // All OCSP handlers should be called in the context of |
| 38 // CertVerifier's thread (i.e. worker pool, not on the I/O thread). | 128 // CertVerifier's thread (i.e. worker pool, not on the I/O thread). |
| 39 // It supports blocking mode only. | 129 // It supports blocking mode only. |
| 40 | 130 |
| 41 SECStatus OCSPCreateSession(const char* host, PRUint16 portnum, | 131 SECStatus OCSPCreateSession(const char* host, PRUint16 portnum, |
| 42 SEC_HTTP_SERVER_SESSION* pSession); | 132 SEC_HTTP_SERVER_SESSION* pSession); |
| 43 SECStatus OCSPKeepAliveSession(SEC_HTTP_SERVER_SESSION session, | 133 SECStatus OCSPKeepAliveSession(SEC_HTTP_SERVER_SESSION session, |
| 44 PRPollDesc **pPollDesc); | 134 PRPollDesc **pPollDesc); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 61 PRPollDesc** pPollDesc, | 151 PRPollDesc** pPollDesc, |
| 62 PRUint16* http_response_code, | 152 PRUint16* http_response_code, |
| 63 const char** http_response_content_type, | 153 const char** http_response_content_type, |
| 64 const char** http_response_headers, | 154 const char** http_response_headers, |
| 65 const char** http_response_data, | 155 const char** http_response_data, |
| 66 PRUint32* http_response_data_len); | 156 PRUint32* http_response_data_len); |
| 67 SECStatus OCSPFree(SEC_HTTP_REQUEST_SESSION request); | 157 SECStatus OCSPFree(SEC_HTTP_REQUEST_SESSION request); |
| 68 | 158 |
| 69 char* GetAlternateOCSPAIAInfo(CERTCertificate *cert); | 159 char* GetAlternateOCSPAIAInfo(CERTCertificate *cert); |
| 70 | 160 |
| 71 class OCSPInitSingleton : public MessageLoop::DestructionObserver { | 161 class OCSPNSSInitialization { |
| 72 public: | 162 private: |
| 73 // Called on IO thread. | 163 friend struct base::DefaultLazyInstanceTraits<OCSPNSSInitialization>; |
| 74 virtual void WillDestroyCurrentMessageLoop() { | |
| 75 AutoLock autolock(lock_); | |
| 76 DCHECK_EQ(MessageLoopForIO::current(), io_loop_); | |
| 77 io_loop_ = NULL; | |
| 78 request_context_ = NULL; | |
| 79 }; | |
| 80 | 164 |
| 81 // Called from worker thread. | 165 OCSPNSSInitialization(); |
| 82 void PostTaskToIOLoop( | 166 ~OCSPNSSInitialization(); |
| 83 const tracked_objects::Location& from_here, Task* task) { | |
| 84 AutoLock autolock(lock_); | |
| 85 if (io_loop_) | |
| 86 io_loop_->PostTask(from_here, task); | |
| 87 } | |
| 88 | |
| 89 // This is static method because it is called before NSS initialization, | |
| 90 // that is, before OCSPInitSingleton is initialized. | |
| 91 static void set_url_request_context(URLRequestContext* request_context) { | |
| 92 request_context_ = request_context; | |
| 93 } | |
| 94 static URLRequestContext* url_request_context() { | |
| 95 return request_context_; | |
| 96 } | |
| 97 | |
| 98 private: | |
| 99 friend struct DefaultSingletonTraits<OCSPInitSingleton>; | |
| 100 | |
| 101 OCSPInitSingleton() | |
| 102 : io_loop_(MessageLoopForIO::current()) { | |
| 103 DCHECK(io_loop_); | |
| 104 io_loop_->AddDestructionObserver(this); | |
| 105 | |
| 106 // NSS calls the functions in the function table to download certificates | |
| 107 // or CRLs or talk to OCSP responders over HTTP. These functions must | |
| 108 // set an NSS/NSPR error code when they fail. Otherwise NSS will get the | |
| 109 // residual error code from an earlier failed function call. | |
| 110 client_fcn_.version = 1; | |
| 111 SEC_HttpClientFcnV1Struct *ft = &client_fcn_.fcnTable.ftable1; | |
| 112 ft->createSessionFcn = OCSPCreateSession; | |
| 113 ft->keepAliveSessionFcn = OCSPKeepAliveSession; | |
| 114 ft->freeSessionFcn = OCSPFreeSession; | |
| 115 ft->createFcn = OCSPCreate; | |
| 116 ft->setPostDataFcn = OCSPSetPostData; | |
| 117 ft->addHeaderFcn = OCSPAddHeader; | |
| 118 ft->trySendAndReceiveFcn = OCSPTrySendAndReceive; | |
| 119 ft->cancelFcn = NULL; | |
| 120 ft->freeFcn = OCSPFree; | |
| 121 SECStatus status = SEC_RegisterDefaultHttpClient(&client_fcn_); | |
| 122 if (status != SECSuccess) { | |
| 123 NOTREACHED() << "Error initializing OCSP: " << PR_GetError(); | |
| 124 } | |
| 125 | |
| 126 // Work around NSS bugs 524013 and 564334. NSS incorrectly thinks the | |
| 127 // CRLs for Network Solutions Certificate Authority have bad signatures, | |
| 128 // which causes certificates issued by that CA to be reported as revoked. | |
| 129 // By using OCSP for those certificates, which don't have AIA extensions, | |
| 130 // we can work around these bugs. See http://crbug.com/41730. | |
| 131 CERT_StringFromCertFcn old_callback = NULL; | |
| 132 status = CERT_RegisterAlternateOCSPAIAInfoCallBack( | |
| 133 GetAlternateOCSPAIAInfo, &old_callback); | |
| 134 if (status == SECSuccess) { | |
| 135 DCHECK(!old_callback); | |
| 136 } else { | |
| 137 NOTREACHED() << "Error initializing OCSP: " << PR_GetError(); | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 virtual ~OCSPInitSingleton() { | |
| 142 // IO thread was already deleted before the singleton is deleted | |
| 143 // in AtExitManager. | |
| 144 AutoLock autolock(lock_); | |
| 145 DCHECK(!io_loop_); | |
| 146 DCHECK(!request_context_); | |
| 147 } | |
| 148 | 167 |
| 149 SEC_HttpClientFcn client_fcn_; | 168 SEC_HttpClientFcn client_fcn_; |
| 150 | 169 |
| 151 // |lock_| protects |io_loop_|. | 170 DISALLOW_COPY_AND_ASSIGN(OCSPNSSInitialization); |
| 152 Lock lock_; | |
| 153 // I/O thread. | |
| 154 MessageLoop* io_loop_; // I/O thread | |
| 155 // URLRequestContext for OCSP handlers. | |
| 156 static URLRequestContext* request_context_; | |
| 157 | |
| 158 DISALLOW_COPY_AND_ASSIGN(OCSPInitSingleton); | |
| 159 }; | 171 }; |
| 160 | 172 |
| 161 URLRequestContext* OCSPInitSingleton::request_context_ = NULL; | 173 OCSPNSSInitialization::OCSPNSSInitialization() { |
| 174 // NSS calls the functions in the function table to download certificates |
| 175 // or CRLs or talk to OCSP responders over HTTP. These functions must |
| 176 // set an NSS/NSPR error code when they fail. Otherwise NSS will get the |
| 177 // residual error code from an earlier failed function call. |
| 178 client_fcn_.version = 1; |
| 179 SEC_HttpClientFcnV1Struct *ft = &client_fcn_.fcnTable.ftable1; |
| 180 ft->createSessionFcn = OCSPCreateSession; |
| 181 ft->keepAliveSessionFcn = OCSPKeepAliveSession; |
| 182 ft->freeSessionFcn = OCSPFreeSession; |
| 183 ft->createFcn = OCSPCreate; |
| 184 ft->setPostDataFcn = OCSPSetPostData; |
| 185 ft->addHeaderFcn = OCSPAddHeader; |
| 186 ft->trySendAndReceiveFcn = OCSPTrySendAndReceive; |
| 187 ft->cancelFcn = NULL; |
| 188 ft->freeFcn = OCSPFree; |
| 189 SECStatus status = SEC_RegisterDefaultHttpClient(&client_fcn_); |
| 190 if (status != SECSuccess) { |
| 191 NOTREACHED() << "Error initializing OCSP: " << PR_GetError(); |
| 192 } |
| 193 |
| 194 // Work around NSS bugs 524013 and 564334. NSS incorrectly thinks the |
| 195 // CRLs for Network Solutions Certificate Authority have bad signatures, |
| 196 // which causes certificates issued by that CA to be reported as revoked. |
| 197 // By using OCSP for those certificates, which don't have AIA extensions, |
| 198 // we can work around these bugs. See http://crbug.com/41730. |
| 199 CERT_StringFromCertFcn old_callback = NULL; |
| 200 status = CERT_RegisterAlternateOCSPAIAInfoCallBack( |
| 201 GetAlternateOCSPAIAInfo, &old_callback); |
| 202 if (status == SECSuccess) { |
| 203 DCHECK(!old_callback); |
| 204 } else { |
| 205 NOTREACHED() << "Error initializing OCSP: " << PR_GetError(); |
| 206 } |
| 207 } |
| 208 |
| 209 OCSPNSSInitialization::~OCSPNSSInitialization() {} |
| 210 |
| 211 base::LazyInstance<OCSPNSSInitialization> g_ocsp_nss_initialization( |
| 212 base::LINKER_INITIALIZED); |
| 162 | 213 |
| 163 // Concrete class for SEC_HTTP_REQUEST_SESSION. | 214 // Concrete class for SEC_HTTP_REQUEST_SESSION. |
| 164 // Public methods except virtual methods of URLRequest::Delegate (On* methods) | 215 // Public methods except virtual methods of URLRequest::Delegate (On* methods) |
| 165 // run on certificate verifier thread (worker thread). | 216 // run on certificate verifier thread (worker thread). |
| 166 // Virtual methods of URLRequest::Delegate and private methods run | 217 // Virtual methods of URLRequest::Delegate and private methods run |
| 167 // on IO thread. | 218 // on IO thread. |
| 168 class OCSPRequestSession | 219 class OCSPRequestSession |
| 169 : public base::RefCountedThreadSafe<OCSPRequestSession>, | 220 : public base::RefCountedThreadSafe<OCSPRequestSession>, |
| 170 public URLRequest::Delegate, | 221 public URLRequest::Delegate, |
| 171 public MessageLoop::DestructionObserver { | 222 public MessageLoop::DestructionObserver { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 192 void AddHeader(const char* http_header_name, const char* http_header_value) { | 243 void AddHeader(const char* http_header_name, const char* http_header_value) { |
| 193 extra_request_headers_.SetHeader(http_header_name, | 244 extra_request_headers_.SetHeader(http_header_name, |
| 194 http_header_value); | 245 http_header_value); |
| 195 } | 246 } |
| 196 | 247 |
| 197 void Start() { | 248 void Start() { |
| 198 // At this point, it runs on worker thread. | 249 // At this point, it runs on worker thread. |
| 199 // |io_loop_| was initialized to be NULL in constructor, and | 250 // |io_loop_| was initialized to be NULL in constructor, and |
| 200 // set only in StartURLRequest, so no need to lock |lock_| here. | 251 // set only in StartURLRequest, so no need to lock |lock_| here. |
| 201 DCHECK(!io_loop_); | 252 DCHECK(!io_loop_); |
| 202 Singleton<OCSPInitSingleton>()->PostTaskToIOLoop( | 253 g_ocsp_io_loop.Get().PostTaskToIOLoop( |
| 203 FROM_HERE, | 254 FROM_HERE, |
| 204 NewRunnableMethod(this, &OCSPRequestSession::StartURLRequest)); | 255 NewRunnableMethod(this, &OCSPRequestSession::StartURLRequest)); |
| 205 } | 256 } |
| 206 | 257 |
| 207 bool Started() const { | 258 bool Started() const { |
| 208 return request_ != NULL; | 259 return request_ != NULL; |
| 209 } | 260 } |
| 210 | 261 |
| 211 void Cancel() { | 262 void Cancel() { |
| 212 // IO thread may set |io_loop_| to NULL, so protect by |lock_|. | 263 // IO thread may set |io_loop_| to NULL, so protect by |lock_|. |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 // Must call this method while holding |lock_|. | 382 // Must call this method while holding |lock_|. |
| 332 void CancelLocked() { | 383 void CancelLocked() { |
| 333 lock_.AssertAcquired(); | 384 lock_.AssertAcquired(); |
| 334 if (io_loop_) { | 385 if (io_loop_) { |
| 335 io_loop_->PostTask( | 386 io_loop_->PostTask( |
| 336 FROM_HERE, | 387 FROM_HERE, |
| 337 NewRunnableMethod(this, &OCSPRequestSession::CancelURLRequest)); | 388 NewRunnableMethod(this, &OCSPRequestSession::CancelURLRequest)); |
| 338 } | 389 } |
| 339 } | 390 } |
| 340 | 391 |
| 392 // Runs on |g_ocsp_io_loop|'s IO loop. |
| 341 void StartURLRequest() { | 393 void StartURLRequest() { |
| 342 DCHECK(!request_); | 394 DCHECK(!request_); |
| 343 | 395 |
| 344 URLRequestContext* url_request_context = | 396 pthread_mutex_lock(&g_request_context_lock); |
| 345 OCSPInitSingleton::url_request_context(); | 397 URLRequestContext* url_request_context = g_request_context; |
| 398 pthread_mutex_unlock(&g_request_context_lock); |
| 399 |
| 346 if (url_request_context == NULL) | 400 if (url_request_context == NULL) |
| 347 return; | 401 return; |
| 348 | 402 |
| 349 { | 403 { |
| 350 AutoLock autolock(lock_); | 404 AutoLock autolock(lock_); |
| 351 DCHECK(!io_loop_); | 405 DCHECK(!io_loop_); |
| 352 io_loop_ = MessageLoopForIO::current(); | 406 io_loop_ = MessageLoopForIO::current(); |
| 353 io_loop_->AddDestructionObserver(this); | 407 io_loop_->AddDestructionObserver(this); |
| 354 } | 408 } |
| 355 | 409 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 DISALLOW_COPY_AND_ASSIGN(OCSPServerSession); | 522 DISALLOW_COPY_AND_ASSIGN(OCSPServerSession); |
| 469 }; | 523 }; |
| 470 | 524 |
| 471 | 525 |
| 472 // OCSP Http Client functions. | 526 // OCSP Http Client functions. |
| 473 // Our Http Client functions operate in blocking mode. | 527 // Our Http Client functions operate in blocking mode. |
| 474 SECStatus OCSPCreateSession(const char* host, PRUint16 portnum, | 528 SECStatus OCSPCreateSession(const char* host, PRUint16 portnum, |
| 475 SEC_HTTP_SERVER_SESSION* pSession) { | 529 SEC_HTTP_SERVER_SESSION* pSession) { |
| 476 LOG(INFO) << "OCSP create session: host=" << host << " port=" << portnum; | 530 LOG(INFO) << "OCSP create session: host=" << host << " port=" << portnum; |
| 477 DCHECK(!MessageLoop::current()); | 531 DCHECK(!MessageLoop::current()); |
| 478 if (OCSPInitSingleton::url_request_context() == NULL) { | 532 pthread_mutex_lock(&g_request_context_lock); |
| 533 URLRequestContext* request_context = g_request_context; |
| 534 pthread_mutex_unlock(&g_request_context_lock); |
| 535 if (request_context == NULL) { |
| 479 LOG(ERROR) << "No URLRequestContext for OCSP handler."; | 536 LOG(ERROR) << "No URLRequestContext for OCSP handler."; |
| 480 // The application failed to call SetURLRequestContextForOCSP, so we | 537 // The application failed to call SetURLRequestContextForOCSP, so we |
| 481 // can't create and use URLRequest. PR_NOT_IMPLEMENTED_ERROR is not an | 538 // can't create and use URLRequest. PR_NOT_IMPLEMENTED_ERROR is not an |
| 482 // accurate error code for this error condition, but is close enough. | 539 // accurate error code for this error condition, but is close enough. |
| 483 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | 540 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); |
| 484 return SECFailure; | 541 return SECFailure; |
| 485 } | 542 } |
| 486 *pSession = new OCSPServerSession(host, portnum); | 543 *pSession = new OCSPServerSession(host, portnum); |
| 487 return SECSuccess; | 544 return SECSuccess; |
| 488 } | 545 } |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 775 } | 832 } |
| 776 } | 833 } |
| 777 | 834 |
| 778 return NULL; | 835 return NULL; |
| 779 } | 836 } |
| 780 | 837 |
| 781 } // anonymous namespace | 838 } // anonymous namespace |
| 782 | 839 |
| 783 namespace net { | 840 namespace net { |
| 784 | 841 |
| 842 void SetMessageLoopForOCSP() { |
| 843 // Must have a MessageLoopForIO. |
| 844 DCHECK(MessageLoopForIO::current()); |
| 845 |
| 846 bool used = g_ocsp_io_loop.Get().used(); |
| 847 |
| 848 // Should not be called when g_ocsp_io_loop has already been used. |
| 849 DCHECK(!used); |
| 850 } |
| 851 |
| 785 void EnsureOCSPInit() { | 852 void EnsureOCSPInit() { |
| 786 Singleton<OCSPInitSingleton>::get(); | 853 g_ocsp_io_loop.Get().StartUsing(); |
| 854 g_ocsp_nss_initialization.Get(); |
| 787 } | 855 } |
| 788 | 856 |
| 789 // This function would be called before NSS initialization. | 857 // This function would be called before NSS initialization. |
| 790 void SetURLRequestContextForOCSP(URLRequestContext* request_context) { | 858 void SetURLRequestContextForOCSP(URLRequestContext* request_context) { |
| 791 OCSPInitSingleton::set_url_request_context(request_context); | 859 pthread_mutex_lock(&g_request_context_lock); |
| 860 if (request_context) { |
| 861 DCHECK(request_context->is_main()); |
| 862 DCHECK(!g_request_context); |
| 863 } else { |
| 864 DCHECK(g_request_context); |
| 865 } |
| 866 g_request_context = request_context; |
| 867 pthread_mutex_unlock(&g_request_context_lock); |
| 792 } | 868 } |
| 793 | 869 |
| 794 URLRequestContext* GetURLRequestContextForOCSP() { | 870 URLRequestContext* GetURLRequestContextForOCSP() { |
| 795 return OCSPInitSingleton::url_request_context(); | 871 pthread_mutex_lock(&g_request_context_lock); |
| 872 URLRequestContext* request_context = g_request_context; |
| 873 pthread_mutex_unlock(&g_request_context_lock); |
| 874 DCHECK(request_context->is_main()); |
| 875 return request_context; |
| 796 } | 876 } |
| 797 | 877 |
| 798 } // namespace net | 878 } // namespace net |
| OLD | NEW |