diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-16 03:29:03 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-16 03:29:03 +0000 |
commit | 3b073b258b19937b1dd9b6b2a609dee207865eba (patch) | |
tree | fb0779236d58e8a49513c1036d891c2e10c9573c /chrome/browser/ssl/ssl_manager.cc | |
parent | 7fb087e0800d0faaa31e4a029ad6813f251b4848 (diff) | |
download | chromium_src-3b073b258b19937b1dd9b6b2a609dee207865eba.zip chromium_src-3b073b258b19937b1dd9b6b2a609dee207865eba.tar.gz chromium_src-3b073b258b19937b1dd9b6b2a609dee207865eba.tar.bz2 |
Move all the SSL stuff into its own subdir
Review URL: http://codereview.chromium.org/18137
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8165 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ssl/ssl_manager.cc')
-rw-r--r-- | chrome/browser/ssl/ssl_manager.cc | 725 |
1 files changed, 725 insertions, 0 deletions
diff --git a/chrome/browser/ssl/ssl_manager.cc b/chrome/browser/ssl/ssl_manager.cc new file mode 100644 index 0000000..b2fd246 --- /dev/null +++ b/chrome/browser/ssl/ssl_manager.cc @@ -0,0 +1,725 @@ +// Copyright (c) 2006-2008 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_manager.h" + +#include "base/message_loop.h" +#include "base/string_util.h" +#include "chrome/app/theme/theme_resources.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/load_notification_details.h" +#include "chrome/browser/load_from_memory_cache_details.h" +#include "chrome/browser/render_view_host.h" +#include "chrome/browser/resource_request_details.h" +#include "chrome/browser/ssl/ssl_error_info.h" +#include "chrome/browser/ssl/ssl_policy.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/browser/tab_contents/web_contents.h" +#include "chrome/common/l10n_util.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "chrome/common/resource_bundle.h" +#include "chrome/views/decision.h" +#include "chrome/views/link.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" +#include "generated_resources.h" + +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); +}; + +//////////////////////////////////////////////////////////////////////////////// +// SSLManager + +// static +void SSLManager::RegisterUserPrefs(PrefService* prefs) { + prefs->RegisterIntegerPref(prefs::kMixedContentFiltering, + FilterPolicy::DONT_FILTER); +} + +SSLManager::SSLManager(NavigationController* controller, Delegate* delegate) + : controller_(controller), + delegate_(delegate) { + DCHECK(controller_); + + // If do delegate is supplied, use the default policy. + if (!delegate_) + delegate_ = SSLPolicy::GetDefaultPolicy(); + + // Subscribe to various notifications. + registrar_.Add(this, NOTIFY_NAV_ENTRY_COMMITTED, + Source<NavigationController>(controller_)); + registrar_.Add(this, NOTIFY_FAIL_PROVISIONAL_LOAD_WITH_ERROR, + Source<NavigationController>(controller_)); + registrar_.Add(this, NOTIFY_RESOURCE_RESPONSE_STARTED, + Source<NavigationController>(controller_)); + registrar_.Add(this, NOTIFY_RESOURCE_RECEIVED_REDIRECT, + Source<NavigationController>(controller_)); + registrar_.Add(this, NOTIFY_LOAD_FROM_MEMORY_CACHE, + Source<NavigationController>(controller_)); +} + +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_->GetPendingEntry()) { + // 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_->active_contents()) { + controller_->active_contents()->AddInfoBar( + new SSLInfoBarDelegate(controller_->active_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 std::wstring& msg, + ConsoleMessageLevel level) { + TabContents* tab_contents = controller_->GetTabContents(TAB_CONTENTS_WEB); + if (!tab_contents) + return; + WebContents* web_contents = tab_contents->AsWebContents(); + if (!web_contents) + return; + + web_contents->render_view_host()->AddMessageToConsole( + std::wstring(), msg, level); +} + +// Delegate API method. +void SSLManager::DenyCertForHost(net::X509Certificate* cert, + const std::string& host) { + // Remember that we don't like this cert for this host. + // TODO(abarth): Do we want to persist this information in the user's profile? + cert_policy_for_host_[host].Deny(cert); +} + +// Delegate API method. +void SSLManager::AllowCertForHost(net::X509Certificate* cert, + const std::string& host) { + // Remember that we do like this cert for this host. + // TODO(abarth): Do we want to persist this information in the user's profile? + cert_policy_for_host_[host].Allow(cert); +} + +// Delegate API method. +net::X509Certificate::Policy::Judgment SSLManager::QueryPolicy( + net::X509Certificate* cert, const std::string& host) { + // TODO(abarth): Do we want to read this information from the user's profile? + return cert_policy_for_host_[host].Check(cert); +} + +bool SSLManager::CanShowInsecureContent(const GURL& url) { + // TODO(jcampan): Do we want to read this information from the user's profile? + return (can_show_insecure_content_for_host_.find(url.host()) != + can_show_insecure_content_for_host_.end()); +} + +void SSLManager::AllowShowInsecureContentForURL(const GURL& url) { + can_show_insecure_content_for_host_.insert(url.host()); +} + +bool SSLManager::ProcessedSSLErrorFromRequest() const { + NavigationEntry* entry = controller_->GetActiveEntry(); + if (!entry) { + NOTREACHED(); + return false; + } + + return net::IsCertStatusError(entry->ssl().cert_status()); +} + +//////////////////////////////////////////////////////////////////////////////// +// ErrorHandler + +SSLManager::ErrorHandler::ErrorHandler(ResourceDispatcherHost* rdh, + URLRequest* request, + MessageLoop* ui_loop) + : ui_loop_(ui_loop), + io_loop_(MessageLoop::current()), + manager_(NULL), + resource_dispatcher_host_(rdh), + request_has_been_notified_(false), + request_id_(0, 0), + request_url_(request->url()) { + DCHECK(MessageLoop::current() != ui_loop); + + ResourceDispatcherHost::ExtraRequestInfo* info = + ResourceDispatcherHost::ExtraInfoForRequest(request); + request_id_.render_process_host_id = info->render_process_host_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 SSLManager::ErrorHandler::Dispatch() { + DCHECK(MessageLoop::current() == ui_loop_); + + TabContents* web_contents = + tab_util::GetWebContentsByID(render_process_host_id_, tab_contents_id_); + + if (!web_contents) { + // We arrived on the UI thread, but the tab we're looking for is no longer + // here. + OnDispatchFailed(); + return; + } + + // Hand ourselves off to the SSLManager. + manager_ = web_contents->controller()->ssl_manager(); + OnDispatched(); +} + +WebContents* SSLManager::ErrorHandler::GetWebContents() { + return tab_util::GetWebContentsByID(render_process_host_id_, + tab_contents_id_); +} + +void SSLManager::ErrorHandler::CancelRequest() { + DCHECK(MessageLoop::current() == ui_loop_); + + // We need to complete this task on the IO thread. + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &SSLManager::ErrorHandler::CompleteCancelRequest, + net::ERR_ABORTED)); +} + +void SSLManager::ErrorHandler::DenyRequest() { + DCHECK(MessageLoop::current() == ui_loop_); + + // We need to complete this task on the IO thread. + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &SSLManager::ErrorHandler::CompleteCancelRequest, + net::ERR_INSECURE_RESPONSE)); +} + +void SSLManager::ErrorHandler::ContinueRequest() { + DCHECK(MessageLoop::current() == ui_loop_); + + // We need to complete this task on the IO thread. + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &SSLManager::ErrorHandler::CompleteContinueRequest)); +} + +void SSLManager::ErrorHandler::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, &SSLManager::ErrorHandler::CompleteStartRequest, filter_policy)); +} + +void SSLManager::ErrorHandler::TakeNoAction() { + DCHECK(MessageLoop::current() == ui_loop_); + + // We need to complete this task on the IO thread. + io_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &SSLManager::ErrorHandler::CompleteTakeNoAction)); +} + +void SSLManager::ErrorHandler::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(); + request->CancelWithError(error); + } + request_has_been_notified_ = true; + + // We're done with this object on the IO thread. + Release(); + } +} + +void SSLManager::ErrorHandler::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 SSLManager::ErrorHandler::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 SSLManager::ErrorHandler::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(); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// CertError + +SSLManager::CertError::CertError( + ResourceDispatcherHost* rdh, + URLRequest* request, + ResourceType::Type resource_type, + int cert_error, + net::X509Certificate* cert, + MessageLoop* ui_loop) + : ErrorHandler(rdh, request, ui_loop), + cert_error_(cert_error), + resource_type_(resource_type) { + 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); +} + +// static +void SSLManager::OnSSLCertificateError(ResourceDispatcherHost* rdh, + URLRequest* request, + int cert_error, + net::X509Certificate* cert, + MessageLoop* ui_loop) { + DLOG(INFO) << "OnSSLCertificateError() cert_error: " << cert_error << + " url: " << request->url().spec(); + + ResourceDispatcherHost::ExtraRequestInfo* info = + ResourceDispatcherHost::ExtraInfoForRequest(request); + DCHECK(info); + + // 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), + &CertError::Dispatch)); +} + +// static +void SSLManager::OnMixedContentRequest(ResourceDispatcherHost* rdh, + URLRequest* request, + MessageLoop* ui_loop) { + ui_loop->PostTask(FROM_HERE, + NewRunnableMethod(new MixedContentHandler(rdh, request, ui_loop), + &MixedContentHandler::Dispatch)); +} + +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); +} + +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); +} + +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) { + case NOTIFY_NAV_ENTRY_COMMITTED: + DidCommitProvisionalLoad(details); + break; + case NOTIFY_FAIL_PROVISIONAL_LOAD_WITH_ERROR: + DidFailProvisionalLoadWithError( + Details<ProvisionalLoadDetails>(details).ptr()); + break; + case NOTIFY_RESOURCE_RESPONSE_STARTED: + DidStartResourceResponse(Details<ResourceRequestDetails>(details).ptr()); + break; + case NOTIFY_RESOURCE_RECEIVED_REDIRECT: + DidReceiveResourceRedirect( + Details<ResourceRedirectDetails>(details).ptr()); + break; + case NOTIFY_LOAD_FROM_MEMORY_CACHE: + DidLoadFromMemoryCache( + Details<LoadFromMemoryCacheDetails>(details).ptr()); + break; + default: + NOTREACHED() << "The SSLManager received an unexpected notification."; + } +} + +void SSLManager::InitializeEntryIfNeeded(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())); + } +} + +void SSLManager::NavigationStateChanged() { + NavigationEntry* active_entry = controller_->GetActiveEntry(); + if (!active_entry) + return; // Nothing showing yet. + + // This might be a new entry we've never seen before. + InitializeEntryIfNeeded(active_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()); +} + +void SSLManager::DidCommitProvisionalLoad( + const NotificationDetails& in_details) { + NavigationController::LoadCommittedDetails* details = + Details<NavigationController::LoadCommittedDetails>(in_details).ptr(); + + // Ignore in-page navigations, they should not change the security style or + // the info-bars. + if (details->is_in_page) + return; + + // Decode the security details. + int ssl_cert_id, ssl_cert_status, ssl_security_bits; + DeserializeSecurityInfo(details->serialized_security_info, + &ssl_cert_id, &ssl_cert_status, &ssl_security_bits); + + bool changed = false; + if (details->is_main_frame) { + // Update the SSL states of the pending entry. + NavigationEntry* entry = controller_->GetActiveEntry(); + if (entry) { + // 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. + 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; + } + + ShowPendingMessages(); + } + + // An HTTPS response may not have a certificate for some reason. When that + // happens, use the unauthenticated (HTTP) rather than the authentication + // broken security style so that we can detect this error condition. + if (net::IsCertStatusError(ssl_cert_status)) { + changed |= 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; + } + } else if (details->entry->url().SchemeIsSecure() && !ssl_cert_id) { + if (details->is_main_frame) { + changed |= 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 + // loaded. + if (!details->is_content_filtered && + !details->entry->ssl().has_mixed_content()) { + details->entry->ssl().set_has_mixed_content(); + changed = true; + } + } + } + + if (changed) { + // Only send the notification when something actually changed. + NotificationService::current()->Notify( + NOTIFY_SSL_STATE_CHANGED, + Source<NavigationController>(controller_), + NotificationService::NoDetails()); + } +} + +void SSLManager::DidFailProvisionalLoadWithError( + ProvisionalLoadDetails* details) { + DCHECK(details); + + // Ignore in-page navigations. + if (details->in_page_navigation()) + return; + + if (details->main_frame()) + ClearPendingMessages(); +} + +void SSLManager::DidStartResourceResponse(ResourceRequestDetails* details) { + DCHECK(details); + + // 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()); +} + +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. +} + +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::ClearPendingMessages() { + pending_messages_.clear(); +} + +// static +std::string SSLManager::SerializeSecurityInfo(int cert_id, + int cert_status, + int security_bits) { + Pickle pickle; + pickle.WriteInt(cert_id); + pickle.WriteInt(cert_status); + pickle.WriteInt(security_bits); + return std::string(static_cast<const char*>(pickle.data()), pickle.size()); +} + +// static +bool SSLManager::DeserializeSecurityInfo(const std::string& state, + int* cert_id, + int* cert_status, + int* security_bits) { + DCHECK(cert_id && cert_status && security_bits); + if (state.empty()) { + // No SSL used. + *cert_id = 0; + *cert_status = 0; + *security_bits = -1; + return false; + } + + Pickle pickle(state.data(), static_cast<int>(state.size())); + void * iter = NULL; + pickle.ReadInt(&iter, cert_id); + pickle.ReadInt(&iter, cert_status); + pickle.ReadInt(&iter, security_bits); + return true; +} + +// static +bool SSLManager::GetEVCertNames(const net::X509Certificate& cert, + std::wstring* short_name, + std::wstring* ca_name) { + DCHECK(short_name || ca_name); + + // EV are required to have an organization name and country. + if (cert.subject().organization_names.empty() || + cert.subject().country_name.empty()) { + NOTREACHED(); + return false; + } + + if (short_name) { + *short_name = l10n_util::GetStringF( + IDS_SECURE_CONNECTION_EV, + UTF8ToWide(cert.subject().organization_names[0]), + UTF8ToWide(cert.subject().country_name)); + } + + if (ca_name) { + // TODO(wtc): should we show the root CA's name instead? + *ca_name = l10n_util::GetStringF( + IDS_SECURE_CONNECTION_EV_CA, + UTF8ToWide(cert.issuer().organization_names[0])); + } + return true; +} + |