• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SSLErrorHandler(ResourceDispatcherHost * rdh,net::URLRequest * request,ResourceType::Type resource_type)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 
~SSLErrorHandler()45 SSLErrorHandler::~SSLErrorHandler() {}
46 
OnDispatchFailed()47 void SSLErrorHandler::OnDispatchFailed() {
48   TakeNoAction();
49 }
50 
OnDispatched()51 void SSLErrorHandler::OnDispatched() {
52   TakeNoAction();
53 }
54 
AsSSLCertErrorHandler()55 SSLCertErrorHandler* SSLErrorHandler::AsSSLCertErrorHandler() {
56   return NULL;
57 }
58 
Dispatch()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 
GetTabContents()75 TabContents* SSLErrorHandler::GetTabContents() {
76   return tab_util::GetTabContentsByID(render_process_host_id_,
77                                       tab_contents_id_);
78 }
79 
CancelRequest()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 
DenyRequest()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 
ContinueRequest()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 
TakeNoAction()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 
CompleteCancelRequest(int error)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 
CompleteContinueRequest()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 
CompleteTakeNoAction()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