diff options
author | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-15 04:08:24 +0000 |
---|---|---|
committer | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-15 04:08:24 +0000 |
commit | 5d063840bdb2c53dc013e2bad48d76cb43ac89a5 (patch) | |
tree | 9dcfc89734943ba273eee63ee2895740c7a3b3c5 /chrome | |
parent | fddf0d42dc3c82d8e8b7a780eb1483723d0915fc (diff) | |
download | chromium_src-5d063840bdb2c53dc013e2bad48d76cb43ac89a5.zip chromium_src-5d063840bdb2c53dc013e2bad48d76cb43ac89a5.tar.gz chromium_src-5d063840bdb2c53dc013e2bad48d76cb43ac89a5.tar.bz2 |
Finish refactoring to make SSLPolicy and friends unit testable. Next stop: tests!
TBR=jcampan
BUG=http://crbug.com/8782
Review URL: http://codereview.chromium.org/115389
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16145 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/browser.vcproj | 14 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_cert_error_handler.cc | 36 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_cert_error_handler.h | 19 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_error_handler.h | 3 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_manager.cc | 52 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_manager.h | 69 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_mixed_content_handler.cc | 29 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_mixed_content_handler.h | 12 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_policy.cc | 262 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_policy.h | 72 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_request_info.h | 10 | ||||
-rw-r--r-- | chrome/browser/tab_contents/navigation_controller.cc | 2 | ||||
-rw-r--r-- | chrome/chrome.gyp | 2 |
13 files changed, 294 insertions, 288 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 11b96c3..b712615 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -810,15 +810,15 @@ > </File> <File - RelativePath=".\task_manager_win.cc" + RelativePath=".\task_manager_resource_providers.cc" > </File> <File - RelativePath=".\task_manager_resource_providers.cc" + RelativePath=".\task_manager_resource_providers.h" > </File> <File - RelativePath=".\task_manager_resource_providers.h" + RelativePath=".\task_manager_win.cc" > </File> <File @@ -2526,6 +2526,10 @@ > </File> <File + RelativePath=".\ssl\ssl_cert_error_handler.cc" + > + </File> + <File RelativePath=".\ssl\ssl_cert_error_handler.h" > </File> @@ -2562,6 +2566,10 @@ > </File> <File + RelativePath=".\ssl\ssl_mixed_content_handler.cc" + > + </File> + <File RelativePath=".\ssl\ssl_mixed_content_handler.h" > </File> diff --git a/chrome/browser/ssl/ssl_cert_error_handler.cc b/chrome/browser/ssl/ssl_cert_error_handler.cc new file mode 100644 index 0000000..d050a64 --- /dev/null +++ b/chrome/browser/ssl/ssl_cert_error_handler.cc @@ -0,0 +1,36 @@ +// 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_cert_error_handler.h" + +#include "chrome/browser/ssl/ssl_manager.h" +#include "chrome/browser/ssl/ssl_policy.h" + +SSLCertErrorHandler::SSLCertErrorHandler( + ResourceDispatcherHost* rdh, + URLRequest* request, + ResourceType::Type resource_type, + const std::string& frame_origin, + const std::string& main_frame_origin, + int cert_error, + net::X509Certificate* cert, + MessageLoop* ui_loop) + : SSLErrorHandler(rdh, request, resource_type, frame_origin, + main_frame_origin, ui_loop), + cert_error_(cert_error) { + DCHECK(request == resource_dispatcher_host_->GetURLRequest(request_id_)); + + // We cannot use the request->ssl_info(), it's not been initialized yet, so + // we have to set the fields manually. + ssl_info_.cert = cert; + ssl_info_.SetCertError(cert_error); +} + +void SSLCertErrorHandler::OnDispatchFailed() { + CancelRequest(); +} + +void SSLCertErrorHandler::OnDispatched() { + manager_->policy()->OnCertError(this); +} diff --git a/chrome/browser/ssl/ssl_cert_error_handler.h b/chrome/browser/ssl/ssl_cert_error_handler.h index 2eed59a..c58b2cf 100644 --- a/chrome/browser/ssl/ssl_cert_error_handler.h +++ b/chrome/browser/ssl/ssl_cert_error_handler.h @@ -5,8 +5,9 @@ #ifndef CHROME_BROWSER_SSL_SSL_CERT_ERROR_HANDLER_H_ #define CHROME_BROWSER_SSL_SSL_CERT_ERROR_HANDLER_H_ +#include <string> + #include "chrome/browser/ssl/ssl_error_handler.h" -#include "chrome/browser/ssl/ssl_manager.h" #include "net/base/ssl_info.h" #include "net/base/x509_certificate.h" @@ -23,17 +24,7 @@ class SSLCertErrorHandler : public SSLErrorHandler { const std::string& main_frame_origin, int cert_error, net::X509Certificate* cert, - MessageLoop* ui_loop) - : SSLErrorHandler(rdh, request, resource_type, frame_origin, - main_frame_origin, ui_loop), - cert_error_(cert_error) { - DCHECK(request == resource_dispatcher_host_->GetURLRequest(request_id_)); - - // We cannot use the request->ssl_info(), it's not been initialized yet, so - // we have to set the fields manually. - ssl_info_.cert = cert; - ssl_info_.SetCertError(cert_error); - } + MessageLoop* ui_loop); virtual SSLCertErrorHandler* AsSSLCertErrorHandler() { return this; } @@ -43,8 +34,8 @@ class SSLCertErrorHandler : public SSLErrorHandler { protected: // SSLErrorHandler methods - virtual void OnDispatchFailed() { CancelRequest(); } - virtual void OnDispatched() { manager_->OnCertError(this); } + virtual void OnDispatchFailed(); + virtual void OnDispatched(); private: // These read-only members may be accessed on any thread. diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h index c891f79..06b524a 100644 --- a/chrome/browser/ssl/ssl_error_handler.h +++ b/chrome/browser/ssl/ssl_error_handler.h @@ -58,9 +58,6 @@ class SSLErrorHandler : public base::RefCountedThreadSafe<SSLErrorHandler> { // Available on either thread. const std::string& main_frame_origin() const { return main_frame_origin_; } - // Call on the UI thread. - SSLPolicyBackend* backend() const { return manager_->backend(); } - // Returns the TabContents this object is associated with. Should be // called from the UI thread. TabContents* GetTabContents(); diff --git a/chrome/browser/ssl/ssl_manager.cc b/chrome/browser/ssl/ssl_manager.cc index a8733af..573597c 100644 --- a/chrome/browser/ssl/ssl_manager.cc +++ b/chrome/browser/ssl/ssl_manager.cc @@ -5,43 +5,21 @@ #include "chrome/browser/ssl/ssl_manager.h" #include "app/l10n_util.h" -#include "app/resource_bundle.h" #include "base/message_loop.h" -#include "base/string_util.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/load_from_memory_cache_details.h" -#include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/resource_request_details.h" #include "chrome/browser/ssl/ssl_cert_error_handler.h" -#include "chrome/browser/ssl/ssl_error_info.h" -#include "chrome/browser/ssl/ssl_error_handler.h" -#include "chrome/browser/ssl/ssl_host_state.h" #include "chrome/browser/ssl/ssl_mixed_content_handler.h" #include "chrome/browser/ssl/ssl_policy.h" #include "chrome/browser/ssl/ssl_request_info.h" -#include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/provisional_load_details.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tab_contents/tab_util.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" #include "grit/generated_resources.h" -#include "grit/theme_resources.h" #include "net/base/cert_status_flags.h" -#include "net/base/net_errors.h" -#include "net/url_request/url_request.h" -#include "webkit/glue/resource_type.h" - -#if defined(OS_WIN) -// TODO(port): Port these files. -#include "chrome/browser/load_notification_details.h" -#include "views/controls/link.h" -#else -#include "chrome/common/temp_scaffolding_stubs.h" -#endif // static void SSLManager::RegisterUserPrefs(PrefService* prefs) { @@ -49,16 +27,12 @@ void SSLManager::RegisterUserPrefs(PrefService* prefs) { FilterPolicy::DONT_FILTER); } -SSLManager::SSLManager(NavigationController* controller, Delegate* delegate) - : delegate_(delegate), - backend_(controller), +SSLManager::SSLManager(NavigationController* controller) + : backend_(controller), + policy_(new SSLPolicy(&backend_)), controller_(controller) { DCHECK(controller_); - // If do delegate is supplied, use the default policy. - if (!delegate_) - delegate_ = SSLPolicy::GetDefaultPolicy(); - // Subscribe to various notifications. registrar_.Add(this, NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR, Source<NavigationController>(controller_)); @@ -141,14 +115,6 @@ bool SSLManager::ShouldStartRequest(ResourceDispatcherHost* rdh, return false; } -void SSLManager::OnCertError(SSLCertErrorHandler* handler) { - delegate()->OnCertError(handler); -} - -void SSLManager::OnMixedContent(SSLMixedContentHandler* handler) { - delegate()->OnMixedContent(handler); -} - void SSLManager::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { @@ -192,7 +158,7 @@ void SSLManager::UpdateEntry(NavigationEntry* entry) { NavigationEntry::SSLStatus original_ssl_status = entry->ssl(); // Copy! - delegate()->UpdateEntry(backend(), entry); + policy()->UpdateEntry(entry); if (!entry->ssl().Equals(original_ssl_status)) DispatchSSLVisibleStateChanged(); @@ -207,7 +173,6 @@ void SSLManager::DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details) { // This resource must have been loaded with FilterPolicy::DONT_FILTER because // filtered resouces aren't cachable. scoped_refptr<SSLRequestInfo> info = new SSLRequestInfo( - backend(), details->url(), ResourceType::SUB_RESOURCE, details->frame_origin(), @@ -218,7 +183,7 @@ void SSLManager::DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details) { details->ssl_cert_status()); // Simulate loading this resource through the usual path. - delegate()->OnRequestStarted(info.get()); + policy()->OnRequestStarted(info.get()); } void SSLManager::DidCommitProvisionalLoad( @@ -271,7 +236,6 @@ void SSLManager::DidStartResourceResponse(ResourceRequestDetails* details) { DCHECK(details); scoped_refptr<SSLRequestInfo> info = new SSLRequestInfo( - backend(), details->url(), details->resource_type(), details->frame_origin(), @@ -281,10 +245,10 @@ void SSLManager::DidStartResourceResponse(ResourceRequestDetails* details) { details->ssl_cert_id(), details->ssl_cert_status()); - // Notify our delegate that we started a resource request. Ideally, the - // delegate should have the ability to cancel the request, but we can't do + // Notify our policy that we started a resource request. Ideally, the + // policy should have the ability to cancel the request, but we can't do // that yet. - delegate()->OnRequestStarted(info.get()); + policy()->OnRequestStarted(info.get()); } void SSLManager::DidReceiveResourceRedirect(ResourceRedirectDetails* details) { diff --git a/chrome/browser/ssl/ssl_manager.h b/chrome/browser/ssl/ssl_manager.h index 4021f53..338037f 100644 --- a/chrome/browser/ssl/ssl_manager.h +++ b/chrome/browser/ssl/ssl_manager.h @@ -38,6 +38,7 @@ class SSLErrorHandler; class SSLErrorInfo; class SSLHostState; class SSLMixedContentHandler; +class SSLPolicy; class SSLRequestInfo; class Task; class URLRequest; @@ -53,47 +54,20 @@ class TabContents; class SSLManager : public NotificationObserver { public: - // The SSLManager will ask its delegate to decide how to handle events - // relevant to SSL. Delegates are expected to be stateless and intended to be - // easily implementable. - // - // Delegates should interact with the rest of the browser only through their - // parameters and through the delegate API of the SSLManager. - // - // If a delegate needs to do something tricky, consider having the SSLManager - // do it instead. - class Delegate { - public: - // An error occurred with the certificate in an SSL connection. - virtual void OnCertError(SSLCertErrorHandler* handler) = 0; - - // A request for a mixed-content resource was made. Note that the resource - // request was not started yet and the delegate is responsible for starting - // it. - virtual void OnMixedContent(SSLMixedContentHandler* handler) = 0; - - // We have started a resource request with the given info. - virtual void OnRequestStarted(SSLRequestInfo* info) = 0; - - // Update the SSL information in |entry| to match the current state. - virtual void UpdateEntry(SSLPolicyBackend* backend, NavigationEntry* entry) = 0; - }; - - static void RegisterUserPrefs(PrefService* prefs); - // Construct an SSLManager for the specified tab. // If |delegate| is NULL, SSLPolicy::GetDefaultPolicy() is used. - SSLManager(NavigationController* controller, Delegate* delegate); - + explicit SSLManager(NavigationController* controller); ~SSLManager(); - // The delegate of the SSLManager. This value may be changed at any time, - // but it is not permissible for it to be NULL. - Delegate* delegate() const { return delegate_; } - void set_delegate(Delegate* delegate) { delegate_ = delegate; } - + SSLPolicy* policy() { return policy_.get(); } SSLPolicyBackend* backend() { return &backend_; } + // The navigation controller associated with this SSLManager. The + // NavigationController is guaranteed to outlive the SSLManager. + NavigationController* controller() { return controller_; } + + static void RegisterUserPrefs(PrefService* prefs); + // Entry point for SSLCertificateErrors. This function begins the process // of resolving a certificate error during an SSL connection. SSLManager // will adjust the security UI and either call |Cancel| or @@ -118,20 +92,6 @@ class SSLManager : public NotificationObserver { URLRequest* request, MessageLoop* ui_loop); - // Called by SSLCertErrorHandler::OnDispatch to kick off processing of the - // cert error by the SSL manager. The error originated from the - // ResourceDispatcherHost. - // - // Called on the UI thread. - void OnCertError(SSLCertErrorHandler* handler); - - // Called by SSLMixedContentHandler::OnDispatch to kick off processing of the - // mixed-content resource request. The info originated from the - // ResourceDispatcherHost. - // - // Called on the UI thread. - void OnMixedContent(SSLMixedContentHandler* handler); - // Entry point for navigation. This function begins the process of updating // the security UI when the main frame navigates to a new URL. // @@ -148,10 +108,6 @@ class SSLManager : public NotificationObserver { // Called to determine if there were any processed SSL errors from request. bool ProcessedSSLErrorFromRequest() const; - // The navigation controller associated with this SSLManager. The - // NavigationController is guaranteed to outlive the SSLManager. - NavigationController* controller() { return controller_; } - // Convenience methods for serializing/deserializing the security info. static std::string SerializeSecurityInfo(int cert_id, int cert_status, @@ -209,13 +165,12 @@ class SSLManager : public NotificationObserver { // Update the NavigationEntry with our current state. void UpdateEntry(NavigationEntry* entry); - // Our delegate. The delegate is responsible for making policy decisions. - // Must not be NULL. - Delegate* delegate_; - // The backend for the SSLPolicy to actuate its decisions. SSLPolicyBackend backend_; + // The SSLPolicy instance for this manager. + scoped_ptr<SSLPolicy> policy_; + // The NavigationController that owns this SSLManager. We are responsible // for the security UI of this tab. NavigationController* controller_; diff --git a/chrome/browser/ssl/ssl_mixed_content_handler.cc b/chrome/browser/ssl/ssl_mixed_content_handler.cc new file mode 100644 index 0000000..8faa259 --- /dev/null +++ b/chrome/browser/ssl/ssl_mixed_content_handler.cc @@ -0,0 +1,29 @@ +// 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_mixed_content_handler.h" + +#include "chrome/browser/ssl/ssl_manager.h" +#include "chrome/browser/ssl/ssl_policy.h" + +SSLMixedContentHandler::SSLMixedContentHandler( + ResourceDispatcherHost* rdh, + URLRequest* request, + ResourceType::Type resource_type, + const std::string& frame_origin, + const std::string& main_frame_origin, + int pid, + MessageLoop* ui_loop) + : SSLErrorHandler(rdh, request, resource_type, frame_origin, + main_frame_origin, ui_loop), + pid_(pid) { +} + +void SSLMixedContentHandler::OnDispatchFailed() { + TakeNoAction(); +} + +void SSLMixedContentHandler::OnDispatched() { + manager_->policy()->OnMixedContent(this); +} diff --git a/chrome/browser/ssl/ssl_mixed_content_handler.h b/chrome/browser/ssl/ssl_mixed_content_handler.h index 19ba73d..0e47bb9 100644 --- a/chrome/browser/ssl/ssl_mixed_content_handler.h +++ b/chrome/browser/ssl/ssl_mixed_content_handler.h @@ -5,8 +5,9 @@ #ifndef CHROME_BROWSER_SSL_SSL_MIXED_CONTENT_HANDLER_H_ #define CHROME_BROWSER_SSL_SSL_MIXED_CONTENT_HANDLER_H_ +#include <string> + #include "chrome/browser/ssl/ssl_error_handler.h" -#include "chrome/browser/ssl/ssl_manager.h" // The SSLMixedContentHandler class is used to query what to do with // mixed content, from the IO thread to the UI thread. @@ -19,16 +20,13 @@ class SSLMixedContentHandler : public SSLErrorHandler { const std::string& frame_origin, const std::string& main_frame_origin, int pid, - MessageLoop* ui_loop) - : SSLErrorHandler(rdh, request, resource_type, frame_origin, - main_frame_origin, ui_loop), - pid_(pid) {} + MessageLoop* ui_loop); int pid() const { return pid_; } protected: - virtual void OnDispatchFailed() { TakeNoAction(); } - virtual void OnDispatched() { manager_->OnMixedContent(this); } + virtual void OnDispatchFailed(); + virtual void OnDispatched(); private: int pid_; diff --git a/chrome/browser/ssl/ssl_policy.cc b/chrome/browser/ssl/ssl_policy.cc index 6c9ac63..7004da7 100644 --- a/chrome/browser/ssl/ssl_policy.cc +++ b/chrome/browser/ssl/ssl_policy.cc @@ -32,152 +32,45 @@ using WebKit::WebConsoleMessage; -// Wrap all these helper classes in an anonymous namespace. -namespace { - -static void MarkOriginAsBroken(SSLPolicyBackend* backend, - const std::string& origin, - int pid) { - GURL parsed_origin(origin); - if (!parsed_origin.SchemeIsSecure()) - return; - - backend->MarkHostAsBroken(parsed_origin.host(), pid); -} - -static void AllowMixedContentForOrigin(SSLPolicyBackend* backend, - const std::string& origin) { - GURL parsed_origin(origin); - if (!parsed_origin.SchemeIsSecure()) - return; - - backend->AllowMixedContentForHost(parsed_origin.host()); -} - -static void UpdateStateForMixedContent(SSLRequestInfo* info) { - if (info->resource_type() != ResourceType::MAIN_FRAME || - info->resource_type() != ResourceType::SUB_FRAME) { - // The frame's origin now contains mixed content and therefore is broken. - MarkOriginAsBroken(info->backend(), info->frame_origin(), info->pid()); - } - - if (info->resource_type() != ResourceType::MAIN_FRAME) { - // The main frame now contains a frame with mixed content. Therefore, we - // mark the main frame's origin as broken too. - MarkOriginAsBroken(info->backend(), info->main_frame_origin(), info->pid()); - } -} - -static void UpdateStateForUnsafeContent(SSLRequestInfo* info) { - // This request as a broken cert, which means its host is broken. - info->backend()->MarkHostAsBroken(info->url().host(), info->pid()); - - UpdateStateForMixedContent(info); -} - -class ShowMixedContentTask : public Task { +class SSLPolicy::ShowMixedContentTask : public Task { public: - ShowMixedContentTask(SSLMixedContentHandler* handler); + ShowMixedContentTask(SSLPolicy* policy, SSLMixedContentHandler* handler); virtual ~ShowMixedContentTask(); virtual void Run(); private: + SSLPolicy* policy_; scoped_refptr<SSLMixedContentHandler> handler_; DISALLOW_COPY_AND_ASSIGN(ShowMixedContentTask); }; -ShowMixedContentTask::ShowMixedContentTask(SSLMixedContentHandler* handler) - : handler_(handler) { -} - -ShowMixedContentTask::~ShowMixedContentTask() { -} - -void ShowMixedContentTask::Run() { - AllowMixedContentForOrigin(handler_->backend(), handler_->frame_origin()); - AllowMixedContentForOrigin(handler_->backend(), - handler_->main_frame_origin()); - handler_->backend()->Reload(); -} - -static void ShowErrorPage(SSLPolicy* policy, SSLCertErrorHandler* handler) { - SSLErrorInfo error_info = policy->GetSSLErrorInfo(handler); - - // Let's build the html error page. - DictionaryValue strings; - strings.SetString(L"title", l10n_util::GetString(IDS_SSL_ERROR_PAGE_TITLE)); - strings.SetString(L"headLine", error_info.title()); - strings.SetString(L"description", error_info.details()); - strings.SetString(L"moreInfoTitle", - l10n_util::GetString(IDS_CERT_ERROR_EXTRA_INFO_TITLE)); - SSLBlockingPage::SetExtraInfo(&strings, error_info.extra_information()); - - strings.SetString(L"back", l10n_util::GetString(IDS_SSL_ERROR_PAGE_BACK)); - - strings.SetString(L"textdirection", - (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ? - L"rtl" : L"ltr"); - - static const StringPiece html( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_SSL_ERROR_HTML)); - - std::string html_text(jstemplate_builder::GetTemplateHtml(html, &strings, - "template_root")); - - TabContents* tab = handler->GetTabContents(); - int cert_id = CertStore::GetSharedInstance()->StoreCert( - handler->ssl_info().cert, tab->render_view_host()->process()->pid()); - std::string security_info = - SSLManager::SerializeSecurityInfo(cert_id, - handler->ssl_info().cert_status, - handler->ssl_info().security_bits); - tab->render_view_host()->LoadAlternateHTMLString(html_text, - true, - handler->request_url(), - security_info); - tab->controller().GetActiveEntry()->set_page_type( - NavigationEntry::ERROR_PAGE); +SSLPolicy::ShowMixedContentTask::ShowMixedContentTask(SSLPolicy* policy, + SSLMixedContentHandler* handler) + : policy_(policy), + handler_(handler) { } -static void ShowBlockingPage(SSLPolicy* policy, SSLCertErrorHandler* handler) { - SSLBlockingPage* blocking_page = new SSLBlockingPage(handler, policy); - blocking_page->Show(); +SSLPolicy::ShowMixedContentTask::~ShowMixedContentTask() { } -static void InitializeEntryIfNeeded(NavigationEntry* entry) { - if (entry->ssl().security_style() != SECURITY_STYLE_UNKNOWN) - return; - - entry->ssl().set_security_style(entry->url().SchemeIsSecure() ? - SECURITY_STYLE_AUTHENTICATED : SECURITY_STYLE_UNAUTHENTICATED); +void SSLPolicy::ShowMixedContentTask::Run() { + policy_->AllowMixedContentForOrigin(handler_->frame_origin()); + policy_->AllowMixedContentForOrigin(handler_->main_frame_origin()); + policy_->backend()->Reload(); } -static void AddMixedContentWarningToConsole(SSLMixedContentHandler* handler) { - const std::wstring& text = l10n_util::GetStringF( - IDS_MIXED_CONTENT_LOG_MESSAGE, - UTF8ToWide(handler->frame_origin()), - UTF8ToWide(handler->request_url().spec())); - handler->backend()->AddMessageToConsole( - WideToUTF16Hack(text), WebConsoleMessage::LevelWarning); -} - -} // namespace - -SSLPolicy::SSLPolicy() { -} - -SSLPolicy* SSLPolicy::GetDefaultPolicy() { - return Singleton<SSLPolicy>::get(); +SSLPolicy::SSLPolicy(SSLPolicyBackend* backend) + : backend_(backend) { + DCHECK(backend_); } void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) { // First we check if we know the policy for this error. net::X509Certificate::Policy::Judgment judgment = - handler->backend()->QueryPolicy(handler->ssl_info().cert, - handler->request_url().host()); + backend_->QueryPolicy(handler->ssl_info().cert, + handler->request_url().host()); if (judgment == net::X509Certificate::Policy::ALLOWED) { handler->ContinueRequest(); @@ -201,7 +94,7 @@ void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) { case net::ERR_CERT_UNABLE_TO_CHECK_REVOCATION: // We ignore this error and display an infobar. handler->ContinueRequest(); - handler->backend()->ShowMessage(l10n_util::GetString( + backend_->ShowMessage(l10n_util::GetString( IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_INFO_BAR)); break; case net::ERR_CERT_CONTAINS_ERRORS: @@ -224,15 +117,15 @@ void SSLPolicy::OnMixedContent(SSLMixedContentHandler* handler) { // If the user has added an exception, doctor the |filter_policy|. std::string host = GURL(handler->main_frame_origin()).host(); - if (handler->backend()->DidAllowMixedContentForHost(host) || - handler->backend()->DidMarkHostAsBroken(host, handler->pid())) + if (backend_->DidAllowMixedContentForHost(host) || + backend_->DidMarkHostAsBroken(host, handler->pid())) filter_policy = FilterPolicy::DONT_FILTER; if (filter_policy != FilterPolicy::DONT_FILTER) { - handler->backend()->ShowMessageWithLink( + backend_->ShowMessageWithLink( l10n_util::GetString(IDS_SSL_INFO_BAR_FILTERED_CONTENT), l10n_util::GetString(IDS_SSL_INFO_BAR_SHOW_CONTENT), - new ShowMixedContentTask(handler)); + new ShowMixedContentTask(this, handler)); } handler->StartRequest(filter_policy); @@ -250,7 +143,7 @@ void SSLPolicy::OnRequestStarted(SSLRequestInfo* info) { UpdateStateForMixedContent(info); } -void SSLPolicy::UpdateEntry(SSLPolicyBackend* backend, NavigationEntry* entry) { +void SSLPolicy::UpdateEntry(NavigationEntry* entry) { DCHECK(entry); InitializeEntryIfNeeded(entry); @@ -271,7 +164,7 @@ void SSLPolicy::UpdateEntry(SSLPolicyBackend* backend, NavigationEntry* entry) { return; } - if (backend->DidMarkHostAsBroken(entry->url().host(), + if (backend_->DidMarkHostAsBroken(entry->url().host(), entry->site_instance()->GetProcess()->pid())) entry->ssl().set_has_mixed_content(); } @@ -321,8 +214,8 @@ void SSLPolicy::OnDenyCertificate(SSLCertErrorHandler* handler) { // While DenyCertForHost() executes synchronously on this thread, // CancelRequest() gets posted to a different thread. Calling // DenyCertForHost() first ensures deterministic ordering. - handler->backend()->DenyCertForHost(handler->ssl_info().cert, - handler->request_url().host()); + backend_->DenyCertForHost(handler->ssl_info().cert, + handler->request_url().host()); handler->CancelRequest(); } @@ -337,8 +230,8 @@ void SSLPolicy::OnAllowCertificate(SSLCertErrorHandler* handler) { // While AllowCertForHost() executes synchronously on this thread, // ContinueRequest() gets posted to a different thread. Calling // AllowCertForHost() first ensures deterministic ordering. - handler->backend()->AllowCertForHost(handler->ssl_info().cert, - handler->request_url().host()); + backend_->AllowCertForHost(handler->ssl_info().cert, + handler->request_url().host()); handler->ContinueRequest(); } @@ -355,7 +248,8 @@ void SSLPolicy::OnOverridableCertError(SSLCertErrorHandler* handler) { return; } // We need to ask the user to approve this certificate. - ShowBlockingPage(this, handler); + SSLBlockingPage* blocking_page = new SSLBlockingPage(handler, this); + blocking_page->Show(); } void SSLPolicy::OnFatalCertError(SSLCertErrorHandler* handler) { @@ -364,6 +258,100 @@ void SSLPolicy::OnFatalCertError(SSLCertErrorHandler* handler) { return; } handler->CancelRequest(); - ShowErrorPage(this, handler); + ShowErrorPage(handler); // No need to degrade our security indicators because we didn't continue. } + +void SSLPolicy::ShowErrorPage(SSLCertErrorHandler* handler) { + SSLErrorInfo error_info = GetSSLErrorInfo(handler); + + // Let's build the html error page. + DictionaryValue strings; + strings.SetString(L"title", l10n_util::GetString(IDS_SSL_ERROR_PAGE_TITLE)); + strings.SetString(L"headLine", error_info.title()); + strings.SetString(L"description", error_info.details()); + strings.SetString(L"moreInfoTitle", + l10n_util::GetString(IDS_CERT_ERROR_EXTRA_INFO_TITLE)); + SSLBlockingPage::SetExtraInfo(&strings, error_info.extra_information()); + + strings.SetString(L"back", l10n_util::GetString(IDS_SSL_ERROR_PAGE_BACK)); + + strings.SetString(L"textdirection", + (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) ? + L"rtl" : L"ltr"); + + static const StringPiece html( + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_SSL_ERROR_HTML)); + + std::string html_text(jstemplate_builder::GetTemplateHtml(html, &strings, + "template_root")); + + TabContents* tab = handler->GetTabContents(); + int cert_id = CertStore::GetSharedInstance()->StoreCert( + handler->ssl_info().cert, tab->render_view_host()->process()->pid()); + std::string security_info = + SSLManager::SerializeSecurityInfo(cert_id, + handler->ssl_info().cert_status, + handler->ssl_info().security_bits); + tab->render_view_host()->LoadAlternateHTMLString(html_text, + true, + handler->request_url(), + security_info); + tab->controller().GetActiveEntry()->set_page_type( + NavigationEntry::ERROR_PAGE); +} + +void SSLPolicy::AddMixedContentWarningToConsole( + SSLMixedContentHandler* handler) { + const std::wstring& text = l10n_util::GetStringF( + IDS_MIXED_CONTENT_LOG_MESSAGE, + UTF8ToWide(handler->frame_origin()), + UTF8ToWide(handler->request_url().spec())); + backend_->AddMessageToConsole( + WideToUTF16Hack(text), WebConsoleMessage::LevelWarning); +} + +void SSLPolicy::InitializeEntryIfNeeded(NavigationEntry* entry) { + if (entry->ssl().security_style() != SECURITY_STYLE_UNKNOWN) + return; + + entry->ssl().set_security_style(entry->url().SchemeIsSecure() ? + SECURITY_STYLE_AUTHENTICATED : SECURITY_STYLE_UNAUTHENTICATED); +} + +void SSLPolicy::MarkOriginAsBroken(const std::string& origin, int pid) { + GURL parsed_origin(origin); + if (!parsed_origin.SchemeIsSecure()) + return; + + backend_->MarkHostAsBroken(parsed_origin.host(), pid); +} + +void SSLPolicy::AllowMixedContentForOrigin(const std::string& origin) { + GURL parsed_origin(origin); + if (!parsed_origin.SchemeIsSecure()) + return; + + backend_->AllowMixedContentForHost(parsed_origin.host()); +} + +void SSLPolicy::UpdateStateForMixedContent(SSLRequestInfo* info) { + if (info->resource_type() != ResourceType::MAIN_FRAME || + info->resource_type() != ResourceType::SUB_FRAME) { + // The frame's origin now contains mixed content and therefore is broken. + MarkOriginAsBroken(info->frame_origin(), info->pid()); + } + + if (info->resource_type() != ResourceType::MAIN_FRAME) { + // The main frame now contains a frame with mixed content. Therefore, we + // mark the main frame's origin as broken too. + MarkOriginAsBroken(info->main_frame_origin(), info->pid()); + } +} + +void SSLPolicy::UpdateStateForUnsafeContent(SSLRequestInfo* info) { + // This request as a broken cert, which means its host is broken. + backend_->MarkHostAsBroken(info->url().host(), info->pid()); + UpdateStateForMixedContent(info); +} diff --git a/chrome/browser/ssl/ssl_policy.h b/chrome/browser/ssl/ssl_policy.h index 117120d..48a5f0d 100644 --- a/chrome/browser/ssl/ssl_policy.h +++ b/chrome/browser/ssl/ssl_policy.h @@ -5,9 +5,17 @@ #ifndef CHROME_BROWSER_SSL_SSL_POLICY_H_ #define CHROME_BROWSER_SSL_SSL_POLICY_H_ -#include "base/singleton.h" +#include <string> + #include "chrome/browser/ssl/ssl_blocking_page.h" -#include "chrome/browser/ssl/ssl_manager.h" +#include "chrome/common/filter_policy.h" +#include "webkit/glue/resource_type.h" + +class NavigationEntry; +class SSLCertErrorHandler; +class SSLMixedContentHandler; +class SSLPolicyBackend; +class SSLRequestInfo; // SSLPolicy // @@ -15,17 +23,23 @@ // SSL trust indicators. It relies on the SSLPolicyBackend to actually enact // the decisions it reaches. // -class SSLPolicy : public SSLManager::Delegate, - public SSLBlockingPage::Delegate { +class SSLPolicy : public SSLBlockingPage::Delegate { public: - // Factory method to get the default policy. - static SSLPolicy* GetDefaultPolicy(); + explicit SSLPolicy(SSLPolicyBackend* backend); + + // An error occurred with the certificate in an SSL connection. + void OnCertError(SSLCertErrorHandler* handler); + + // A request for a mixed-content resource was made. Note that the resource + // request was not started yet and the delegate is responsible for starting + // it. + void OnMixedContent(SSLMixedContentHandler* handler); - // SSLManager::Delegate methods. - virtual void OnCertError(SSLCertErrorHandler* handler); - virtual void OnMixedContent(SSLMixedContentHandler* handler); - virtual void OnRequestStarted(SSLRequestInfo* info); - virtual void UpdateEntry(SSLPolicyBackend* backend, NavigationEntry* entry); + // We have started a resource request with the given info. + void OnRequestStarted(SSLRequestInfo* info); + + // Update the SSL information in |entry| to match the current state. + void UpdateEntry(NavigationEntry* entry); // This method is static because it is called from both the UI and the IO // threads. @@ -34,15 +48,15 @@ class SSLPolicy : public SSLManager::Delegate, FilterPolicy::Type filter_policy, const std::string& frame_origin); + SSLPolicyBackend* backend() const { return backend_; } + // SSLBlockingPage::Delegate methods. virtual SSLErrorInfo GetSSLErrorInfo(SSLCertErrorHandler* handler); virtual void OnDenyCertificate(SSLCertErrorHandler* handler); virtual void OnAllowCertificate(SSLCertErrorHandler* handler); private: - // Construct via |GetDefaultPolicy|. - SSLPolicy(); - friend struct DefaultSingletonTraits<SSLPolicy>; + class ShowMixedContentTask; // Helper method for derived classes handling certificate errors that can be // overridden by the user. @@ -53,6 +67,36 @@ class SSLPolicy : public SSLManager::Delegate, // Cancel the request and show an error page. void OnFatalCertError(SSLCertErrorHandler* handler); + // Show an error page for this certificate error. This error page does not + // give the user the opportunity to ingore the error. + void ShowErrorPage(SSLCertErrorHandler* handler); + + // Add a warning about mixed content to the JavaScript console. This warning + // helps web developers track down and eliminate mixed content on their site. + void AddMixedContentWarningToConsole(SSLMixedContentHandler* handler); + + // If the security style of |entry| has not been initialized, then initialize + // it with the default style for its URL. + void InitializeEntryIfNeeded(NavigationEntry* entry); + + // Mark |origin| as containing insecure content in the process with ID |pid|. + void MarkOriginAsBroken(const std::string& origin, int pid); + + // Allow |origin| to include mixed content. This stops us from showing an + // infobar warning after the user as approved mixed content. + void AllowMixedContentForOrigin(const std::string& origin); + + // Called after we've decided that |info| represents a request for mixed + // content. Updates our internal state to reflect that we've loaded |info|. + void UpdateStateForMixedContent(SSLRequestInfo* info); + + // Called after we've decided that |info| represents a request for unsafe + // content. Updates our internal state to reflect that we've loaded |info|. + void UpdateStateForUnsafeContent(SSLRequestInfo* info); + + // The backend we use to enact our decisions. + SSLPolicyBackend* backend_; + DISALLOW_COPY_AND_ASSIGN(SSLPolicy); }; diff --git a/chrome/browser/ssl/ssl_request_info.h b/chrome/browser/ssl/ssl_request_info.h index 9128e97..fc8e417 100644 --- a/chrome/browser/ssl/ssl_request_info.h +++ b/chrome/browser/ssl/ssl_request_info.h @@ -11,15 +11,12 @@ #include "googleurl/src/gurl.h" #include "webkit/glue/resource_type.h" -class SSLPolicyBackend; - // SSLRequestInfo wraps up the information SSLPolicy needs about a request in // order to update our security IU. SSLRequestInfo is RefCounted in case we // need to deal with the request asynchronously. class SSLRequestInfo : public base::RefCounted<SSLRequestInfo> { public: - SSLRequestInfo(SSLPolicyBackend* backend, - const GURL& url, + SSLRequestInfo(const GURL& url, ResourceType::Type resource_type, const std::string& frame_origin, const std::string& main_frame_origin, @@ -27,8 +24,7 @@ class SSLRequestInfo : public base::RefCounted<SSLRequestInfo> { int pid, int ssl_cert_id, int ssl_cert_status) - : backend_(backend), - url_(url), + : url_(url), resource_type_(resource_type), frame_origin_(frame_origin), main_frame_origin_(main_frame_origin), @@ -38,7 +34,6 @@ class SSLRequestInfo : public base::RefCounted<SSLRequestInfo> { ssl_cert_status_(ssl_cert_status) { } - SSLPolicyBackend* backend() const { return backend_; } const GURL& url() const { return url_; } ResourceType::Type resource_type() const { return resource_type_; } const std::string& frame_origin() const { return frame_origin_; } @@ -49,7 +44,6 @@ class SSLRequestInfo : public base::RefCounted<SSLRequestInfo> { int ssl_cert_status() const { return ssl_cert_status_; } private: - SSLPolicyBackend* backend_; GURL url_; ResourceType::Type resource_type_; std::string frame_origin_; diff --git a/chrome/browser/tab_contents/navigation_controller.cc b/chrome/browser/tab_contents/navigation_controller.cc index a097455..a21088f 100644 --- a/chrome/browser/tab_contents/navigation_controller.cc +++ b/chrome/browser/tab_contents/navigation_controller.cc @@ -117,7 +117,7 @@ NavigationController::NavigationController(TabContents* contents, transient_entry_index_(-1), tab_contents_(contents), max_restored_page_id_(-1), - ALLOW_THIS_IN_INITIALIZER_LIST(ssl_manager_(this, NULL)), + ALLOW_THIS_IN_INITIALIZER_LIST(ssl_manager_(this)), needs_reload_(false), load_pending_entry_when_active_(false) { DCHECK(profile_); diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 2e7defb..ef608e1 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1301,6 +1301,7 @@ 'browser/spellchecker.h', 'browser/ssl/ssl_blocking_page.cc', 'browser/ssl/ssl_blocking_page.h', + 'browser/ssl/ssl_cert_error_handler.cc', 'browser/ssl/ssl_cert_error_handler.h', 'browser/ssl/ssl_error_handler.cc', 'browser/ssl/ssl_error_handler.h', @@ -1310,6 +1311,7 @@ 'browser/ssl/ssl_host_state.h', 'browser/ssl/ssl_manager.cc', 'browser/ssl/ssl_manager.h', + 'browser/ssl/ssl_mixed_content_handler.cc', 'browser/ssl/ssl_mixed_content_handler.h', 'browser/ssl/ssl_policy.cc', 'browser/ssl/ssl_policy.h', |