Add session.setCertificateVerifyProc
authorCheng Zhao <zcbenz@gmail.com>
Wed, 18 Nov 2015 03:17:08 +0000 (11:17 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Wed, 18 Nov 2015 03:17:08 +0000 (11:17 +0800)
atom/browser/api/atom_api_session.cc
atom/browser/api/atom_api_session.h
atom/browser/net/atom_cert_verifier.cc
atom/browser/net/atom_cert_verifier.h

index 3510a21668e96aec35588d9005eb529c55479ad8..2a2c7b2fff35196691e507ccf3aeb92052e5d767 100644 (file)
@@ -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<v8::Value> 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<v8::Value> 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);
 }
 
index ebcfc45223db183b635523a5358169cdc8d68c5b..01dc0a408a8c19341058a732d6a9c1285417028f 100644 (file)
@@ -8,7 +8,6 @@
 #include <string>
 
 #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<Session>,
-               public AtomCertVerifier::Delegate,
                public content::DownloadManager::Observer {
  public:
   using ResolveProxyCallback = base::Callback<void(std::string)>;
@@ -74,6 +72,7 @@ class Session: public mate::TrackableObject<Session>,
   void SetDownloadPath(const base::FilePath& path);
   void EnableNetworkEmulation(const mate::Dictionary& options);
   void DisableNetworkEmulation();
+  void SetCertVerifyProc(v8::Local<v8::Value> proc, mate::Arguments* args);
   v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
 
   // Cached object for cookies API.
index 0f94e4fe2ad22ea6f14db3e349d03346c71ecef7..3633d805fb5b89707c1924d40ab3d10e2bb6e14e 100644 (file)
@@ -15,30 +15,31 @@ using content::BrowserThread;
 
 namespace atom {
 
-AtomCertVerifier::CertVerifyRequest::~CertVerifyRequest() {
-}
-
-void AtomCertVerifier::CertVerifyRequest::ContinueWithResult(int result) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+namespace {
 
-  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
index 8736db0f8723b12a9b703b1db28e4a15b15108be..796ae2849bda44743699e9bf03ca830608d16189 100644 (file)
@@ -8,61 +8,22 @@
 #include <string>
 
 #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<net::X509Certificate> cert;
-    const std::string& hostname;
-    net::CompletionCallback callback;
-  };
-
-  class CertVerifyRequest
-      : public base::RefCountedThreadSafe<CertVerifyRequest> {
-   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>;
-    ~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<CertVerifyRequest>& request) {}
-  };
-
   AtomCertVerifier();
   virtual ~AtomCertVerifier();
 
-  void SetDelegate(Delegate* delegate) {
-    delegate_ = delegate;
-  }
+  using VerifyProc =
+      base::Callback<void(const std::string& hostname,
+                          scoped_refptr<net::X509Certificate>,
+                          const base::Callback<void(bool)>&)>;
+
+  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<net::CertVerifier> default_cert_verifier_;
 
   DISALLOW_COPY_AND_ASSIGN(AtomCertVerifier);