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 "content/browser/ssl/ssl_error_handler.h" 6 7#include "base/bind.h" 8#include "content/browser/frame_host/navigation_controller_impl.h" 9#include "content/browser/frame_host/render_frame_host_impl.h" 10#include "content/browser/ssl/ssl_cert_error_handler.h" 11#include "content/browser/web_contents/web_contents_impl.h" 12#include "content/public/browser/browser_thread.h" 13#include "content/public/browser/resource_request_info.h" 14#include "net/base/net_errors.h" 15#include "net/url_request/url_request.h" 16 17using net::SSLInfo; 18 19namespace content { 20 21SSLErrorHandler::SSLErrorHandler(const base::WeakPtr<Delegate>& delegate, 22 const GlobalRequestID& id, 23 ResourceType resource_type, 24 const GURL& url, 25 int render_process_id, 26 int render_frame_id) 27 : manager_(NULL), 28 request_id_(id), 29 delegate_(delegate), 30 render_process_id_(render_process_id), 31 render_frame_id_(render_frame_id), 32 request_url_(url), 33 resource_type_(resource_type), 34 request_has_been_notified_(false) { 35 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 36 DCHECK(delegate.get()); 37 38 // This makes sure we don't disappear on the IO thread until we've given an 39 // answer to the net::URLRequest. 40 // 41 // Release in CompleteCancelRequest, CompleteContinueRequest, or 42 // CompleteTakeNoAction. 43 AddRef(); 44} 45 46SSLErrorHandler::~SSLErrorHandler() {} 47 48void SSLErrorHandler::OnDispatchFailed() { 49 TakeNoAction(); 50} 51 52void SSLErrorHandler::OnDispatched() { 53 TakeNoAction(); 54} 55 56SSLCertErrorHandler* SSLErrorHandler::AsSSLCertErrorHandler() { 57 return NULL; 58} 59 60void SSLErrorHandler::Dispatch() { 61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 62 63 WebContents* web_contents = NULL; 64 RenderFrameHost* render_frame_host = 65 RenderFrameHost::FromID(render_process_id_, render_frame_id_); 66 web_contents = WebContents::FromRenderFrameHost(render_frame_host); 67 68 if (!web_contents) { 69 // We arrived on the UI thread, but the tab we're looking for is no longer 70 // here. 71 OnDispatchFailed(); 72 return; 73 } 74 75 // Hand ourselves off to the SSLManager. 76 manager_ = 77 static_cast<NavigationControllerImpl*>(&web_contents->GetController())-> 78 ssl_manager(); 79 OnDispatched(); 80} 81 82void SSLErrorHandler::CancelRequest() { 83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 84 85 // We need to complete this task on the IO thread. 86 BrowserThread::PostTask( 87 BrowserThread::IO, FROM_HERE, 88 base::Bind( 89 &SSLErrorHandler::CompleteCancelRequest, this, net::ERR_ABORTED)); 90} 91 92void SSLErrorHandler::DenyRequest() { 93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 94 95 // We need to complete this task on the IO thread. 96 BrowserThread::PostTask( 97 BrowserThread::IO, FROM_HERE, 98 base::Bind( 99 &SSLErrorHandler::CompleteCancelRequest, this, 100 net::ERR_INSECURE_RESPONSE)); 101} 102 103void SSLErrorHandler::ContinueRequest() { 104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 105 106 // We need to complete this task on the IO thread. 107 BrowserThread::PostTask( 108 BrowserThread::IO, FROM_HERE, 109 base::Bind(&SSLErrorHandler::CompleteContinueRequest, this)); 110} 111 112void SSLErrorHandler::TakeNoAction() { 113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 114 115 // We need to complete this task on the IO thread. 116 BrowserThread::PostTask( 117 BrowserThread::IO, FROM_HERE, 118 base::Bind(&SSLErrorHandler::CompleteTakeNoAction, this)); 119} 120 121void SSLErrorHandler::CompleteCancelRequest(int error) { 122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 123 124 // It is important that we notify the net::URLRequest only once. If we try 125 // to notify the request twice, it may no longer exist and |this| might have 126 // already have been deleted. 127 DCHECK(!request_has_been_notified_); 128 if (request_has_been_notified_) 129 return; 130 131 SSLCertErrorHandler* cert_error = AsSSLCertErrorHandler(); 132 const SSLInfo* ssl_info = NULL; 133 if (cert_error) 134 ssl_info = &cert_error->ssl_info(); 135 if (delegate_.get()) 136 delegate_->CancelSSLRequest(request_id_, error, ssl_info); 137 request_has_been_notified_ = true; 138 139 // We're done with this object on the IO thread. 140 Release(); 141} 142 143void SSLErrorHandler::CompleteContinueRequest() { 144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 145 146 // It is important that we notify the net::URLRequest only once. If we try to 147 // notify the request twice, it may no longer exist and |this| might have 148 // already have been deleted. 149 DCHECK(!request_has_been_notified_); 150 if (request_has_been_notified_) 151 return; 152 153 if (delegate_.get()) 154 delegate_->ContinueSSLRequest(request_id_); 155 request_has_been_notified_ = true; 156 157 // We're done with this object on the IO thread. 158 Release(); 159} 160 161void SSLErrorHandler::CompleteTakeNoAction() { 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 163 164 // It is important that we notify the net::URLRequest only once. If we try to 165 // notify the request twice, it may no longer exist and |this| might have 166 // already have been deleted. 167 DCHECK(!request_has_been_notified_); 168 if (request_has_been_notified_) 169 return; 170 171 request_has_been_notified_ = true; 172 173 // We're done with this object on the IO thread. 174 Release(); 175} 176 177} // namespace content 178