summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/io_thread.cc9
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc16
-rw-r--r--chrome/browser/net/chrome_url_request_context.h1
-rw-r--r--chrome/browser/profile_impl.cc1
-rw-r--r--chrome/common/net/url_request_context_getter.cc3
-rw-r--r--chrome/common/net/url_request_context_getter.h15
-rw-r--r--net/ocsp/nss_ocsp.cc264
-rw-r--r--net/ocsp/nss_ocsp.h5
-rw-r--r--net/proxy/proxy_script_fetcher.cc1
-rw-r--r--net/url_request/url_request_context.cc3
-rw-r--r--net/url_request/url_request_context.h8
11 files changed, 223 insertions, 103 deletions
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 682e390..7ff8c4b 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -26,6 +26,9 @@
#include "net/base/net_util.h"
#include "net/http/http_auth_filter.h"
#include "net/http/http_auth_handler_factory.h"
+#if defined(USE_NSS)
+#include "net/ocsp/nss_ocsp.h"
+#endif // defined(USE_NSS)
#include "net/proxy/proxy_script_fetcher.h"
namespace {
@@ -160,6 +163,12 @@ void IOThread::ChangedToOnTheRecord() {
void IOThread::Init() {
BrowserProcessSubThread::Init();
+ DCHECK_EQ(MessageLoop::TYPE_IO, message_loop()->type());
+
+#if defined(USE_NSS)
+ net::SetMessageLoopForOCSP();
+#endif // defined(USE_NSS)
+
DCHECK(!globals_);
globals_ = new Globals;
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc
index 9f053f3..28f7621 100644
--- a/chrome/browser/net/chrome_url_request_context.cc
+++ b/chrome/browser/net/chrome_url_request_context.cc
@@ -314,11 +314,6 @@ ChromeURLRequestContext* FactoryForOriginal::Create() {
appcache_service_->set_request_context(context);
-#if defined(USE_NSS)
- // TODO(ukai): find a better way to set the URLRequestContext for OCSP.
- net::SetURLRequestContextForOCSP(context);
-#endif
-
context->set_net_log(io_thread_globals->net_log.get());
return context;
}
@@ -559,6 +554,14 @@ URLRequestContext* ChromeURLRequestContextGetter::GetURLRequestContext() {
if (!url_request_context_) {
DCHECK(factory_.get());
url_request_context_ = factory_->Create();
+ if (is_main()) {
+ url_request_context_->set_is_main(true);
+#if defined(USE_NSS)
+ // TODO(ukai): find a better way to set the URLRequestContext for OCSP.
+ net::SetURLRequestContextForOCSP(url_request_context_);
+#endif
+ }
+
factory_.reset();
}
@@ -756,7 +759,8 @@ ChromeURLRequestContext::~ChromeURLRequestContext() {
}
#if defined(USE_NSS)
- if (this == net::GetURLRequestContextForOCSP()) {
+ if (is_main()) {
+ DCHECK_EQ(this, net::GetURLRequestContextForOCSP());
// We are releasing the URLRequestContext used by OCSP handlers.
net::SetURLRequestContextForOCSP(NULL);
}
diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h
index 183ad4a..a580282 100644
--- a/chrome/browser/net/chrome_url_request_context.h
+++ b/chrome/browser/net/chrome_url_request_context.h
@@ -211,7 +211,6 @@ class ChromeURLRequestContext : public URLRequestContext {
bool is_off_the_record_;
private:
-
DISALLOW_COPY_AND_ASSIGN(ChromeURLRequestContext);
};
diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc
index 779cb4d..f02e070 100644
--- a/chrome/browser/profile_impl.cc
+++ b/chrome/browser/profile_impl.cc
@@ -713,6 +713,7 @@ URLRequestContextGetter* ProfileImpl::GetRequestContext() {
// created first.
if (!default_request_context_) {
default_request_context_ = request_context_;
+ request_context_->set_is_main(true);
// TODO(eroman): this isn't terribly useful anymore now that the
// URLRequestContext is constructed by the IO thread...
NotificationService::current()->Notify(
diff --git a/chrome/common/net/url_request_context_getter.cc b/chrome/common/net/url_request_context_getter.cc
index c53f782..57feb0e 100644
--- a/chrome/common/net/url_request_context_getter.cc
+++ b/chrome/common/net/url_request_context_getter.cc
@@ -10,7 +10,7 @@ net::CookieStore* URLRequestContextGetter::GetCookieStore() {
return GetURLRequestContext()->cookie_store();
}
-URLRequestContextGetter::URLRequestContextGetter() {}
+URLRequestContextGetter::URLRequestContextGetter() : is_main_(false) {}
URLRequestContextGetter::~URLRequestContextGetter() {}
@@ -28,4 +28,3 @@ void URLRequestContextGetter::OnDestruct() {
// If no IO message loop proxy was available, we will just leak memory.
// This is also true if the IO thread is gone.
}
-
diff --git a/chrome/common/net/url_request_context_getter.h b/chrome/common/net/url_request_context_getter.h
index 89b28b5..2b6ea82 100644
--- a/chrome/common/net/url_request_context_getter.h
+++ b/chrome/common/net/url_request_context_getter.h
@@ -35,6 +35,14 @@ class URLRequestContextGetter
// may be used).
virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() = 0;
+ // Controls whether or not the URLRequestContextGetter considers itself to be
+ // the the "main" URLRequestContextGetter. Note that each Profile will have a
+ // "default" URLRequestContextGetter. Therefore, "is_main" refers to the
+ // default URLRequestContextGetter for the "main" Profile.
+ // TODO(willchan): Move this code to ChromeURLRequestContextGetter, since this
+ // ia a browser process specific concept.
+ void set_is_main(bool is_main) { is_main_ = is_main; }
+
protected:
friend class DeleteTask<URLRequestContextGetter>;
friend struct URLRequestContextGetterTraits;
@@ -42,10 +50,16 @@ class URLRequestContextGetter
URLRequestContextGetter();
virtual ~URLRequestContextGetter();
+ bool is_main() const { return is_main_; }
+
private:
// OnDestruct is meant to ensure deletion on the thread on which the request
// IO happens.
void OnDestruct();
+
+ // Indicates whether or not this is the default URLRequestContextGetter for
+ // the main Profile.
+ bool is_main_;
};
struct URLRequestContextGetterTraits {
@@ -55,4 +69,3 @@ struct URLRequestContextGetterTraits {
};
#endif // CHROME_COMMON_NET_URL_REQUEST_CONTEXT_GETTER_H_
-
diff --git a/net/ocsp/nss_ocsp.cc b/net/ocsp/nss_ocsp.cc
index dc1851f..3faeb54 100644
--- a/net/ocsp/nss_ocsp.cc
+++ b/net/ocsp/nss_ocsp.cc
@@ -9,16 +9,19 @@
#include <ocsp.h>
#include <nspr.h>
#include <nss.h>
+#include <pthread.h>
#include <secerr.h>
#include <string>
+#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/condition_variable.h"
#include "base/histogram.h"
+#include "base/lazy_instance.h"
+#include "base/lock.h"
#include "base/logging.h"
#include "base/message_loop.h"
-#include "base/singleton.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/thread.h"
@@ -33,6 +36,93 @@
namespace {
+// Protects |g_request_context|.
+pthread_mutex_t g_request_context_lock = PTHREAD_MUTEX_INITIALIZER;
+static URLRequestContext* g_request_context = NULL;
+
+class OCSPIOLoop : public MessageLoop::DestructionObserver {
+ public:
+ // MessageLoop::DestructionObserver:
+ virtual void WillDestroyCurrentMessageLoop();
+
+ void StartUsing() {
+ AutoLock autolock(lock_);
+ used_ = true;
+ }
+
+ bool used() const {
+ AutoLock autolock(lock_);
+ return used_;
+ }
+
+ // Called from worker thread.
+ void PostTaskToIOLoop(const tracked_objects::Location& from_here, Task* task);
+
+ void EnsureIOLoop();
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<OCSPIOLoop>;
+
+ OCSPIOLoop();
+ ~OCSPIOLoop();
+
+ mutable Lock lock_;
+ bool used_; // Protected by |lock_|.
+ // This should not be modified after |used_|.
+ MessageLoopForIO* io_loop_; // Protected by |lock_|.
+
+ DISALLOW_COPY_AND_ASSIGN(OCSPIOLoop);
+};
+
+OCSPIOLoop::OCSPIOLoop()
+ : used_(false),
+ io_loop_(MessageLoopForIO::current()) {
+ DCHECK(io_loop_);
+ io_loop_->AddDestructionObserver(this);
+}
+
+OCSPIOLoop::~OCSPIOLoop() {
+ // IO thread was already deleted before the singleton is deleted
+ // in AtExitManager.
+ {
+ AutoLock autolock(lock_);
+ DCHECK(!io_loop_);
+ DCHECK(!used_);
+ }
+
+ pthread_mutex_lock(&g_request_context_lock);
+ DCHECK(!g_request_context);
+ pthread_mutex_unlock(&g_request_context_lock);
+}
+
+void OCSPIOLoop::WillDestroyCurrentMessageLoop() {
+ // Prevent the worker thread from trying to access |io_loop_|.
+ {
+ AutoLock autolock(lock_);
+ DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
+ io_loop_ = NULL;
+ used_ = false;
+ }
+
+ pthread_mutex_lock(&g_request_context_lock);
+ g_request_context = NULL;
+ pthread_mutex_unlock(&g_request_context_lock);
+}
+
+void OCSPIOLoop::PostTaskToIOLoop(
+ const tracked_objects::Location& from_here, Task* task) {
+ AutoLock autolock(lock_);
+ if (io_loop_)
+ io_loop_->PostTask(from_here, task);
+}
+
+void OCSPIOLoop::EnsureIOLoop() {
+ AutoLock autolock(lock_);
+ DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
+}
+
+base::LazyInstance<OCSPIOLoop> g_ocsp_io_loop(base::LINKER_INITIALIZED);
+
const int kRecvBufferSize = 4096;
// All OCSP handlers should be called in the context of
@@ -69,97 +159,58 @@ SECStatus OCSPFree(SEC_HTTP_REQUEST_SESSION request);
char* GetAlternateOCSPAIAInfo(CERTCertificate *cert);
-class OCSPInitSingleton : public MessageLoop::DestructionObserver {
- public:
- // Called on IO thread.
- virtual void WillDestroyCurrentMessageLoop() {
- AutoLock autolock(lock_);
- DCHECK_EQ(MessageLoopForIO::current(), io_loop_);
- io_loop_ = NULL;
- request_context_ = NULL;
- };
-
- // Called from worker thread.
- void PostTaskToIOLoop(
- const tracked_objects::Location& from_here, Task* task) {
- AutoLock autolock(lock_);
- if (io_loop_)
- io_loop_->PostTask(from_here, task);
- }
-
- // This is static method because it is called before NSS initialization,
- // that is, before OCSPInitSingleton is initialized.
- static void set_url_request_context(URLRequestContext* request_context) {
- request_context_ = request_context;
- }
- static URLRequestContext* url_request_context() {
- return request_context_;
- }
-
+class OCSPNSSInitialization {
private:
- friend struct DefaultSingletonTraits<OCSPInitSingleton>;
-
- OCSPInitSingleton()
- : io_loop_(MessageLoopForIO::current()) {
- DCHECK(io_loop_);
- io_loop_->AddDestructionObserver(this);
-
- // NSS calls the functions in the function table to download certificates
- // or CRLs or talk to OCSP responders over HTTP. These functions must
- // set an NSS/NSPR error code when they fail. Otherwise NSS will get the
- // residual error code from an earlier failed function call.
- client_fcn_.version = 1;
- SEC_HttpClientFcnV1Struct *ft = &client_fcn_.fcnTable.ftable1;
- ft->createSessionFcn = OCSPCreateSession;
- ft->keepAliveSessionFcn = OCSPKeepAliveSession;
- ft->freeSessionFcn = OCSPFreeSession;
- ft->createFcn = OCSPCreate;
- ft->setPostDataFcn = OCSPSetPostData;
- ft->addHeaderFcn = OCSPAddHeader;
- ft->trySendAndReceiveFcn = OCSPTrySendAndReceive;
- ft->cancelFcn = NULL;
- ft->freeFcn = OCSPFree;
- SECStatus status = SEC_RegisterDefaultHttpClient(&client_fcn_);
- if (status != SECSuccess) {
- NOTREACHED() << "Error initializing OCSP: " << PR_GetError();
- }
+ friend struct base::DefaultLazyInstanceTraits<OCSPNSSInitialization>;
- // Work around NSS bugs 524013 and 564334. NSS incorrectly thinks the
- // CRLs for Network Solutions Certificate Authority have bad signatures,
- // which causes certificates issued by that CA to be reported as revoked.
- // By using OCSP for those certificates, which don't have AIA extensions,
- // we can work around these bugs. See http://crbug.com/41730.
- CERT_StringFromCertFcn old_callback = NULL;
- status = CERT_RegisterAlternateOCSPAIAInfoCallBack(
- GetAlternateOCSPAIAInfo, &old_callback);
- if (status == SECSuccess) {
- DCHECK(!old_callback);
- } else {
- NOTREACHED() << "Error initializing OCSP: " << PR_GetError();
- }
- }
-
- virtual ~OCSPInitSingleton() {
- // IO thread was already deleted before the singleton is deleted
- // in AtExitManager.
- AutoLock autolock(lock_);
- DCHECK(!io_loop_);
- DCHECK(!request_context_);
- }
+ OCSPNSSInitialization();
+ ~OCSPNSSInitialization();
SEC_HttpClientFcn client_fcn_;
- // |lock_| protects |io_loop_|.
- Lock lock_;
- // I/O thread.
- MessageLoop* io_loop_; // I/O thread
- // URLRequestContext for OCSP handlers.
- static URLRequestContext* request_context_;
-
- DISALLOW_COPY_AND_ASSIGN(OCSPInitSingleton);
+ DISALLOW_COPY_AND_ASSIGN(OCSPNSSInitialization);
};
-URLRequestContext* OCSPInitSingleton::request_context_ = NULL;
+OCSPNSSInitialization::OCSPNSSInitialization() {
+ // NSS calls the functions in the function table to download certificates
+ // or CRLs or talk to OCSP responders over HTTP. These functions must
+ // set an NSS/NSPR error code when they fail. Otherwise NSS will get the
+ // residual error code from an earlier failed function call.
+ client_fcn_.version = 1;
+ SEC_HttpClientFcnV1Struct *ft = &client_fcn_.fcnTable.ftable1;
+ ft->createSessionFcn = OCSPCreateSession;
+ ft->keepAliveSessionFcn = OCSPKeepAliveSession;
+ ft->freeSessionFcn = OCSPFreeSession;
+ ft->createFcn = OCSPCreate;
+ ft->setPostDataFcn = OCSPSetPostData;
+ ft->addHeaderFcn = OCSPAddHeader;
+ ft->trySendAndReceiveFcn = OCSPTrySendAndReceive;
+ ft->cancelFcn = NULL;
+ ft->freeFcn = OCSPFree;
+ SECStatus status = SEC_RegisterDefaultHttpClient(&client_fcn_);
+ if (status != SECSuccess) {
+ NOTREACHED() << "Error initializing OCSP: " << PR_GetError();
+ }
+
+ // Work around NSS bugs 524013 and 564334. NSS incorrectly thinks the
+ // CRLs for Network Solutions Certificate Authority have bad signatures,
+ // which causes certificates issued by that CA to be reported as revoked.
+ // By using OCSP for those certificates, which don't have AIA extensions,
+ // we can work around these bugs. See http://crbug.com/41730.
+ CERT_StringFromCertFcn old_callback = NULL;
+ status = CERT_RegisterAlternateOCSPAIAInfoCallBack(
+ GetAlternateOCSPAIAInfo, &old_callback);
+ if (status == SECSuccess) {
+ DCHECK(!old_callback);
+ } else {
+ NOTREACHED() << "Error initializing OCSP: " << PR_GetError();
+ }
+}
+
+OCSPNSSInitialization::~OCSPNSSInitialization() {}
+
+base::LazyInstance<OCSPNSSInitialization> g_ocsp_nss_initialization(
+ base::LINKER_INITIALIZED);
// Concrete class for SEC_HTTP_REQUEST_SESSION.
// Public methods except virtual methods of URLRequest::Delegate (On* methods)
@@ -200,7 +251,7 @@ class OCSPRequestSession
// |io_loop_| was initialized to be NULL in constructor, and
// set only in StartURLRequest, so no need to lock |lock_| here.
DCHECK(!io_loop_);
- Singleton<OCSPInitSingleton>()->PostTaskToIOLoop(
+ g_ocsp_io_loop.Get().PostTaskToIOLoop(
FROM_HERE,
NewRunnableMethod(this, &OCSPRequestSession::StartURLRequest));
}
@@ -339,11 +390,14 @@ class OCSPRequestSession
}
}
+ // Runs on |g_ocsp_io_loop|'s IO loop.
void StartURLRequest() {
DCHECK(!request_);
- URLRequestContext* url_request_context =
- OCSPInitSingleton::url_request_context();
+ pthread_mutex_lock(&g_request_context_lock);
+ URLRequestContext* url_request_context = g_request_context;
+ pthread_mutex_unlock(&g_request_context_lock);
+
if (url_request_context == NULL)
return;
@@ -476,7 +530,10 @@ SECStatus OCSPCreateSession(const char* host, PRUint16 portnum,
SEC_HTTP_SERVER_SESSION* pSession) {
VLOG(1) << "OCSP create session: host=" << host << " port=" << portnum;
DCHECK(!MessageLoop::current());
- if (OCSPInitSingleton::url_request_context() == NULL) {
+ pthread_mutex_lock(&g_request_context_lock);
+ URLRequestContext* request_context = g_request_context;
+ pthread_mutex_unlock(&g_request_context_lock);
+ if (request_context == NULL) {
LOG(ERROR) << "No URLRequestContext for OCSP handler.";
// The application failed to call SetURLRequestContextForOCSP, so we
// can't create and use URLRequest. PR_NOT_IMPLEMENTED_ERROR is not an
@@ -783,17 +840,40 @@ char* GetAlternateOCSPAIAInfo(CERTCertificate *cert) {
namespace net {
+void SetMessageLoopForOCSP() {
+ // Must have a MessageLoopForIO.
+ DCHECK(MessageLoopForIO::current());
+
+ bool used = g_ocsp_io_loop.Get().used();
+
+ // Should not be called when g_ocsp_io_loop has already been used.
+ DCHECK(!used);
+}
+
void EnsureOCSPInit() {
- Singleton<OCSPInitSingleton>::get();
+ g_ocsp_io_loop.Get().StartUsing();
+ g_ocsp_nss_initialization.Get();
}
// This function would be called before NSS initialization.
void SetURLRequestContextForOCSP(URLRequestContext* request_context) {
- OCSPInitSingleton::set_url_request_context(request_context);
+ pthread_mutex_lock(&g_request_context_lock);
+ if (request_context) {
+ DCHECK(request_context->is_main());
+ DCHECK(!g_request_context);
+ } else {
+ DCHECK(g_request_context);
+ }
+ g_request_context = request_context;
+ pthread_mutex_unlock(&g_request_context_lock);
}
URLRequestContext* GetURLRequestContextForOCSP() {
- return OCSPInitSingleton::url_request_context();
+ pthread_mutex_lock(&g_request_context_lock);
+ URLRequestContext* request_context = g_request_context;
+ pthread_mutex_unlock(&g_request_context_lock);
+ DCHECK(request_context->is_main());
+ return request_context;
}
} // namespace net
diff --git a/net/ocsp/nss_ocsp.h b/net/ocsp/nss_ocsp.h
index a31d025..97d69b9 100644
--- a/net/ocsp/nss_ocsp.h
+++ b/net/ocsp/nss_ocsp.h
@@ -10,6 +10,11 @@ class URLRequestContext;
namespace net {
+// Sets the MessageLoop for OCSP to the current message loop.
+// This should be called before EnsureOCSPInit() if you want to
+// control the message loop for OCSP.
+void SetMessageLoopForOCSP();
+
// Initializes OCSP handlers for NSS. This must be called before any
// certificate verification functions. This function is thread-safe, and OCSP
// handlers will only ever be initialized once.
diff --git a/net/proxy/proxy_script_fetcher.cc b/net/proxy/proxy_script_fetcher.cc
index 0398134..0856430 100644
--- a/net/proxy/proxy_script_fetcher.cc
+++ b/net/proxy/proxy_script_fetcher.cc
@@ -412,4 +412,5 @@ size_t ProxyScriptFetcher::SetSizeConstraintForUnittest(size_t size_bytes) {
return prev;
}
+
} // namespace net
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc
index 329f83f..518d43a 100644
--- a/net/url_request/url_request_context.cc
+++ b/net/url_request/url_request_context.cc
@@ -16,7 +16,8 @@ URLRequestContext::URLRequestContext()
http_auth_handler_factory_(NULL),
network_delegate_(NULL),
cookie_policy_(NULL),
- transport_security_state_(NULL) {
+ transport_security_state_(NULL),
+ is_main_(false) {
}
const std::string& URLRequestContext::GetUserAgent(const GURL& url) const {
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index 96de77d..bbbae67 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -109,6 +109,11 @@ class URLRequestContext
referrer_charset_ = charset;
}
+ // Controls whether or not the URLRequestContext considers itself to be the
+ // "main" URLRequestContext.
+ bool is_main() const { return is_main_; }
+ void set_is_main(bool is_main) { is_main_ = is_main; }
+
protected:
friend class base::RefCountedThreadSafe<URLRequestContext>;
@@ -137,6 +142,9 @@ class URLRequestContext
std::string referrer_charset_;
private:
+ // Indicates whether or not this is the main URLRequestContext.
+ bool is_main_;
+
DISALLOW_COPY_AND_ASSIGN(URLRequestContext);
};