From c5bfac196914218ff98d2a45bc6287641594deea Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 18 Nov 2015 11:17:08 +0800 Subject: [PATCH] Add session.setCertificateVerifyProc --- atom/browser/api/atom_api_session.cc | 15 +++++- atom/browser/api/atom_api_session.h | 3 +- atom/browser/net/atom_cert_verifier.cc | 74 ++++++++++---------------- atom/browser/net/atom_cert_verifier.h | 61 ++++----------------- 4 files changed, 51 insertions(+), 102 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 3510a21668e9..2a2c7b2fff35 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -13,6 +13,7 @@ #include "atom/browser/api/save_page_handler.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" +#include "atom/browser/net/atom_cert_verifier.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/file_path_converter.h" @@ -243,7 +244,6 @@ void SetProxyInIO(net::URLRequestContextGetter* getter, Session::Session(AtomBrowserContext* browser_context) : browser_context_(browser_context) { AttachAsUserData(browser_context); - browser_context->cert_verifier()->SetDelegate(this); // Observe DownloadManger to get download notifications. content::BrowserContext::GetDownloadManager(browser_context)-> @@ -276,7 +276,6 @@ bool Session::IsDestroyed() const { } void Session::Destroy() { - browser_context_->cert_verifier()->SetDelegate(nullptr); browser_context_ = nullptr; } @@ -358,6 +357,17 @@ void Session::DisableNetworkEmulation() { base::Passed(&conditions))); } +void Session::SetCertVerifyProc(v8::Local val, mate::Arguments* args) { + AtomCertVerifier::VerifyProc proc; + if (val.IsEmpty() || + !(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &proc))) { + args->ThrowError("Must pass null or function"); + return; + } + + browser_context_->cert_verifier()->SetVerifyProc(proc); +} + v8::Local Session::Cookies(v8::Isolate* isolate) { if (cookies_.IsEmpty()) { auto handle = atom::api::Cookies::Create(isolate, browser_context()); @@ -376,6 +386,7 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( .SetMethod("setDownloadPath", &Session::SetDownloadPath) .SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation) .SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation) + .SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc) .SetProperty("cookies", &Session::Cookies); } diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index ebcfc45223db..01dc0a408a8c 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -8,7 +8,6 @@ #include #include "atom/browser/api/trackable_object.h" -#include "atom/browser/net/atom_cert_verifier.h" #include "content/public/browser/download_manager.h" #include "native_mate/handle.h" #include "net/base/completion_callback.h" @@ -35,7 +34,6 @@ class AtomBrowserContext; namespace api { class Session: public mate::TrackableObject, - public AtomCertVerifier::Delegate, public content::DownloadManager::Observer { public: using ResolveProxyCallback = base::Callback; @@ -74,6 +72,7 @@ class Session: public mate::TrackableObject, void SetDownloadPath(const base::FilePath& path); void EnableNetworkEmulation(const mate::Dictionary& options); void DisableNetworkEmulation(); + void SetCertVerifyProc(v8::Local proc, mate::Arguments* args); v8::Local Cookies(v8::Isolate* isolate); // Cached object for cookies API. diff --git a/atom/browser/net/atom_cert_verifier.cc b/atom/browser/net/atom_cert_verifier.cc index 0f94e4fe2ad2..3633d805fb5b 100644 --- a/atom/browser/net/atom_cert_verifier.cc +++ b/atom/browser/net/atom_cert_verifier.cc @@ -15,30 +15,31 @@ using content::BrowserThread; namespace atom { -AtomCertVerifier::CertVerifyRequest::~CertVerifyRequest() { -} +namespace { -void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - if (handled_) - return; - - handled_ = true; +void OnResult( + net::CertVerifyResult* verify_result, + const net::CompletionCallback& callback, + bool result) { BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(args_.callback, - result == net::ERR_IO_PENDING ? result_ : result)); + base::Bind(callback, result ? net::OK : net::ERR_FAILED)); } +} // namespace + AtomCertVerifier::AtomCertVerifier() - : delegate_(nullptr) { - default_cert_verifier_.reset(net::CertVerifier::CreateDefault()); + : default_cert_verifier_(net::CertVerifier::CreateDefault()) { } AtomCertVerifier::~AtomCertVerifier() { } +void AtomCertVerifier::SetVerifyProc(const VerifyProc& proc) { + base::AutoLock auto_lock(lock_); + verify_proc_ = proc; +} + int AtomCertVerifier::Verify( net::X509Certificate* cert, const std::string& hostname, @@ -51,45 +52,26 @@ int AtomCertVerifier::Verify( const net::BoundNetLog& net_log) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (callback.is_null() || !verify_result || hostname.empty() || !delegate_) - return net::ERR_INVALID_ARGUMENT; - - VerifyArgs args = { cert, hostname, callback }; - int result = default_cert_verifier_->Verify( - cert, hostname, ocsp_response, flags, crl_set, verify_result, - base::Bind(&AtomCertVerifier::OnDefaultVerificationResult, - base::Unretained(this), args), - out_req, net_log); - if (result != net::OK && result != net::ERR_IO_PENDING) { - // The default verifier fails immediately. - VerifyCertificateFromDelegate(args, result); - return net::ERR_IO_PENDING; + VerifyProc proc; + { + base::AutoLock auto_lock(lock_); + proc = verify_proc_; } - return result; + if (proc.is_null()) + return default_cert_verifier_->Verify( + cert, hostname, ocsp_response, flags, crl_set, verify_result, callback, + out_req, net_log); + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(proc, hostname, make_scoped_refptr(cert), + base::Bind(OnResult, verify_result, callback))); + return net::ERR_IO_PENDING; } bool AtomCertVerifier::SupportsOCSPStapling() { return true; } -void AtomCertVerifier::VerifyCertificateFromDelegate( - const VerifyArgs& args, int result) { - CertVerifyRequest* request = new CertVerifyRequest(this, result, args); - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&Delegate::RequestCertVerification, - base::Unretained(delegate_), - make_scoped_refptr(request))); -} - -void AtomCertVerifier::OnDefaultVerificationResult( - const VerifyArgs& args, int result) { - if (result == net::OK) { - args.callback.Run(result); - return; - } - - VerifyCertificateFromDelegate(args, result); -} - } // namespace atom diff --git a/atom/browser/net/atom_cert_verifier.h b/atom/browser/net/atom_cert_verifier.h index 8736db0f8723..796ae2849bda 100644 --- a/atom/browser/net/atom_cert_verifier.h +++ b/atom/browser/net/atom_cert_verifier.h @@ -8,61 +8,22 @@ #include #include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" #include "net/cert/cert_verifier.h" namespace atom { class AtomCertVerifier : public net::CertVerifier { public: - struct VerifyArgs { - scoped_refptr cert; - const std::string& hostname; - net::CompletionCallback callback; - }; - - class CertVerifyRequest - : public base::RefCountedThreadSafe { - public: - CertVerifyRequest(AtomCertVerifier* cert_verifier, - int result, - const VerifyArgs& args) - : cert_verifier_(cert_verifier), - result_(result), - args_(args), - handled_(false) { - } - - void ContinueWithResult(int result); - - const VerifyArgs& args() const { return args_; } - - private: - friend class base::RefCountedThreadSafe; - ~CertVerifyRequest(); - - AtomCertVerifier* cert_verifier_; - int result_; - VerifyArgs args_; - bool handled_; - - DISALLOW_COPY_AND_ASSIGN(CertVerifyRequest); - }; - - class Delegate { - public: - virtual ~Delegate() {} - - // Called on UI thread. - virtual void RequestCertVerification( - const scoped_refptr& request) {} - }; - AtomCertVerifier(); virtual ~AtomCertVerifier(); - void SetDelegate(Delegate* delegate) { - delegate_ = delegate; - } + using VerifyProc = + base::Callback, + const base::Callback&)>; + + void SetVerifyProc(const VerifyProc& proc); protected: // net::CertVerifier: @@ -78,12 +39,8 @@ class AtomCertVerifier : public net::CertVerifier { bool SupportsOCSPStapling() override; private: - friend class CertVerifyRequest; - - void VerifyCertificateFromDelegate(const VerifyArgs& args, int result); - void OnDefaultVerificationResult(const VerifyArgs& args, int result); - - Delegate* delegate_; + base::Lock lock_; + VerifyProc verify_proc_; scoped_ptr default_cert_verifier_; DISALLOW_COPY_AND_ASSIGN(AtomCertVerifier);