| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/ssl/ssl_error_handler.h" | 5 #include "content/browser/ssl/ssl_error_handler.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "content/browser/frame_host/navigation_controller_impl.h" | 8 #include "content/browser/frame_host/navigation_controller_impl.h" |
| 9 #include "content/browser/frame_host/render_frame_host_impl.h" | 9 #include "content/browser/frame_host/render_frame_host_impl.h" |
| 10 #include "content/browser/ssl/ssl_manager.h" | |
| 11 #include "content/browser/ssl/ssl_policy.h" | |
| 12 #include "content/browser/web_contents/web_contents_impl.h" | 10 #include "content/browser/web_contents/web_contents_impl.h" |
| 13 #include "content/public/browser/browser_thread.h" | 11 #include "content/public/browser/browser_thread.h" |
| 14 #include "content/public/browser/resource_request_info.h" | 12 #include "content/public/browser/resource_request_info.h" |
| 15 #include "net/base/net_errors.h" | 13 #include "net/base/net_errors.h" |
| 16 #include "net/cert/cert_status_flags.h" | 14 #include "net/cert/cert_status_flags.h" |
| 17 #include "net/url_request/url_request.h" | 15 #include "net/url_request/url_request.h" |
| 18 | 16 |
| 19 using net::SSLInfo; | 17 using net::SSLInfo; |
| 20 | 18 |
| 21 namespace content { | 19 namespace content { |
| 22 | 20 |
| 23 SSLErrorHandler::SSLErrorHandler(const base::WeakPtr<Delegate>& delegate, | 21 namespace { |
| 22 |
| 23 void CompleteCancelRequest( |
| 24 const base::WeakPtr<SSLErrorHandler::Delegate>& delegate, |
| 25 const net::SSLInfo& ssl_info, |
| 26 int error) { |
| 27 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 28 if (delegate.get()) |
| 29 delegate->CancelSSLRequest(error, &ssl_info); |
| 30 } |
| 31 |
| 32 void CompleteContinueRequest( |
| 33 const base::WeakPtr<SSLErrorHandler::Delegate>& delegate) { |
| 34 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 35 if (delegate.get()) { |
| 36 delegate->ContinueSSLRequest(); |
| 37 } |
| 38 } |
| 39 |
| 40 } // namespace |
| 41 |
| 42 SSLErrorHandler::SSLErrorHandler(WebContents* web_contents, |
| 43 const base::WeakPtr<Delegate>& delegate, |
| 24 ResourceType resource_type, | 44 ResourceType resource_type, |
| 25 const GURL& url, | 45 const GURL& url, |
| 26 const net::SSLInfo& ssl_info, | 46 const net::SSLInfo& ssl_info, |
| 27 bool fatal) | 47 bool fatal) |
| 28 : manager_(NULL), | 48 : delegate_(delegate), |
| 29 delegate_(delegate), | |
| 30 request_has_been_notified_(false), | |
| 31 request_url_(url), | 49 request_url_(url), |
| 32 resource_type_(resource_type), | 50 resource_type_(resource_type), |
| 33 ssl_info_(ssl_info), | 51 ssl_info_(ssl_info), |
| 34 cert_error_(net::MapCertStatusToNetError(ssl_info.cert_status)), | 52 cert_error_(net::MapCertStatusToNetError(ssl_info.cert_status)), |
| 35 fatal_(fatal) { | 53 fatal_(fatal), |
| 36 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); | 54 web_contents_(web_contents) { |
| 37 DCHECK(delegate.get()); | 55 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 38 | |
| 39 // This makes sure we don't disappear on the IO thread until we've given an | |
| 40 // answer to the net::URLRequest. | |
| 41 // | |
| 42 // Release in CompleteCancelRequest, CompleteContinueRequest, or | |
| 43 // CompleteTakeNoAction. | |
| 44 AddRef(); | |
| 45 } | 56 } |
| 46 | 57 |
| 47 SSLErrorHandler::~SSLErrorHandler() {} | 58 SSLErrorHandler::~SSLErrorHandler() {} |
| 48 | 59 |
| 49 void SSLErrorHandler::OnDispatchFailed() { | |
| 50 // Requests can fail to dispatch because they don't have a WebContents. See | |
| 51 // <http://crbug.com/86537>. In this case we have to make a decision in this | |
| 52 // function, so we ignore revocation check failures. | |
| 53 if (net::IsCertStatusMinorError(ssl_info().cert_status)) { | |
| 54 ContinueRequest(); | |
| 55 } else { | |
| 56 CancelRequest(); | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 void SSLErrorHandler::OnDispatched() { | |
| 61 manager_->policy()->OnCertError(this); | |
| 62 } | |
| 63 | |
| 64 void SSLErrorHandler::Dispatch( | |
| 65 const base::Callback<WebContents*(void)>& web_contents_getter) { | |
| 66 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 67 | |
| 68 WebContents* web_contents = web_contents_getter.Run(); | |
| 69 | |
| 70 if (!web_contents) { | |
| 71 // We arrived on the UI thread, but the tab we're looking for is no longer | |
| 72 // here. | |
| 73 OnDispatchFailed(); | |
| 74 return; | |
| 75 } | |
| 76 | |
| 77 // Hand ourselves off to the SSLManager. | |
| 78 manager_ = | |
| 79 static_cast<NavigationControllerImpl*>(&web_contents->GetController())-> | |
| 80 ssl_manager(); | |
| 81 OnDispatched(); | |
| 82 } | |
| 83 | |
| 84 void SSLErrorHandler::CancelRequest() { | 60 void SSLErrorHandler::CancelRequest() { |
| 85 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 61 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 86 | 62 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 87 // We need to complete this task on the IO thread. | 63 base::Bind(&CompleteCancelRequest, delegate_, |
| 88 BrowserThread::PostTask( | 64 ssl_info(), net::ERR_ABORTED)); |
| 89 BrowserThread::IO, FROM_HERE, | |
| 90 base::Bind( | |
| 91 &SSLErrorHandler::CompleteCancelRequest, this, net::ERR_ABORTED)); | |
| 92 } | 65 } |
| 93 | 66 |
| 94 void SSLErrorHandler::DenyRequest() { | 67 void SSLErrorHandler::DenyRequest() { |
| 95 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 68 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 96 | 69 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 97 // We need to complete this task on the IO thread. | 70 base::Bind(&CompleteCancelRequest, delegate_, |
| 98 BrowserThread::PostTask( | 71 ssl_info(), net::ERR_INSECURE_RESPONSE)); |
| 99 BrowserThread::IO, FROM_HERE, | |
| 100 base::Bind( | |
| 101 &SSLErrorHandler::CompleteCancelRequest, this, | |
| 102 net::ERR_INSECURE_RESPONSE)); | |
| 103 } | 72 } |
| 104 | 73 |
| 105 void SSLErrorHandler::ContinueRequest() { | 74 void SSLErrorHandler::ContinueRequest() { |
| 106 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 75 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 107 | 76 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 108 // We need to complete this task on the IO thread. | 77 base::Bind(&CompleteContinueRequest, delegate_)); |
| 109 BrowserThread::PostTask( | |
| 110 BrowserThread::IO, FROM_HERE, | |
| 111 base::Bind(&SSLErrorHandler::CompleteContinueRequest, this)); | |
| 112 } | |
| 113 | |
| 114 void SSLErrorHandler::TakeNoAction() { | |
| 115 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 116 | |
| 117 // We need to complete this task on the IO thread. | |
| 118 BrowserThread::PostTask( | |
| 119 BrowserThread::IO, FROM_HERE, | |
| 120 base::Bind(&SSLErrorHandler::CompleteTakeNoAction, this)); | |
| 121 } | |
| 122 | |
| 123 SSLManager* SSLErrorHandler::GetManager() const { | |
| 124 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 125 return manager_; | |
| 126 } | |
| 127 | |
| 128 void SSLErrorHandler::CompleteCancelRequest(int error) { | |
| 129 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 130 | |
| 131 // It is important that we notify the net::URLRequest only once. If we try | |
| 132 // to notify the request twice, it may no longer exist and |this| might have | |
| 133 // already have been deleted. | |
| 134 DCHECK(!request_has_been_notified_); | |
| 135 if (request_has_been_notified_) | |
| 136 return; | |
| 137 | |
| 138 if (delegate_.get()) | |
| 139 delegate_->CancelSSLRequest(error, &ssl_info_); | |
| 140 request_has_been_notified_ = true; | |
| 141 | |
| 142 // We're done with this object on the IO thread. | |
| 143 Release(); | |
| 144 } | |
| 145 | |
| 146 void SSLErrorHandler::CompleteContinueRequest() { | |
| 147 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 148 | |
| 149 // It is important that we notify the net::URLRequest only once. If we try to | |
| 150 // notify the request twice, it may no longer exist and |this| might have | |
| 151 // already have been deleted. | |
| 152 DCHECK(!request_has_been_notified_); | |
| 153 if (request_has_been_notified_) | |
| 154 return; | |
| 155 | |
| 156 if (delegate_.get()) | |
| 157 delegate_->ContinueSSLRequest(); | |
| 158 request_has_been_notified_ = true; | |
| 159 | |
| 160 // We're done with this object on the IO thread. | |
| 161 Release(); | |
| 162 } | |
| 163 | |
| 164 void SSLErrorHandler::CompleteTakeNoAction() { | |
| 165 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 166 | |
| 167 // It is important that we notify the net::URLRequest only once. If we try to | |
| 168 // notify the request twice, it may no longer exist and |this| might have | |
| 169 // already have been deleted. | |
| 170 DCHECK(!request_has_been_notified_); | |
| 171 if (request_has_been_notified_) | |
| 172 return; | |
| 173 | |
| 174 request_has_been_notified_ = true; | |
| 175 | |
| 176 // We're done with this object on the IO thread. | |
| 177 Release(); | |
| 178 } | 78 } |
| 179 | 79 |
| 180 } // namespace content | 80 } // namespace content |
| OLD | NEW |