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