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