1 // Copyright (c) 2010 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_error_handler.h" 6 7 #include "chrome/browser/ssl/ssl_cert_error_handler.h" 8 #include "chrome/browser/tab_contents/tab_util.h" 9 #include "content/browser/browser_thread.h" 10 #include "content/browser/renderer_host/resource_dispatcher_host.h" 11 #include "content/browser/renderer_host/resource_dispatcher_host_request_info.h" 12 #include "content/browser/tab_contents/tab_contents.h" 13 #include "net/base/net_errors.h" 14 #include "net/url_request/url_request.h" 15 16 SSLErrorHandler::SSLErrorHandler(ResourceDispatcherHost* rdh, 17 net::URLRequest* request, 18 ResourceType::Type resource_type) 19 : manager_(NULL), 20 request_id_(0, 0), 21 resource_dispatcher_host_(rdh), 22 request_url_(request->url()), 23 resource_type_(resource_type), 24 request_has_been_notified_(false) { 25 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 26 27 ResourceDispatcherHostRequestInfo* info = 28 ResourceDispatcherHost::InfoForRequest(request); 29 request_id_.child_id = info->child_id(); 30 request_id_.request_id = info->request_id(); 31 32 if (!ResourceDispatcherHost::RenderViewForRequest(request, 33 &render_process_host_id_, 34 &tab_contents_id_)) 35 NOTREACHED(); 36 37 // This makes sure we don't disappear on the IO thread until we've given an 38 // answer to the net::URLRequest. 39 // 40 // Release in CompleteCancelRequest, CompleteContinueRequest, or 41 // CompleteTakeNoAction. 42 AddRef(); 43 } 44 45 SSLErrorHandler::~SSLErrorHandler() {} 46 47 void SSLErrorHandler::OnDispatchFailed() { 48 TakeNoAction(); 49 } 50 51 void SSLErrorHandler::OnDispatched() { 52 TakeNoAction(); 53 } 54 55 SSLCertErrorHandler* SSLErrorHandler::AsSSLCertErrorHandler() { 56 return NULL; 57 } 58 59 void SSLErrorHandler::Dispatch() { 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 61 62 TabContents* tab_contents = GetTabContents(); 63 if (!tab_contents) { 64 // We arrived on the UI thread, but the tab we're looking for is no longer 65 // here. 66 OnDispatchFailed(); 67 return; 68 } 69 70 // Hand ourselves off to the SSLManager. 71 manager_ = tab_contents->controller().ssl_manager(); 72 OnDispatched(); 73 } 74 75 TabContents* SSLErrorHandler::GetTabContents() { 76 return tab_util::GetTabContentsByID(render_process_host_id_, 77 tab_contents_id_); 78 } 79 80 void SSLErrorHandler::CancelRequest() { 81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 82 83 // We need to complete this task on the IO thread. 84 BrowserThread::PostTask( 85 BrowserThread::IO, FROM_HERE, 86 NewRunnableMethod( 87 this, &SSLErrorHandler::CompleteCancelRequest, net::ERR_ABORTED)); 88 } 89 90 void SSLErrorHandler::DenyRequest() { 91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 92 93 // We need to complete this task on the IO thread. 94 BrowserThread::PostTask( 95 BrowserThread::IO, FROM_HERE, 96 NewRunnableMethod( 97 this, &SSLErrorHandler::CompleteCancelRequest, 98 net::ERR_INSECURE_RESPONSE)); 99 } 100 101 void SSLErrorHandler::ContinueRequest() { 102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 103 104 // We need to complete this task on the IO thread. 105 BrowserThread::PostTask( 106 BrowserThread::IO, FROM_HERE, 107 NewRunnableMethod(this, &SSLErrorHandler::CompleteContinueRequest)); 108 } 109 110 void SSLErrorHandler::TakeNoAction() { 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 112 113 // We need to complete this task on the IO thread. 114 BrowserThread::PostTask( 115 BrowserThread::IO, FROM_HERE, 116 NewRunnableMethod(this, &SSLErrorHandler::CompleteTakeNoAction)); 117 } 118 119 void SSLErrorHandler::CompleteCancelRequest(int error) { 120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 121 122 // It is important that we notify the net::URLRequest only once. If we try 123 // to notify the request twice, it may no longer exist and |this| might have 124 // already have been deleted. 125 DCHECK(!request_has_been_notified_); 126 if (request_has_been_notified_) 127 return; 128 129 net::URLRequest* request = 130 resource_dispatcher_host_->GetURLRequest(request_id_); 131 if (request) { 132 // The request can be NULL if it was cancelled by the renderer (as the 133 // result of the user navigating to a new page from the location bar). 134 DVLOG(1) << "CompleteCancelRequest() url: " << request->url().spec(); 135 SSLCertErrorHandler* cert_error = AsSSLCertErrorHandler(); 136 if (cert_error) 137 request->SimulateSSLError(error, cert_error->ssl_info()); 138 else 139 request->SimulateError(error); 140 } 141 request_has_been_notified_ = true; 142 143 // We're done with this object on the IO thread. 144 Release(); 145 } 146 147 void SSLErrorHandler::CompleteContinueRequest() { 148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 149 150 // It is important that we notify the net::URLRequest only once. If we try to 151 // notify the request twice, it may no longer exist and |this| might have 152 // already have been deleted. 153 DCHECK(!request_has_been_notified_); 154 if (request_has_been_notified_) 155 return; 156 157 net::URLRequest* request = 158 resource_dispatcher_host_->GetURLRequest(request_id_); 159 if (request) { 160 // The request can be NULL if it was cancelled by the renderer (as the 161 // result of the user navigating to a new page from the location bar). 162 DVLOG(1) << "CompleteContinueRequest() url: " << request->url().spec(); 163 request->ContinueDespiteLastError(); 164 } 165 request_has_been_notified_ = true; 166 167 // We're done with this object on the IO thread. 168 Release(); 169 } 170 171 void SSLErrorHandler::CompleteTakeNoAction() { 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 173 174 // It is important that we notify the net::URLRequest only once. If we try to 175 // notify the request twice, it may no longer exist and |this| might have 176 // already have been deleted. 177 DCHECK(!request_has_been_notified_); 178 if (request_has_been_notified_) 179 return; 180 181 request_has_been_notified_ = true; 182 183 // We're done with this object on the IO thread. 184 Release(); 185 } 186