1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ssl/ssl_add_cert_handler.h" 6 7#include "base/bind.h" 8#include "chrome/browser/ssl/ssl_tab_helper.h" 9#include "chrome/browser/tab_contents/tab_util.h" 10#include "content/public/browser/browser_thread.h" 11#include "content/public/browser/resource_request_info.h" 12#include "content/public/browser/web_contents.h" 13#include "net/base/net_errors.h" 14#include "net/cert/cert_database.h" 15#include "net/cert/x509_certificate.h" 16#include "net/url_request/url_request.h" 17 18using content::BrowserThread; 19using content::WebContents; 20 21SSLAddCertHandler::SSLAddCertHandler(net::URLRequest* request, 22 net::X509Certificate* cert, 23 int render_process_host_id, 24 int render_view_id) 25 : cert_(cert), 26 render_process_host_id_(render_process_host_id), 27 render_view_id_(render_view_id) { 28 network_request_id_ 29 = content::ResourceRequestInfo::ForRequest(request)->GetRequestID(); 30 // Stay alive until the process completes and Finished() is called. 31 AddRef(); 32 // Delay adding the certificate until the next mainloop iteration. 33 BrowserThread::PostTask( 34 BrowserThread::IO, FROM_HERE, 35 base::Bind(&SSLAddCertHandler::Run, this)); 36} 37 38SSLAddCertHandler::~SSLAddCertHandler() {} 39 40void SSLAddCertHandler::Run() { 41 int cert_error = net::CertDatabase::GetInstance()->CheckUserCert(cert_.get()); 42 if (cert_error != net::OK) { 43 LOG_IF(ERROR, cert_error == net::ERR_NO_PRIVATE_KEY_FOR_CERT) 44 << "No corresponding private key in store for cert: " 45 << (cert_.get() ? cert_->subject().GetDisplayName() : "NULL"); 46 47 BrowserThread::PostTask( 48 BrowserThread::UI, FROM_HERE, 49 base::Bind( 50 &SSLAddCertHandler::CallVerifyClientCertificateError, this, 51 cert_error)); 52 Finished(false); 53 return; 54 } 55 // TODO(davidben): Move the existing certificate dialog elsewhere, make 56 // AskToAddCert send a message to the RenderViewHostDelegate, and ask when we 57 // cannot completely verify the certificate for whatever reason. 58 59 // AskToAddCert(); 60 Finished(true); 61} 62 63#if !defined(OS_MACOSX) 64void SSLAddCertHandler::AskToAddCert() { 65 // TODO(snej): Someone should add Windows and GTK implementations with UI. 66 Finished(true); 67} 68#endif 69 70void SSLAddCertHandler::Finished(bool add_cert) { 71 int cert_error = net::OK; 72 if (add_cert) 73 cert_error = net::CertDatabase::GetInstance()->AddUserCert(cert_.get()); 74 75 BrowserThread::PostTask( 76 BrowserThread::UI, FROM_HERE, 77 base::Bind( 78 &SSLAddCertHandler::CallAddClientCertificate, this, 79 add_cert, cert_error)); 80 81 Release(); 82} 83 84void SSLAddCertHandler::CallVerifyClientCertificateError(int cert_error) { 85 WebContents* tab = tab_util::GetWebContentsByID( 86 render_process_host_id_, render_view_id_); 87 if (!tab) 88 return; 89 90 SSLTabHelper* ssl_tab_helper = SSLTabHelper::FromWebContents(tab); 91 ssl_tab_helper->OnVerifyClientCertificateError(this, cert_error); 92} 93 94void SSLAddCertHandler::CallAddClientCertificate(bool add_cert, 95 int cert_error) { 96 WebContents* tab = tab_util::GetWebContentsByID( 97 render_process_host_id_, render_view_id_); 98 if (!tab) 99 return; 100 101 SSLTabHelper* ssl_tab_helper = SSLTabHelper::FromWebContents(tab); 102 if (add_cert) { 103 if (cert_error == net::OK) { 104 ssl_tab_helper->OnAddClientCertificateSuccess(this); 105 } else { 106 ssl_tab_helper->OnAddClientCertificateError(this, cert_error); 107 } 108 } 109 ssl_tab_helper->OnAddClientCertificateFinished(this); 110} 111