| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/ssl/ssl_error_handler.h" |
| |
| #include "base/bind.h" |
| #include "content/browser/frame_host/navigation_controller_impl.h" |
| #include "content/browser/frame_host/render_frame_host_impl.h" |
| #include "content/browser/ssl/ssl_cert_error_handler.h" |
| #include "content/browser/web_contents/web_contents_impl.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/resource_request_info.h" |
| #include "net/base/net_errors.h" |
| #include "net/url_request/url_request.h" |
| |
| using net::SSLInfo; |
| |
| namespace content { |
| |
| SSLErrorHandler::SSLErrorHandler(const base::WeakPtr<Delegate>& delegate, |
| const GlobalRequestID& id, |
| ResourceType::Type resource_type, |
| const GURL& url, |
| int render_process_id, |
| int render_frame_id) |
| : manager_(NULL), |
| request_id_(id), |
| delegate_(delegate), |
| render_process_id_(render_process_id), |
| render_frame_id_(render_frame_id), |
| request_url_(url), |
| resource_type_(resource_type), |
| request_has_been_notified_(false) { |
| DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| DCHECK(delegate.get()); |
| |
| // This makes sure we don't disappear on the IO thread until we've given an |
| // answer to the net::URLRequest. |
| // |
| // Release in CompleteCancelRequest, CompleteContinueRequest, or |
| // CompleteTakeNoAction. |
| AddRef(); |
| } |
| |
| SSLErrorHandler::~SSLErrorHandler() {} |
| |
| void SSLErrorHandler::OnDispatchFailed() { |
| TakeNoAction(); |
| } |
| |
| void SSLErrorHandler::OnDispatched() { |
| TakeNoAction(); |
| } |
| |
| SSLCertErrorHandler* SSLErrorHandler::AsSSLCertErrorHandler() { |
| return NULL; |
| } |
| |
| void SSLErrorHandler::Dispatch() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| |
| WebContents* web_contents = NULL; |
| RenderFrameHost* render_frame_host = |
| RenderFrameHost::FromID(render_process_id_, render_frame_id_); |
| web_contents = WebContents::FromRenderFrameHost(render_frame_host); |
| |
| if (!web_contents) { |
| // We arrived on the UI thread, but the tab we're looking for is no longer |
| // here. |
| OnDispatchFailed(); |
| return; |
| } |
| |
| // Hand ourselves off to the SSLManager. |
| manager_ = |
| static_cast<NavigationControllerImpl*>(&web_contents->GetController())-> |
| ssl_manager(); |
| OnDispatched(); |
| } |
| |
| void SSLErrorHandler::CancelRequest() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| |
| // We need to complete this task on the IO thread. |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind( |
| &SSLErrorHandler::CompleteCancelRequest, this, net::ERR_ABORTED)); |
| } |
| |
| void SSLErrorHandler::DenyRequest() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| |
| // We need to complete this task on the IO thread. |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind( |
| &SSLErrorHandler::CompleteCancelRequest, this, |
| net::ERR_INSECURE_RESPONSE)); |
| } |
| |
| void SSLErrorHandler::ContinueRequest() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| |
| // We need to complete this task on the IO thread. |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&SSLErrorHandler::CompleteContinueRequest, this)); |
| } |
| |
| void SSLErrorHandler::TakeNoAction() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| |
| // We need to complete this task on the IO thread. |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&SSLErrorHandler::CompleteTakeNoAction, this)); |
| } |
| |
| void SSLErrorHandler::CompleteCancelRequest(int error) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| |
| // It is important that we notify the net::URLRequest only once. If we try |
| // to notify the request twice, it may no longer exist and |this| might have |
| // already have been deleted. |
| DCHECK(!request_has_been_notified_); |
| if (request_has_been_notified_) |
| return; |
| |
| SSLCertErrorHandler* cert_error = AsSSLCertErrorHandler(); |
| const SSLInfo* ssl_info = NULL; |
| if (cert_error) |
| ssl_info = &cert_error->ssl_info(); |
| if (delegate_.get()) |
| delegate_->CancelSSLRequest(request_id_, error, ssl_info); |
| request_has_been_notified_ = true; |
| |
| // We're done with this object on the IO thread. |
| Release(); |
| } |
| |
| void SSLErrorHandler::CompleteContinueRequest() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| |
| // It is important that we notify the net::URLRequest only once. If we try to |
| // notify the request twice, it may no longer exist and |this| might have |
| // already have been deleted. |
| DCHECK(!request_has_been_notified_); |
| if (request_has_been_notified_) |
| return; |
| |
| if (delegate_.get()) |
| delegate_->ContinueSSLRequest(request_id_); |
| request_has_been_notified_ = true; |
| |
| // We're done with this object on the IO thread. |
| Release(); |
| } |
| |
| void SSLErrorHandler::CompleteTakeNoAction() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| |
| // It is important that we notify the net::URLRequest only once. If we try to |
| // notify the request twice, it may no longer exist and |this| might have |
| // already have been deleted. |
| DCHECK(!request_has_been_notified_); |
| if (request_has_been_notified_) |
| return; |
| |
| request_has_been_notified_ = true; |
| |
| // We're done with this object on the IO thread. |
| Release(); |
| } |
| |
| } // namespace content |