ssl_error_handler.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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
3// found in the LICENSE file.
4
5#include "content/browser/ssl/ssl_error_handler.h"
6
7#include "base/bind.h"
8#include "content/browser/renderer_host/render_view_host_impl.h"
9#include "content/browser/ssl/ssl_cert_error_handler.h"
10#include "content/browser/web_contents/navigation_controller_impl.h"
11#include "content/browser/web_contents/web_contents_impl.h"
12#include "content/public/browser/browser_thread.h"
13#include "content/public/browser/resource_request_info.h"
14#include "net/base/net_errors.h"
15#include "net/url_request/url_request.h"
16
17using net::SSLInfo;
18
19namespace content {
20
21SSLErrorHandler::SSLErrorHandler(const base::WeakPtr<Delegate>& delegate,
22                                 const GlobalRequestID& id,
23                                 ResourceType::Type resource_type,
24                                 const GURL& url,
25                                 int render_process_id,
26                                 int render_view_id)
27    : manager_(NULL),
28      request_id_(id),
29      delegate_(delegate),
30      render_process_id_(render_process_id),
31      render_view_id_(render_view_id),
32      request_url_(url),
33      resource_type_(resource_type),
34      request_has_been_notified_(false) {
35  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
36  DCHECK(delegate);
37
38  // This makes sure we don't disappear on the IO thread until we've given an
39  // answer to the net::URLRequest.
40  //
41  // Release in CompleteCancelRequest, CompleteContinueRequest, or
42  // CompleteTakeNoAction.
43  AddRef();
44}
45
46SSLErrorHandler::~SSLErrorHandler() {}
47
48void SSLErrorHandler::OnDispatchFailed() {
49  TakeNoAction();
50}
51
52void SSLErrorHandler::OnDispatched() {
53  TakeNoAction();
54}
55
56SSLCertErrorHandler* SSLErrorHandler::AsSSLCertErrorHandler() {
57  return NULL;
58}
59
60void SSLErrorHandler::Dispatch() {
61  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
62
63  WebContents* web_contents = NULL;
64  RenderViewHostImpl* render_view_host =
65      RenderViewHostImpl::FromID(render_process_id_, render_view_id_);
66  if (render_view_host)
67    web_contents = render_view_host->GetDelegate()->GetAsWebContents();
68
69  if (!web_contents) {
70    // We arrived on the UI thread, but the tab we're looking for is no longer
71    // here.
72    OnDispatchFailed();
73    return;
74  }
75
76  // Hand ourselves off to the SSLManager.
77  manager_ =
78      static_cast<NavigationControllerImpl*>(&web_contents->GetController())->
79          ssl_manager();
80  OnDispatched();
81}
82
83void SSLErrorHandler::CancelRequest() {
84  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
85
86  // We need to complete this task on the IO thread.
87  BrowserThread::PostTask(
88      BrowserThread::IO, FROM_HERE,
89      base::Bind(
90          &SSLErrorHandler::CompleteCancelRequest, this, net::ERR_ABORTED));
91}
92
93void SSLErrorHandler::DenyRequest() {
94  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
95
96  // We need to complete this task on the IO thread.
97  BrowserThread::PostTask(
98      BrowserThread::IO, FROM_HERE,
99      base::Bind(
100          &SSLErrorHandler::CompleteCancelRequest, this,
101          net::ERR_INSECURE_RESPONSE));
102}
103
104void SSLErrorHandler::ContinueRequest() {
105  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
106
107  // We need to complete this task on the IO thread.
108  BrowserThread::PostTask(
109      BrowserThread::IO, FROM_HERE,
110      base::Bind(&SSLErrorHandler::CompleteContinueRequest, this));
111}
112
113void SSLErrorHandler::TakeNoAction() {
114  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
115
116  // We need to complete this task on the IO thread.
117  BrowserThread::PostTask(
118      BrowserThread::IO, FROM_HERE,
119      base::Bind(&SSLErrorHandler::CompleteTakeNoAction, this));
120}
121
122void SSLErrorHandler::CompleteCancelRequest(int error) {
123  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
124
125  // It is important that we notify the net::URLRequest only once.  If we try
126  // to notify the request twice, it may no longer exist and |this| might have
127  // already have been deleted.
128  DCHECK(!request_has_been_notified_);
129  if (request_has_been_notified_)
130    return;
131
132  SSLCertErrorHandler* cert_error = AsSSLCertErrorHandler();
133  const SSLInfo* ssl_info = NULL;
134  if (cert_error)
135    ssl_info = &cert_error->ssl_info();
136  if (delegate_)
137    delegate_->CancelSSLRequest(request_id_, error, ssl_info);
138  request_has_been_notified_ = true;
139
140  // We're done with this object on the IO thread.
141  Release();
142}
143
144void SSLErrorHandler::CompleteContinueRequest() {
145  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
146
147  // It is important that we notify the net::URLRequest only once. If we try to
148  // notify the request twice, it may no longer exist and |this| might have
149  // already have been deleted.
150  DCHECK(!request_has_been_notified_);
151  if (request_has_been_notified_)
152    return;
153
154  if (delegate_)
155    delegate_->ContinueSSLRequest(request_id_);
156  request_has_been_notified_ = true;
157
158  // We're done with this object on the IO thread.
159  Release();
160}
161
162void SSLErrorHandler::CompleteTakeNoAction() {
163  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
164
165  // It is important that we notify the net::URLRequest only once. If we try to
166  // notify the request twice, it may no longer exist and |this| might have
167  // already have been deleted.
168  DCHECK(!request_has_been_notified_);
169  if (request_has_been_notified_)
170    return;
171
172  request_has_been_notified_ = true;
173
174  // We're done with this object on the IO thread.
175  Release();
176}
177
178}  // namespace content
179