net: make QUIC ProofVerifier more generic (reland).

r213862 caused a crash when QUIC was enabled because, if a certificate
verification completely immmediately, the details scoped_ptr wouldn't be set.
This ended up crashing on a NULL pointer later in the code.

BUG=none
[email protected]

Review URL: https://codereview.chromium.org/21086003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214380 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index 6f54788..c8b197b 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -33,8 +33,6 @@
 ProofVerifierChromium::ProofVerifierChromium(CertVerifier* cert_verifier,
                                              const BoundNetLog& net_log)
   : cert_verifier_(cert_verifier),
-    cert_verify_result_(NULL),
-    error_details_(NULL),
     next_state_(STATE_NONE),
     net_log_(net_log) {
 }
@@ -43,29 +41,36 @@
   verifier_.reset();
 }
 
-int ProofVerifierChromium::VerifyProof(const string& hostname,
-                                       const string& server_config,
-                                       const vector<string>& certs,
-                                       const string& signature,
-                                       std::string* error_details,
-                                       CertVerifyResult* cert_verify_result,
-                                       const CompletionCallback& callback) {
+ProofVerifierChromium::Status ProofVerifierChromium::VerifyProof(
+    const string& hostname,
+    const string& server_config,
+    const vector<string>& certs,
+    const string& signature,
+    std::string* error_details,
+    scoped_ptr<ProofVerifyDetails>* details,
+    ProofVerifierCallback* callback) {
   DCHECK(error_details);
-  DCHECK(cert_verify_result);
+  DCHECK(details);
+  DCHECK(callback);
+
+  callback_.reset(callback);
   error_details->clear();
-  cert_verify_result->Reset();
 
   DCHECK_EQ(STATE_NONE, next_state_);
   if (STATE_NONE != next_state_) {
     *error_details = "Certificate is already set and VerifyProof has begun";
     DLOG(WARNING) << *error_details;
-    return ERR_FAILED;
+    return FAILURE;
   }
 
+  verify_details_.reset(new ProofVerifyDetailsChromium);
+
   if (certs.empty()) {
     *error_details = "Failed to create certificate chain. Certs are empty.";
     DLOG(WARNING) << *error_details;
-    return ERR_FAILED;
+    verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
+    details->reset(verify_details_.release());
+    return FAILURE;
   }
 
   // Convert certs to X509Certificate.
@@ -77,8 +82,9 @@
   if (!cert_.get()) {
     *error_details = "Failed to create certificate chain";
     DLOG(WARNING) << *error_details;
-    cert_verify_result->cert_status = CERT_STATUS_INVALID;
-    return ERR_FAILED;
+    verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
+    details->reset(verify_details_.release());
+    return FAILURE;
   }
 
   // We call VerifySignature first to avoid copying of server_config and
@@ -86,16 +92,25 @@
   if (!VerifySignature(server_config, signature, certs[0])) {
     *error_details = "Failed to verify signature of server config";
     DLOG(WARNING) << *error_details;
-    return ERR_FAILED;
+    verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
+    details->reset(verify_details_.release());
+    return FAILURE;
   }
 
   hostname_ = hostname;
-  callback_ = callback;
-  error_details_ = error_details;
-  cert_verify_result_ = cert_verify_result;
 
   next_state_ = STATE_VERIFY_CERT;
-  return DoLoop(OK);
+  switch (DoLoop(OK)) {
+    case OK:
+      details->reset(verify_details_.release());
+      return SUCCESS;
+    case ERR_IO_PENDING:
+      return PENDING;
+    default:
+      *error_details = error_details_;
+      details->reset(verify_details_.release());
+      return FAILURE;
+  }
 }
 
 int ProofVerifierChromium::DoLoop(int last_result) {
@@ -124,7 +139,9 @@
 void ProofVerifierChromium::OnIOComplete(int result) {
   int rv = DoLoop(result);
   if (rv != ERR_IO_PENDING) {
-    base::ResetAndReturn(&callback_).Run(rv);
+    scoped_ptr<ProofVerifyDetails> scoped_details(verify_details_.release());
+    callback_->Run(rv == OK, error_details_, &scoped_details);
+    callback_.reset();
   }
 }
 
@@ -138,7 +155,7 @@
       hostname_,
       flags,
       SSLConfigService::GetCRLSet().get(),
-      cert_verify_result_,
+      &verify_details_->cert_verify_result,
       base::Bind(&ProofVerifierChromium::OnIOComplete,
                  base::Unretained(this)),
       net_log_);
@@ -148,9 +165,9 @@
   verifier_.reset();
 
   if (result <= ERR_FAILED) {
-    *error_details_ = StringPrintf("Failed to verify certificate chain: %s",
-                                   ErrorToString(result));
-    DLOG(WARNING) << *error_details_;
+    error_details_ = StringPrintf("Failed to verify certificate chain: %s",
+                                  ErrorToString(result));
+    DLOG(WARNING) << error_details_;
     result = ERR_FAILED;
   }