blob: 8c2c37bf5865f6dc97915e9cfc2f87e410ace54c [file] [log] [blame]
// 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 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