diff options
author | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-14 08:47:30 +0000 |
---|---|---|
committer | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-14 08:47:30 +0000 |
commit | 5edce1ef5502e3dc20f030e108978da0c360fb65 (patch) | |
tree | 831153859e0fcbcff99901f2b3b38f68126299bf /chrome | |
parent | 5dc0cc7bf9cb2f5e6b050933d1ebe7852b10baa0 (diff) | |
download | chromium_src-5edce1ef5502e3dc20f030e108978da0c360fb65.zip chromium_src-5edce1ef5502e3dc20f030e108978da0c360fb65.tar.gz chromium_src-5edce1ef5502e3dc20f030e108978da0c360fb65.tar.bz2 |
Factor SSLPolicyBackend out of SSLManager.
This reduces the complexity of SSLManager. The idea is eventually to be able to test SSLPolicy by substituting a fake SSLPolicyBackend.
TBR=jcampan
TEST=No behavior changes.
Review URL: http://codereview.chromium.org/113395
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16048 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/browser.vcproj | 8 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_error_handler.h | 4 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_manager.cc | 177 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_manager.h | 81 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_mixed_content_handler.h | 2 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_policy.cc | 41 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_policy.h | 6 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_policy_backend.cc | 185 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_policy_backend.h | 122 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_request_info.h | 10 | ||||
-rw-r--r-- | chrome/chrome.gyp | 2 |
11 files changed, 364 insertions, 274 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 646bd17..dd12b4c 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -2562,6 +2562,14 @@ > </File> <File + RelativePath=".\ssl\ssl_policy_backend.cc" + > + </File> + <File + RelativePath=".\ssl\ssl_policy_backend.h" + > + </File> + <File RelativePath=".\ssl\ssl_request_info.h" > </File> diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h index 9ef1b04..c891f79 100644 --- a/chrome/browser/ssl/ssl_error_handler.h +++ b/chrome/browser/ssl/ssl_error_handler.h @@ -9,6 +9,7 @@ #include "base/basictypes.h" #include "base/ref_counted.h" +#include "chrome/browser/ssl/ssl_manager.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/common/filter_policy.h" #include "googleurl/src/gurl.h" @@ -16,7 +17,6 @@ class MessageLoop; class SSLCertErrorHandler; -class SSLManager; class TabContents; class URLRequest; @@ -59,7 +59,7 @@ class SSLErrorHandler : public base::RefCountedThreadSafe<SSLErrorHandler> { const std::string& main_frame_origin() const { return main_frame_origin_; } // Call on the UI thread. - SSLManager* manager() const { return manager_; } + SSLPolicyBackend* backend() const { return manager_->backend(); } // Returns the TabContents this object is associated with. Should be // called from the UI thread. diff --git a/chrome/browser/ssl/ssl_manager.cc b/chrome/browser/ssl/ssl_manager.cc index c46a20b..334eaa4 100644 --- a/chrome/browser/ssl/ssl_manager.cc +++ b/chrome/browser/ssl/ssl_manager.cc @@ -43,57 +43,6 @@ #include "chrome/common/temp_scaffolding_stubs.h" #endif -using WebKit::WebConsoleMessage; - -class SSLInfoBarDelegate : public ConfirmInfoBarDelegate { - public: - SSLInfoBarDelegate(TabContents* contents, - const std::wstring message, - const std::wstring& button_label, - Task* task) - : ConfirmInfoBarDelegate(contents), - message_(message), - button_label_(button_label), - task_(task) { - } - virtual ~SSLInfoBarDelegate() {} - - // Overridden from ConfirmInfoBarDelegate: - virtual void InfoBarClosed() { - delete this; - } - virtual std::wstring GetMessageText() const { - return message_; - } - virtual SkBitmap* GetIcon() const { - return ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_INFOBAR_SSL_WARNING); - } - virtual int GetButtons() const { - return !button_label_.empty() ? BUTTON_OK : BUTTON_NONE; - } - virtual std::wstring GetButtonLabel(InfoBarButton button) const { - return button_label_; - } - virtual bool Accept() { - if (task_.get()) { - task_->Run(); - task_.reset(); // Ensures we won't run the task again. - } - return true; - } - - private: - // Labels for the InfoBar's message and button. - std::wstring message_; - std::wstring button_label_; - - // A task to run when the InfoBar is accepted. - scoped_ptr<Task> task_; - - DISALLOW_COPY_AND_ASSIGN(SSLInfoBarDelegate); -}; - // static void SSLManager::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterIntegerPref(prefs::kMixedContentFiltering, @@ -102,8 +51,8 @@ void SSLManager::RegisterUserPrefs(PrefService* prefs) { SSLManager::SSLManager(NavigationController* controller, Delegate* delegate) : delegate_(delegate), - controller_(controller), - ssl_host_state_(controller->profile()->GetSSLHostState()) { + backend_(controller), + controller_(controller) { DCHECK(controller_); // If do delegate is supplied, use the default policy. @@ -126,102 +75,6 @@ SSLManager::SSLManager(NavigationController* controller, Delegate* delegate) SSLManager::~SSLManager() { } -// Delegate API method. -void SSLManager::ShowMessage(const std::wstring& msg) { - ShowMessageWithLink(msg, std::wstring(), NULL); -} - -void SSLManager::ShowMessageWithLink(const std::wstring& msg, - const std::wstring& link_text, - Task* task) { - if (controller_->pending_entry()) { - // The main frame is currently loading, wait until the load is committed so - // to show the error on the right page (once the location bar shows the - // correct url). - if (std::find(pending_messages_.begin(), pending_messages_.end(), msg) == - pending_messages_.end()) - pending_messages_.push_back(SSLMessageInfo(msg, link_text, task)); - - return; - } - - NavigationEntry* entry = controller_->GetActiveEntry(); - if (!entry) - return; - - // Don't show the message if the user doesn't expect an authenticated session. - if (entry->ssl().security_style() <= SECURITY_STYLE_UNAUTHENTICATED) - return; - - if (controller_->tab_contents()) { - controller_->tab_contents()->AddInfoBar( - new SSLInfoBarDelegate(controller_->tab_contents(), msg, link_text, - task)); - } -} - -// Delegate API method. -bool SSLManager::SetMaxSecurityStyle(SecurityStyle style) { - NavigationEntry* entry = controller_->GetActiveEntry(); - if (!entry) { - NOTREACHED(); - return false; - } - - if (entry->ssl().security_style() > style) { - entry->ssl().set_security_style(style); - return true; - } - return false; -} - -// Delegate API method. -void SSLManager::AddMessageToConsole(const string16& message, - const WebConsoleMessage::Level& level) { - controller_->tab_contents()->render_view_host()->AddMessageToConsole( - string16(), message, level); -} - -// Delegate API method. -void SSLManager::MarkHostAsBroken(const std::string& host, int pid) { - ssl_host_state_->MarkHostAsBroken(host, pid); - DispatchSSLInternalStateChanged(); -} - -// Delegate API method. -bool SSLManager::DidMarkHostAsBroken(const std::string& host, int pid) const { - return ssl_host_state_->DidMarkHostAsBroken(host, pid); -} - -// Delegate API method. -void SSLManager::DenyCertForHost(net::X509Certificate* cert, - const std::string& host) { - // Remember that we don't like this cert for this host. - ssl_host_state_->DenyCertForHost(cert, host); -} - -// Delegate API method. -void SSLManager::AllowCertForHost(net::X509Certificate* cert, - const std::string& host) { - ssl_host_state_->AllowCertForHost(cert, host); -} - -// Delegate API method. -net::X509Certificate::Policy::Judgment SSLManager::QueryPolicy( - net::X509Certificate* cert, const std::string& host) { - return ssl_host_state_->QueryPolicy(cert, host); -} - -// Delegate API method. -void SSLManager::AllowMixedContentForHost(const std::string& host) { - ssl_host_state_->AllowMixedContentForHost(host); -} - -// Delegate API method. -bool SSLManager::DidAllowMixedContentForHost(const std::string& host) const { - return ssl_host_state_->DidAllowMixedContentForHost(host); -} - bool SSLManager::ProcessedSSLErrorFromRequest() const { NavigationEntry* entry = controller_->GetActiveEntry(); if (!entry) { @@ -324,13 +177,6 @@ void SSLManager::Observe(NotificationType type, } } -void SSLManager::DispatchSSLInternalStateChanged() { - NotificationService::current()->Notify( - NotificationType::SSL_INTERNAL_STATE_CHANGED, - Source<NavigationController>(controller_), - NotificationService::NoDetails()); -} - void SSLManager::DispatchSSLVisibleStateChanged() { NotificationService::current()->Notify( NotificationType::SSL_VISIBLE_STATE_CHANGED, @@ -346,7 +192,7 @@ void SSLManager::UpdateEntry(NavigationEntry* entry) { NavigationEntry::SSLStatus original_ssl_status = entry->ssl(); // Copy! - delegate()->UpdateEntry(this, entry); + delegate()->UpdateEntry(backend(), entry); if (!entry->ssl().Equals(original_ssl_status)) DispatchSSLVisibleStateChanged(); @@ -361,7 +207,7 @@ 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( - this, + backend(), details->url(), ResourceType::SUB_RESOURCE, details->frame_origin(), @@ -425,7 +271,7 @@ void SSLManager::DidStartResourceResponse(ResourceRequestDetails* details) { DCHECK(details); scoped_refptr<SSLRequestInfo> info = new SSLRequestInfo( - this, + backend(), details->url(), details->resource_type(), details->frame_origin(), @@ -449,23 +295,10 @@ void SSLManager::DidReceiveResourceRedirect(ResourceRedirectDetails* details) { // the HTTP request to https://attacker.com/payload.js. } -void SSLManager::ShowPendingMessages() { - std::vector<SSLMessageInfo>::const_iterator iter; - for (iter = pending_messages_.begin(); - iter != pending_messages_.end(); ++iter) { - ShowMessageWithLink(iter->message, iter->link_text, iter->action); - } - ClearPendingMessages(); -} - void SSLManager::DidChangeSSLInternalState() { UpdateEntry(controller_->GetActiveEntry()); } -void SSLManager::ClearPendingMessages() { - pending_messages_.clear(); -} - // static std::string SSLManager::SerializeSecurityInfo(int cert_id, int cert_status, diff --git a/chrome/browser/ssl/ssl_manager.h b/chrome/browser/ssl/ssl_manager.h index da77c05..d5c4e13 100644 --- a/chrome/browser/ssl/ssl_manager.h +++ b/chrome/browser/ssl/ssl_manager.h @@ -13,6 +13,7 @@ #include "base/observer_list.h" #include "base/ref_counted.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" +#include "chrome/browser/ssl/ssl_policy_backend.h" #include "chrome/browser/tab_contents/provisional_load_details.h" #include "chrome/browser/tab_contents/security_style.h" #include "chrome/common/notification_observer.h" @@ -75,7 +76,7 @@ class SSLManager : public NotificationObserver { virtual void OnRequestStarted(SSLRequestInfo* info) = 0; // Update the SSL information in |entry| to match the current state. - virtual void UpdateEntry(SSLManager* manager, NavigationEntry* entry) = 0; + virtual void UpdateEntry(SSLPolicyBackend* backend, NavigationEntry* entry) = 0; }; static void RegisterUserPrefs(PrefService* prefs); @@ -86,67 +87,13 @@ class SSLManager : public NotificationObserver { ~SSLManager(); - ////////////////////////////////////////////////////////////////////////////// - // Delegate API - // - // The SSL manager expects these methods to be called by its delegate. They - // exist to make Delegates easy to implement. - - // Ensure that the specified message is displayed to the user. This will - // display an InfoBar at the top of the associated tab. - void ShowMessage(const std::wstring& msg); - - // Same as ShowMessage but also contains a link that when clicked run the - // specified task. The SSL Manager becomes the owner of the task. - void ShowMessageWithLink(const std::wstring& msg, - const std::wstring& link_text, - Task* task); - - // Records that a host is "broken," that is, the origin for that host has been - // contaminated with insecure content, either via HTTP or via HTTPS with a - // bad certificate. - void MarkHostAsBroken(const std::string& host, int pid); - - // Returns whether the specified host was marked as broken. - bool DidMarkHostAsBroken(const std::string& host, int pid) const; - - // Sets the maximum security style for the page. If the current security - // style is lower than |style|, this will not have an effect on the security - // indicators. - // - // It will return true if the navigation entry was updated or false if - // nothing changed. The caller is responsible for broadcasting - // NOTIFY_SSY_STATE_CHANGED if it returns true. - bool SetMaxSecurityStyle(SecurityStyle style); - - // Logs a message to the console of the page. - void AddMessageToConsole(const string16& message, - const WebKit::WebConsoleMessage::Level&); - - // Records that |cert| is permitted to be used for |host| in the future. - void DenyCertForHost(net::X509Certificate* cert, const std::string& host); - - // Records that |cert| is not permitted to be used for |host| in the future. - void AllowCertForHost(net::X509Certificate* cert, const std::string& host); - - // Queries whether |cert| is allowed or denied for |host|. - net::X509Certificate::Policy::Judgment QueryPolicy( - net::X509Certificate* cert, const std::string& host); - - // Allow mixed content to be visible (non filtered). - void AllowMixedContentForHost(const std::string& host); - - // Returns whether the specified host is allowed to show mixed content. - bool DidAllowMixedContentForHost(const std::string& host) const; - - // - ////////////////////////////////////////////////////////////////////////////// - // 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; } + SSLPolicyBackend* backend() { return &backend_; } + // 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 @@ -171,13 +118,14 @@ class SSLManager : public NotificationObserver { URLRequest* request, MessageLoop* ui_loop); - // Called by CertError::Dispatch to kick off processing of the cert error by - // the SSL manager. The error originated from the ResourceDispatcherHost. + // 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 MixedContentHandler::Dispatch to kick off processing of the + // Called by SSLMixedContentHandler::OnDispatch to kick off processing of the // mixed-content resource request. The info originated from the // ResourceDispatcherHost. // @@ -255,9 +203,6 @@ class SSLManager : public NotificationObserver { void DidReceiveResourceRedirect(ResourceRedirectDetails* details); void DidChangeSSLInternalState(); - // Dispatch NotificationType::SSL_INTERNAL_STATE_CHANGED notification. - void DispatchSSLInternalStateChanged(); - // Dispatch NotificationType::SSL_VISIBLE_STATE_CHANGED notification. void DispatchSSLVisibleStateChanged(); @@ -274,6 +219,9 @@ class SSLManager : public NotificationObserver { // Must not be NULL. Delegate* delegate_; + // The backend for the SSLPolicy to actuate its decisions. + SSLPolicyBackend backend_; + // The NavigationController that owns this SSLManager. We are responsible // for the security UI of this tab. NavigationController* controller_; @@ -281,13 +229,6 @@ class SSLManager : public NotificationObserver { // Handles registering notifications with the NotificationService. NotificationRegistrar registrar_; - // SSL state specific for each host. - SSLHostState* ssl_host_state_; - - // The list of messages that should be displayed (in info bars) when the page - // currently loading had loaded. - std::vector<SSLMessageInfo> pending_messages_; - DISALLOW_COPY_AND_ASSIGN(SSLManager); }; diff --git a/chrome/browser/ssl/ssl_mixed_content_handler.h b/chrome/browser/ssl/ssl_mixed_content_handler.h index c3f9057..1ed2e0c 100644 --- a/chrome/browser/ssl/ssl_mixed_content_handler.h +++ b/chrome/browser/ssl/ssl_mixed_content_handler.h @@ -28,7 +28,7 @@ class SSLMixedContentHandler : public SSLErrorHandler { protected: virtual void OnDispatchFailed() { TakeNoAction(); } - virtual void OnDispatched() { manager()->OnMixedContent(this); } + virtual void OnDispatched() { manager_->OnMixedContent(this); } private: int pid_; diff --git a/chrome/browser/ssl/ssl_policy.cc b/chrome/browser/ssl/ssl_policy.cc index 9c37117..6c9ac63 100644 --- a/chrome/browser/ssl/ssl_policy.cc +++ b/chrome/browser/ssl/ssl_policy.cc @@ -30,48 +30,47 @@ #include "net/base/ssl_info.h" #include "webkit/glue/resource_type.h" - using WebKit::WebConsoleMessage; // Wrap all these helper classes in an anonymous namespace. namespace { -static void MarkOriginAsBroken(SSLManager* manager, +static void MarkOriginAsBroken(SSLPolicyBackend* backend, const std::string& origin, int pid) { GURL parsed_origin(origin); if (!parsed_origin.SchemeIsSecure()) return; - manager->MarkHostAsBroken(parsed_origin.host(), pid); + backend->MarkHostAsBroken(parsed_origin.host(), pid); } -static void AllowMixedContentForOrigin(SSLManager* manager, +static void AllowMixedContentForOrigin(SSLPolicyBackend* backend, const std::string& origin) { GURL parsed_origin(origin); if (!parsed_origin.SchemeIsSecure()) return; - manager->AllowMixedContentForHost(parsed_origin.host()); + 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->manager(), info->frame_origin(), info->pid()); + 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->manager(), info->main_frame_origin(), info->pid()); + 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->manager()->MarkHostAsBroken(info->url().host(), info->pid()); + info->backend()->MarkHostAsBroken(info->url().host(), info->pid()); UpdateStateForMixedContent(info); } @@ -97,10 +96,10 @@ ShowMixedContentTask::~ShowMixedContentTask() { } void ShowMixedContentTask::Run() { - AllowMixedContentForOrigin(handler_->manager(), handler_->frame_origin()); - AllowMixedContentForOrigin(handler_->manager(), + AllowMixedContentForOrigin(handler_->backend(), handler_->frame_origin()); + AllowMixedContentForOrigin(handler_->backend(), handler_->main_frame_origin()); - handler_->manager()->controller()->Reload(true); + handler_->backend()->Reload(); } static void ShowErrorPage(SSLPolicy* policy, SSLCertErrorHandler* handler) { @@ -161,7 +160,7 @@ static void AddMixedContentWarningToConsole(SSLMixedContentHandler* handler) { IDS_MIXED_CONTENT_LOG_MESSAGE, UTF8ToWide(handler->frame_origin()), UTF8ToWide(handler->request_url().spec())); - handler->manager()->AddMessageToConsole( + handler->backend()->AddMessageToConsole( WideToUTF16Hack(text), WebConsoleMessage::LevelWarning); } @@ -177,7 +176,7 @@ SSLPolicy* SSLPolicy::GetDefaultPolicy() { void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) { // First we check if we know the policy for this error. net::X509Certificate::Policy::Judgment judgment = - handler->manager()->QueryPolicy(handler->ssl_info().cert, + handler->backend()->QueryPolicy(handler->ssl_info().cert, handler->request_url().host()); if (judgment == net::X509Certificate::Policy::ALLOWED) { @@ -202,7 +201,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->manager()->ShowMessage(l10n_util::GetString( + handler->backend()->ShowMessage(l10n_util::GetString( IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_INFO_BAR)); break; case net::ERR_CERT_CONTAINS_ERRORS: @@ -225,12 +224,12 @@ 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->manager()->DidAllowMixedContentForHost(host) || - handler->manager()->DidMarkHostAsBroken(host, handler->pid())) + if (handler->backend()->DidAllowMixedContentForHost(host) || + handler->backend()->DidMarkHostAsBroken(host, handler->pid())) filter_policy = FilterPolicy::DONT_FILTER; if (filter_policy != FilterPolicy::DONT_FILTER) { - handler->manager()->ShowMessageWithLink( + handler->backend()->ShowMessageWithLink( l10n_util::GetString(IDS_SSL_INFO_BAR_FILTERED_CONTENT), l10n_util::GetString(IDS_SSL_INFO_BAR_SHOW_CONTENT), new ShowMixedContentTask(handler)); @@ -251,7 +250,7 @@ void SSLPolicy::OnRequestStarted(SSLRequestInfo* info) { UpdateStateForMixedContent(info); } -void SSLPolicy::UpdateEntry(SSLManager* manager, NavigationEntry* entry) { +void SSLPolicy::UpdateEntry(SSLPolicyBackend* backend, NavigationEntry* entry) { DCHECK(entry); InitializeEntryIfNeeded(entry); @@ -272,7 +271,7 @@ void SSLPolicy::UpdateEntry(SSLManager* manager, NavigationEntry* entry) { return; } - if (manager->DidMarkHostAsBroken(entry->url().host(), + if (backend->DidMarkHostAsBroken(entry->url().host(), entry->site_instance()->GetProcess()->pid())) entry->ssl().set_has_mixed_content(); } @@ -322,7 +321,7 @@ 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->manager()->DenyCertForHost(handler->ssl_info().cert, + handler->backend()->DenyCertForHost(handler->ssl_info().cert, handler->request_url().host()); handler->CancelRequest(); } @@ -338,7 +337,7 @@ 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->manager()->AllowCertForHost(handler->ssl_info().cert, + handler->backend()->AllowCertForHost(handler->ssl_info().cert, handler->request_url().host()); handler->ContinueRequest(); } diff --git a/chrome/browser/ssl/ssl_policy.h b/chrome/browser/ssl/ssl_policy.h index 204a96e..117120d 100644 --- a/chrome/browser/ssl/ssl_policy.h +++ b/chrome/browser/ssl/ssl_policy.h @@ -12,8 +12,8 @@ // SSLPolicy // // This class is responsible for making the security decisions that concern the -// SSL trust indicators. It relies on the SSLManager to actually enact the -// decisions it reaches. +// SSL trust indicators. It relies on the SSLPolicyBackend to actually enact +// the decisions it reaches. // class SSLPolicy : public SSLManager::Delegate, public SSLBlockingPage::Delegate { @@ -25,7 +25,7 @@ class SSLPolicy : public SSLManager::Delegate, virtual void OnCertError(SSLCertErrorHandler* handler); virtual void OnMixedContent(SSLMixedContentHandler* handler); virtual void OnRequestStarted(SSLRequestInfo* info); - virtual void UpdateEntry(SSLManager* manager, NavigationEntry* entry); + virtual void UpdateEntry(SSLPolicyBackend* backend, NavigationEntry* entry); // This method is static because it is called from both the UI and the IO // threads. diff --git a/chrome/browser/ssl/ssl_policy_backend.cc b/chrome/browser/ssl/ssl_policy_backend.cc new file mode 100644 index 0000000..96cc8ce --- /dev/null +++ b/chrome/browser/ssl/ssl_policy_backend.cc @@ -0,0 +1,185 @@ +// 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_policy_backend.h" + +#include "app/resource_bundle.h" +#include "chrome/browser/ssl/ssl_host_state.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/tab_contents.h" +#include "chrome/common/notification_service.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" + +using WebKit::WebConsoleMessage; + +class SSLInfoBarDelegate : public ConfirmInfoBarDelegate { + public: + SSLInfoBarDelegate(TabContents* contents, + const std::wstring message, + const std::wstring& button_label, + Task* task) + : ConfirmInfoBarDelegate(contents), + message_(message), + button_label_(button_label), + task_(task) { + } + virtual ~SSLInfoBarDelegate() {} + + // Overridden from ConfirmInfoBarDelegate: + virtual void InfoBarClosed() { + delete this; + } + virtual std::wstring GetMessageText() const { + return message_; + } + virtual SkBitmap* GetIcon() const { + return ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_INFOBAR_SSL_WARNING); + } + virtual int GetButtons() const { + return !button_label_.empty() ? BUTTON_OK : BUTTON_NONE; + } + virtual std::wstring GetButtonLabel(InfoBarButton button) const { + return button_label_; + } + virtual bool Accept() { + if (task_.get()) { + task_->Run(); + task_.reset(); // Ensures we won't run the task again. + } + return true; + } + + private: + // Labels for the InfoBar's message and button. + std::wstring message_; + std::wstring button_label_; + + // A task to run when the InfoBar is accepted. + scoped_ptr<Task> task_; + + DISALLOW_COPY_AND_ASSIGN(SSLInfoBarDelegate); +}; + +SSLPolicyBackend::SSLPolicyBackend(NavigationController* controller) + : controller_(controller), + ssl_host_state_(controller->profile()->GetSSLHostState()) { + DCHECK(controller_); + DCHECK(ssl_host_state_); +} + +void SSLPolicyBackend::ShowMessage(const std::wstring& msg) { + ShowMessageWithLink(msg, std::wstring(), NULL); +} + +void SSLPolicyBackend::ShowMessageWithLink(const std::wstring& msg, + const std::wstring& link_text, + Task* task) { + if (controller_->pending_entry()) { + // The main frame is currently loading, wait until the load is committed so + // to show the error on the right page (once the location bar shows the + // correct url). + if (std::find(pending_messages_.begin(), pending_messages_.end(), msg) == + pending_messages_.end()) + pending_messages_.push_back(SSLMessageInfo(msg, link_text, task)); + + return; + } + + NavigationEntry* entry = controller_->GetActiveEntry(); + if (!entry) + return; + + // Don't show the message if the user doesn't expect an authenticated session. + if (entry->ssl().security_style() <= SECURITY_STYLE_UNAUTHENTICATED) + return; + + if (controller_->tab_contents()) { + controller_->tab_contents()->AddInfoBar( + new SSLInfoBarDelegate(controller_->tab_contents(), msg, link_text, + task)); + } +} + +bool SSLPolicyBackend::SetMaxSecurityStyle(SecurityStyle style) { + NavigationEntry* entry = controller_->GetActiveEntry(); + if (!entry) { + NOTREACHED(); + return false; + } + + if (entry->ssl().security_style() > style) { + entry->ssl().set_security_style(style); + return true; + } + return false; +} + +void SSLPolicyBackend::AddMessageToConsole( + const string16& message, const WebConsoleMessage::Level& level) { + controller_->tab_contents()->render_view_host()->AddMessageToConsole( + string16(), message, level); +} + +void SSLPolicyBackend::MarkHostAsBroken(const std::string& host, int pid) { + ssl_host_state_->MarkHostAsBroken(host, pid); + DispatchSSLInternalStateChanged(); +} + +bool SSLPolicyBackend::DidMarkHostAsBroken(const std::string& host, + int pid) const { + return ssl_host_state_->DidMarkHostAsBroken(host, pid); +} + +void SSLPolicyBackend::DenyCertForHost(net::X509Certificate* cert, + const std::string& host) { + // Remember that we don't like this cert for this host. + ssl_host_state_->DenyCertForHost(cert, host); +} + +void SSLPolicyBackend::AllowCertForHost(net::X509Certificate* cert, + const std::string& host) { + ssl_host_state_->AllowCertForHost(cert, host); +} + +net::X509Certificate::Policy::Judgment SSLPolicyBackend::QueryPolicy( + net::X509Certificate* cert, const std::string& host) { + return ssl_host_state_->QueryPolicy(cert, host); +} + +void SSLPolicyBackend::AllowMixedContentForHost(const std::string& host) { + ssl_host_state_->AllowMixedContentForHost(host); +} + +bool SSLPolicyBackend::DidAllowMixedContentForHost( + const std::string& host) const { + return ssl_host_state_->DidAllowMixedContentForHost(host); +} + +void SSLPolicyBackend::Reload() { + controller_->Reload(true); +} + +void SSLPolicyBackend::DispatchSSLInternalStateChanged() { + NotificationService::current()->Notify( + NotificationType::SSL_INTERNAL_STATE_CHANGED, + Source<NavigationController>(controller_), + NotificationService::NoDetails()); +} + +void SSLPolicyBackend::ShowPendingMessages() { + std::vector<SSLMessageInfo>::const_iterator iter; + for (iter = pending_messages_.begin(); + iter != pending_messages_.end(); ++iter) { + ShowMessageWithLink(iter->message, iter->link_text, iter->action); + } + ClearPendingMessages(); +} + +void SSLPolicyBackend::ClearPendingMessages() { + pending_messages_.clear(); +} diff --git a/chrome/browser/ssl/ssl_policy_backend.h b/chrome/browser/ssl/ssl_policy_backend.h new file mode 100644 index 0000000..b0af806 --- /dev/null +++ b/chrome/browser/ssl/ssl_policy_backend.h @@ -0,0 +1,122 @@ +// 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. + +#ifndef CHROME_BROWSER_SSL_SSL_POLICY_BACKEND_H_ +#define CHROME_BROWSER_SSL_SSL_POLICY_BACKEND_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "chrome/browser/tab_contents/security_style.h" +#include "net/base/x509_certificate.h" +#include "webkit/api/public/WebConsoleMessage.h" + +class NavigationController; +class SSLHostState; +class Task; + +class SSLPolicyBackend { + public: + explicit SSLPolicyBackend(NavigationController* controller); + + // Ensure that the specified message is displayed to the user. This will + // display an InfoBar at the top of the associated tab. + void ShowMessage(const std::wstring& msg); + + // Same as ShowMessage but also contains a link that when clicked run the + // specified task. The SSL Manager becomes the owner of the task. + void ShowMessageWithLink(const std::wstring& msg, + const std::wstring& link_text, + Task* task); + + // Records that a host is "broken," that is, the origin for that host has been + // contaminated with insecure content, either via HTTP or via HTTPS with a + // bad certificate. + void MarkHostAsBroken(const std::string& host, int pid); + + // Returns whether the specified host was marked as broken. + bool DidMarkHostAsBroken(const std::string& host, int pid) const; + + // Sets the maximum security style for the page. If the current security + // style is lower than |style|, this will not have an effect on the security + // indicators. + // + // It will return true if the navigation entry was updated or false if + // nothing changed. The caller is responsible for broadcasting + // NOTIFY_SSY_STATE_CHANGED if it returns true. + bool SetMaxSecurityStyle(SecurityStyle style); + + // Logs a message to the console of the page. + void AddMessageToConsole(const string16& message, + const WebKit::WebConsoleMessage::Level&); + + // Records that |cert| is permitted to be used for |host| in the future. + void DenyCertForHost(net::X509Certificate* cert, const std::string& host); + + // Records that |cert| is not permitted to be used for |host| in the future. + void AllowCertForHost(net::X509Certificate* cert, const std::string& host); + + // Queries whether |cert| is allowed or denied for |host|. + net::X509Certificate::Policy::Judgment QueryPolicy( + net::X509Certificate* cert, const std::string& host); + + // Allow mixed content to be visible (non filtered). + void AllowMixedContentForHost(const std::string& host); + + // Returns whether the specified host is allowed to show mixed content. + bool DidAllowMixedContentForHost(const std::string& host) const; + + // Reloads the tab. + void Reload(); + + private: + // SSLMessageInfo contains the information necessary for displaying a message + // in an info-bar. + struct SSLMessageInfo { + public: + explicit SSLMessageInfo(const std::wstring& text) + : message(text), + action(NULL) { } + + SSLMessageInfo(const std::wstring& message, + const std::wstring& link_text, + Task* action) + : message(message), link_text(link_text), action(action) { } + + // Overridden so that std::find works. + bool operator==(const std::wstring& other_message) const { + // We are uniquing SSLMessageInfo by their message only. + return message == other_message; + } + + std::wstring message; + std::wstring link_text; + Task* action; + }; + + // Dispatch NotificationType::SSL_INTERNAL_STATE_CHANGED notification. + void DispatchSSLInternalStateChanged(); + + // Shows the pending messages (in info-bars) if any. + void ShowPendingMessages(); + + // Clears any pending messages. + void ClearPendingMessages(); + + // The NavigationController that owns this SSLManager. We are responsible + // for the security UI of this tab. + NavigationController* controller_; + + // SSL state specific for each host. + SSLHostState* ssl_host_state_; + + // The list of messages that should be displayed (in info bars) when the page + // currently loading had loaded. + std::vector<SSLMessageInfo> pending_messages_; + + DISALLOW_COPY_AND_ASSIGN(SSLPolicyBackend); +}; + +#endif // CHROME_BROWSER_SSL_SSL_POLICY_BACKEND_H_ diff --git a/chrome/browser/ssl/ssl_request_info.h b/chrome/browser/ssl/ssl_request_info.h index bd1544a..9128e97 100644 --- a/chrome/browser/ssl/ssl_request_info.h +++ b/chrome/browser/ssl/ssl_request_info.h @@ -11,14 +11,14 @@ #include "googleurl/src/gurl.h" #include "webkit/glue/resource_type.h" -class SSLManager; +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(SSLManager* manager, + SSLRequestInfo(SSLPolicyBackend* backend, const GURL& url, ResourceType::Type resource_type, const std::string& frame_origin, @@ -27,7 +27,7 @@ class SSLRequestInfo : public base::RefCounted<SSLRequestInfo> { int pid, int ssl_cert_id, int ssl_cert_status) - : manager_(manager), + : backend_(backend), url_(url), resource_type_(resource_type), frame_origin_(frame_origin), @@ -38,7 +38,7 @@ class SSLRequestInfo : public base::RefCounted<SSLRequestInfo> { ssl_cert_status_(ssl_cert_status) { } - SSLManager* manager() const { return manager_; } + 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 +49,7 @@ class SSLRequestInfo : public base::RefCounted<SSLRequestInfo> { int ssl_cert_status() const { return ssl_cert_status_; } private: - SSLManager* manager_; + SSLPolicyBackend* backend_; GURL url_; ResourceType::Type resource_type_; std::string frame_origin_; diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index a37d2b0..e1237d1 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1302,6 +1302,8 @@ 'browser/ssl/ssl_mixed_content_handler.h', 'browser/ssl/ssl_policy.cc', 'browser/ssl/ssl_policy.h', + 'browser/ssl/ssl_policy_backend.cc', + 'browser/ssl/ssl_policy_backend.h', 'browser/ssl/ssl_request_info.h', 'browser/status_bubble.h', 'browser/tab_contents/constrained_window.h', |