diff options
Diffstat (limited to 'chrome/browser/ssl/ssl_error_handler.cc')
| -rw-r--r-- | chrome/browser/ssl/ssl_error_handler.cc | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc new file mode 100644 index 0000000..b5b435b --- /dev/null +++ b/chrome/browser/ssl/ssl_error_handler.cc @@ -0,0 +1,209 @@ +// Copyright (c) 2009 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 "chrome/browser/ssl/ssl_error_handler.h" + +#include "base/message_loop.h" +#include "chrome/browser/ssl/ssl_cert_error_handler.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" +#include "net/base/net_errors.h" +#include "net/url_request/url_request.h" + +SSLErrorHandler::SSLErrorHandler(ResourceDispatcherHost* rdh, + URLRequest* request, + ResourceType::Type resource_type, + const std::string& frame_origin, + const std::string& main_frame_origin, + MessageLoop* ui_loop) + : ui_loop_(ui_loop), + io_loop_(MessageLoop::current()), + manager_(NULL), + request_id_(0, 0), + resource_dispatcher_host_(rdh), + request_url_(request->url()), + resource_type_(resource_type), + frame_origin_(frame_origin), + main_frame_origin_(main_frame_origin), + request_has_been_notified_(false) { + DCHECK(MessageLoop::current() != ui_loop); + + ResourceDispatcherHost::ExtraRequestInfo* info = + ResourceDispatcherHost::ExtraInfoForRequest(request); + request_id_.process_id = info->process_id; + request_id_.request_id = info->request_id; + + if (!tab_util::GetTabContentsID(request, + &render_process_host_id_, + &tab_contents_id_)) + NOTREACHED(); + + // This makes sure we don't disappear on the IO thread until we've given an + // answer to the URLRequest. + // + // Release in CompleteCancelRequest, CompleteContinueRequest, + // CompleteStartRequest or CompleteTakeNoAction. + AddRef(); +} + +void SSLErrorHandler::Dispatch() { + DCHECK(MessageLoop::current() == ui_loop_); + + TabContents* tab_contents = + tab_util::GetTabContentsByID(render_process_host_id_, tab_contents_id_); + + if (!tab_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_ = tab_contents->controller().ssl_manager(); + OnDispatched(); +} + +TabContents* SSLErrorHandler::GetTabContents() { + return tab_util::GetTabContentsByID(render_process_host_id_, + tab_contents_id_); +} + +void SSLErrorHandler::CancelRequest() { + DCHECK(MessageLoop::current() == ui_loop_); + + // We need to complete this task on the IO thread. + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &SSLErrorHandler::CompleteCancelRequest, + net::ERR_ABORTED)); +} + +void SSLErrorHandler::DenyRequest() { + DCHECK(MessageLoop::current() == ui_loop_); + + // We need to complete this task on the IO thread. + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &SSLErrorHandler::CompleteCancelRequest, + net::ERR_INSECURE_RESPONSE)); +} + +void SSLErrorHandler::ContinueRequest() { + DCHECK(MessageLoop::current() == ui_loop_); + + // We need to complete this task on the IO thread. + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &SSLErrorHandler::CompleteContinueRequest)); +} + +void SSLErrorHandler::StartRequest(FilterPolicy::Type filter_policy) { + DCHECK(MessageLoop::current() == ui_loop_); + + // We need to complete this task on the IO thread. + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &SSLErrorHandler::CompleteStartRequest, filter_policy)); +} + +void SSLErrorHandler::TakeNoAction() { + DCHECK(MessageLoop::current() == ui_loop_); + + // We need to complete this task on the IO thread. + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &SSLErrorHandler::CompleteTakeNoAction)); +} + +void SSLErrorHandler::CompleteCancelRequest(int error) { + DCHECK(MessageLoop::current() == io_loop_); + + // It is important that we notify the 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_) { + URLRequest* request = resource_dispatcher_host_->GetURLRequest(request_id_); + if (request) { + // The request can be NULL if it was cancelled by the renderer (as the + // result of the user navigating to a new page from the location bar). + DLOG(INFO) << "CompleteCancelRequest() url: " << request->url().spec(); + SSLCertErrorHandler* cert_error = AsSSLCertErrorHandler(); + if (cert_error) + request->SimulateSSLError(error, cert_error->ssl_info()); + else + request->SimulateError(error); + } + request_has_been_notified_ = true; + + // We're done with this object on the IO thread. + Release(); + } +} + +void SSLErrorHandler::CompleteContinueRequest() { + DCHECK(MessageLoop::current() == io_loop_); + + // It is important that we notify the 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_) { + URLRequest* request = resource_dispatcher_host_->GetURLRequest(request_id_); + if (request) { + // The request can be NULL if it was cancelled by the renderer (as the + // result of the user navigating to a new page from the location bar). + DLOG(INFO) << "CompleteContinueRequest() url: " << request->url().spec(); + request->ContinueDespiteLastError(); + } + request_has_been_notified_ = true; + + // We're done with this object on the IO thread. + Release(); + } +} + +void SSLErrorHandler::CompleteStartRequest(FilterPolicy::Type filter_policy) { + DCHECK(MessageLoop::current() == io_loop_); + + // It is important that we notify the 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; + + URLRequest* request = resource_dispatcher_host_->GetURLRequest(request_id_); + if (request) { + // The request can be NULL if it was cancelled by the renderer (as the + // result of the user navigating to a new page from the location bar). + DLOG(INFO) << "CompleteStartRequest() url: " << request->url().spec(); + // The request should not have been started (SUCCESS is the initial state). + DCHECK(request->status().status() == URLRequestStatus::SUCCESS); + ResourceDispatcherHost::ExtraRequestInfo* info = + ResourceDispatcherHost::ExtraInfoForRequest(request); + info->filter_policy = filter_policy; + request->Start(); + } + request_has_been_notified_ = true; + + // We're done with this object on the IO thread. + Release(); +} + +void SSLErrorHandler::CompleteTakeNoAction() { + DCHECK(MessageLoop::current() == io_loop_); + + // It is important that we notify the 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_) { + request_has_been_notified_ = true; + + // We're done with this object on the IO thread. + Release(); + } +} + |
