Chromium Code Reviews| Index: chrome/browser/ssl/ssl_manager.cc |
| =================================================================== |
| --- chrome/browser/ssl/ssl_manager.cc (revision 11701) |
| +++ chrome/browser/ssl/ssl_manager.cc (working copy) |
| @@ -121,6 +121,8 @@ |
| Source<NavigationController>(controller_)); |
| registrar_.Add(this, NotificationType::LOAD_FROM_MEMORY_CACHE, |
| Source<NavigationController>(controller_)); |
| + registrar_.Add(this, NotificationType::SSL_INTERNAL_STATE_CHANGED, |
| + NotificationService::AllSources()); |
| } |
| SSLManager::~SSLManager() { |
| @@ -161,21 +163,6 @@ |
| } |
| // 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 std::wstring& msg, |
| ConsoleMessageLevel level) { |
| TabContents* tab_contents = controller_->GetTabContents(TAB_CONTENTS_WEB); |
| @@ -190,16 +177,29 @@ |
| } |
| // Delegate API method. |
| +void SSLManager::MarkHostAsBroken(const std::string& host) { |
| + ssl_host_state_->MarkHostAsBroken(host); |
| + DispatchSSLInternalStateChanged(); |
| +} |
| + |
| +// Delegate API method. |
| +bool SSLManager::DidMarkHostAsBroken(const std::string& host) const { |
| + return ssl_host_state_->DidMarkHostAsBroken(host); |
| +} |
| + |
| +// 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); |
| + DispatchSSLInternalStateChanged(); |
| } |
| // Delegate API method. |
| void SSLManager::AllowCertForHost(net::X509Certificate* cert, |
| const std::string& host) { |
| ssl_host_state_->AllowCertForHost(cert, host); |
| + DispatchSSLInternalStateChanged(); |
| } |
| // Delegate API method. |
| @@ -208,12 +208,15 @@ |
| return ssl_host_state_->QueryPolicy(cert, host); |
| } |
| -bool SSLManager::CanShowInsecureContent(const GURL& url) { |
| - return ssl_host_state_->CanShowInsecureContent(url); |
| +// Delegate API method. |
| +void SSLManager::AllowMixedContentForHost(const std::string& host) { |
| + ssl_host_state_->AllowMixedContentForHost(host); |
| + DispatchSSLInternalStateChanged(); |
| } |
| -void SSLManager::AllowShowInsecureContentForURL(const GURL& url) { |
| - ssl_host_state_->AllowShowInsecureContentForURL(url); |
| +// Delegate API method. |
| +bool SSLManager::DidAllowMixedContentForHost(const std::string& host) const { |
| + return ssl_host_state_->DidAllowMixedContentForHost(host); |
| } |
| bool SSLManager::ProcessedSSLErrorFromRequest() const { |
| @@ -231,6 +234,9 @@ |
| SSLManager::ErrorHandler::ErrorHandler(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()), |
| @@ -238,6 +244,9 @@ |
| 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); |
| @@ -428,12 +437,14 @@ |
| 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) |
| - : ErrorHandler(rdh, request, ui_loop), |
| - cert_error_(cert_error), |
| - resource_type_(resource_type) { |
| + : ErrorHandler(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 |
| @@ -458,50 +469,53 @@ |
| // A certificate error occurred. Construct a CertError object and hand it |
| // over to the UI thread for processing. |
| ui_loop->PostTask(FROM_HERE, |
| - NewRunnableMethod(new CertError(rdh, request, info->resource_type, |
| - cert_error, cert, ui_loop), |
| + NewRunnableMethod(new CertError(rdh, |
| + request, |
| + info->resource_type, |
| + info->frame_origin, |
| + info->main_frame_origin, |
| + cert_error, |
| + cert, |
| + ui_loop), |
| &CertError::Dispatch)); |
| } |
| // static |
| -void SSLManager::OnMixedContentRequest(ResourceDispatcherHost* rdh, |
| - URLRequest* request, |
| - MessageLoop* ui_loop) { |
| +bool SSLManager::ShouldDelayRequest(ResourceDispatcherHost* rdh, |
| + URLRequest* request, |
| + MessageLoop* ui_loop) { |
| + ResourceDispatcherHost::ExtraRequestInfo* info = |
| + ResourceDispatcherHost::ExtraInfoForRequest(request); |
| + DCHECK(info); |
| + |
| + // We cheat here and talk to the SSLPolicy on the IO channel because we need |
| + // to respond synchronously to avoid delaying all network requests... |
| + SSLPolicy::IsMixedContent(request->url(), |
|
jcampan
2009/03/16 18:43:54
Don't you want to return false if IsMixedContent r
abarth-chromium
2009/03/16 21:34:21
Yes. :)
|
| + info->resource_type, |
| + info->frame_origin); |
| + |
| + |
| ui_loop->PostTask(FROM_HERE, |
| - NewRunnableMethod(new MixedContentHandler(rdh, request, ui_loop), |
| + NewRunnableMethod(new MixedContentHandler(rdh, request, |
| + info->resource_type, |
| + info->frame_origin, |
| + info->main_frame_origin, |
| + ui_loop), |
| &MixedContentHandler::Dispatch)); |
| + return true; |
| } |
| void SSLManager::OnCertError(CertError* error) { |
| - // Ask our delegate to deal with the error. |
| - NavigationEntry* entry = controller_->GetActiveEntry(); |
| - // We might not have a navigation entry in some cases (e.g. when a |
| - // HTTPS page opens a popup with no URL and then populate it with |
| - // document.write()). See bug http://crbug.com/3845. |
| - if (!entry) |
| - return; |
| - |
| - delegate()->OnCertError(entry->url(), error); |
| + delegate()->OnCertError(error); |
| } |
| void SSLManager::OnMixedContent(MixedContentHandler* mixed_content) { |
| - // Ask our delegate to deal with the mixed content. |
| - NavigationEntry* entry = controller_->GetActiveEntry(); |
| - // We might not have a navigation entry in some cases (e.g. when a |
| - // HTTPS page opens a popup with no URL and then populate it with |
| - // document.write()). See bug http://crbug.com/3845. |
| - if (!entry) |
| - return; |
| - |
| - delegate()->OnMixedContent(controller_, entry->url(), mixed_content); |
| + delegate()->OnMixedContent(mixed_content); |
| } |
| void SSLManager::Observe(NotificationType type, |
| const NotificationSource& source, |
| const NotificationDetails& details) { |
| - // We should only be getting notifications from our controller. |
| - DCHECK(source == Source<NavigationController>(controller_)); |
| - |
| // Dispatch by type. |
| switch (type.value) { |
| case NotificationType::NAV_ENTRY_COMMITTED: |
| @@ -522,43 +536,77 @@ |
| DidLoadFromMemoryCache( |
| Details<LoadFromMemoryCacheDetails>(details).ptr()); |
| break; |
| + case NotificationType::SSL_INTERNAL_STATE_CHANGED: |
| + DidChangeSSLInternalState(); |
| + break; |
| default: |
| NOTREACHED() << "The SSLManager received an unexpected notification."; |
| } |
| } |
| -void SSLManager::InitializeEntryIfNeeded(NavigationEntry* entry) { |
| +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, |
| + Source<NavigationController>(controller_), |
| + NotificationService::NoDetails()); |
| +} |
| + |
| +void SSLManager::UpdateEntry(NavigationEntry* entry) { |
| DCHECK(entry); |
| - // If the security style of the entry is SECURITY_STYLE_UNKNOWN, then it is a |
| - // fresh entry and should get the default style. |
| - if (entry->ssl().security_style() == SECURITY_STYLE_UNKNOWN) { |
| - entry->ssl().set_security_style( |
| - delegate()->GetDefaultStyle(entry->url())); |
| - } |
| + NavigationEntry::SSLStatus original_status = entry->ssl(); // Copy! |
| + |
| + delegate()->UpdateEntry(this, entry); |
| + |
| + if (original_status.security_style() != entry->ssl().security_style() || |
| + original_status.has_mixed_content() != entry->ssl().has_mixed_content() || |
| + original_status.has_unsafe_content() != entry->ssl().has_unsafe_content()) |
| + DispatchSSLVisibleStateChanged(); |
| } |
| void SSLManager::NavigationStateChanged() { |
| - NavigationEntry* active_entry = controller_->GetActiveEntry(); |
| - if (!active_entry) |
| + NavigationEntry* entry = controller_->GetActiveEntry(); |
| + if (!entry) |
| return; // Nothing showing yet. |
| // This might be a new entry we've never seen before. |
| - InitializeEntryIfNeeded(active_entry); |
| + UpdateEntry(entry); |
| } |
| void SSLManager::DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details) { |
| DCHECK(details); |
| - // Simulate loading this resource through the usual path. |
| // Note that we specify SUB_RESOURCE as the resource type as WebCore only |
| // caches sub-resources. |
| - delegate()->OnRequestStarted(this, details->url(), |
| - ResourceType::SUB_RESOURCE, |
| - details->ssl_cert_id(), |
| - details->ssl_cert_status()); |
| + scoped_refptr<RequestInfo> info = new RequestInfo( |
| + this, |
| + details->url(), |
| + ResourceType::SUB_RESOURCE, |
| + details->frame_origin(), |
| + details->main_frame_origin(), |
| + details->ssl_cert_id(), |
| + details->ssl_cert_status()); |
| + |
| + // Simulate loading this resource through the usual path. |
| + delegate()->OnRequestStarted(info.get()); |
| } |
| +void SSLManager::DidChangeSSLInternalState() { |
| + NavigationEntry* entry = controller_->GetActiveEntry(); |
| + if (!entry) |
| + return; // Nothing showing yet. |
| + |
| + // We might have to update the current entry if our SSL state changes. |
| + UpdateEntry(entry); |
| +} |
| + |
| void SSLManager::DidCommitProvisionalLoad( |
| const NotificationDetails& in_details) { |
| NavigationController::LoadCommittedDetails* details = |
| @@ -574,7 +622,7 @@ |
| DeserializeSecurityInfo(details->serialized_security_info, |
| &ssl_cert_id, &ssl_cert_status, &ssl_security_bits); |
| - bool changed = false; |
| + bool entry_changed = false; |
| if (details->is_main_frame) { |
| // Update the SSL states of the pending entry. |
| NavigationEntry* entry = controller_->GetActiveEntry(); |
| @@ -582,11 +630,11 @@ |
| // We may not have an entry if this is a navigation to an initial blank |
| // page. Reset the SSL information and add the new data we have. |
| entry->ssl() = NavigationEntry::SSLStatus(); |
| - InitializeEntryIfNeeded(entry); // For security_style. |
| + UpdateEntry(entry); // For security_style. |
| entry->ssl().set_cert_id(ssl_cert_id); |
| entry->ssl().set_cert_status(ssl_cert_status); |
| entry->ssl().set_security_bits(ssl_security_bits); |
| - changed = true; |
| + entry_changed = true; |
| } |
| ShowPendingMessages(); |
| @@ -597,15 +645,19 @@ |
| // broken security style so that we can detect this error condition. |
| if (net::IsCertStatusError(ssl_cert_status) && |
| !details->is_content_filtered) { |
| - changed |= SetMaxSecurityStyle(SECURITY_STYLE_AUTHENTICATION_BROKEN); |
| + // TODO(abarth): This is wrong. It's the SSLPolicy's job to set the max |
| + // security style. |
| + //SetMaxSecurityStyle(SECURITY_STYLE_AUTHENTICATION_BROKEN); |
| if (!details->is_main_frame && |
| !details->entry->ssl().has_unsafe_content()) { |
| details->entry->ssl().set_has_unsafe_content(); |
| - changed = true; |
| + entry_changed = true; |
| } |
| } else if (details->entry->url().SchemeIsSecure() && !ssl_cert_id) { |
| if (details->is_main_frame) { |
| - changed |= SetMaxSecurityStyle(SECURITY_STYLE_UNAUTHENTICATED); |
| + // TODO(abarth): This is wrong. It's the SSLPolicy's job to set the max |
| + // security style. |
| + //SetMaxSecurityStyle(SECURITY_STYLE_UNAUTHENTICATED); |
| } else { |
| // If the frame has been blocked we keep our security style as |
| // authenticated in that case as nothing insecure is actually showing or |
| @@ -613,18 +665,13 @@ |
| if (!details->is_content_filtered && |
| !details->entry->ssl().has_mixed_content()) { |
| details->entry->ssl().set_has_mixed_content(); |
| - changed = true; |
| + entry_changed = true; |
| } |
| } |
| } |
| - if (changed) { |
| - // Only send the notification when something actually changed. |
| - NotificationService::current()->Notify( |
| - NotificationType::SSL_STATE_CHANGED, |
| - Source<NavigationController>(controller_), |
| - NotificationService::NoDetails()); |
| - } |
| + if (entry_changed) |
| + DispatchSSLVisibleStateChanged(); |
| } |
| void SSLManager::DidFailProvisionalLoadWithError( |
| @@ -642,18 +689,25 @@ |
| void SSLManager::DidStartResourceResponse(ResourceRequestDetails* details) { |
| DCHECK(details); |
| + scoped_refptr<RequestInfo> info = new RequestInfo( |
| + this, |
| + details->url(), |
| + details->resource_type(), |
| + details->frame_origin(), |
| + details->main_frame_origin(), |
| + 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 |
| // that yet. |
| - delegate()->OnRequestStarted(this, details->url(), |
| - details->resource_type(), |
| - details->ssl_cert_id() , |
| - details->ssl_cert_status()); |
| + delegate()->OnRequestStarted(info.get()); |
| } |
| void SSLManager::DidReceiveResourceRedirect(ResourceRedirectDetails* details) { |
| // TODO(jcampan): when we receive a redirect for a sub-resource, we may want |
| // to clear any mixed/unsafe content error that it may have triggered. |
| + // Really??? I'm not sure that's right. -- abarth (3/14/2009) |
| } |
| void SSLManager::ShowPendingMessages() { |