| // Copyright (c) 2012 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 "ios/chrome/browser/ui/omnibox/page_info_model.h" | 
 |  | 
 | #include <stdint.h> | 
 |  | 
 | #include <string> | 
 |  | 
 | #include "base/bind.h" | 
 | #include "base/bind_helpers.h" | 
 | #include "base/command_line.h" | 
 | #include "base/i18n/time_formatting.h" | 
 | #include "base/strings/string16.h" | 
 | #include "base/strings/string_number_conversions.h" | 
 | #include "base/strings/utf_string_conversions.h" | 
 | #include "components/keyed_service/core/service_access_type.h" | 
 | #include "components/ssl_errors/error_info.h" | 
 | #include "components/strings/grit/components_chromium_strings.h" | 
 | #include "components/strings/grit/components_google_chrome_strings.h" | 
 | #include "components/strings/grit/components_strings.h" | 
 | #include "ios/chrome/browser/browser_state/chrome_browser_state.h" | 
 | #include "ios/chrome/browser/chrome_url_constants.h" | 
 | #include "ios/chrome/browser/ui/omnibox/page_info_model_observer.h" | 
 | #include "ios/chrome/grit/ios_chromium_strings.h" | 
 | #include "ios/chrome/grit/ios_strings.h" | 
 | #include "ios/chrome/grit/ios_theme_resources.h" | 
 | #include "ios/web/public/ssl_status.h" | 
 | #include "net/cert/cert_status_flags.h" | 
 | #include "net/cert/x509_certificate.h" | 
 | #include "net/ssl/ssl_cipher_suite_names.h" | 
 | #include "net/ssl/ssl_connection_status_flags.h" | 
 | #include "ui/base/l10n/l10n_util.h" | 
 | #include "ui/base/resource/resource_bundle.h" | 
 |  | 
 | // TODO(crbug.com/227827) Merge 178763: PageInfoModel has been removed in | 
 | // upstream; check if we should use PageInfoModel. | 
 | PageInfoModel::PageInfoModel(ios::ChromeBrowserState* browser_state, | 
 |                              const GURL& url, | 
 |                              const web::SSLStatus& ssl, | 
 |                              PageInfoModelObserver* observer) | 
 |     : observer_(observer) { | 
 |   if (url.SchemeIs(kChromeUIScheme)) { | 
 |     if (url.host() == kChromeUIOfflineHost) { | 
 |       sections_.push_back(SectionInfo( | 
 |           ICON_STATE_OFFLINE_PAGE, | 
 |           l10n_util::GetStringUTF16(IDS_IOS_PAGE_INFO_OFFLINE_TITLE), | 
 |           l10n_util::GetStringUTF16(IDS_IOS_PAGE_INFO_OFFLINE_PAGE), | 
 |           SECTION_INFO_INTERNAL_PAGE, BUTTON_RELOAD)); | 
 |     } else { | 
 |       sections_.push_back( | 
 |           SectionInfo(ICON_STATE_INTERNAL_PAGE, base::string16(), | 
 |                       l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE), | 
 |                       SECTION_INFO_INTERNAL_PAGE, BUTTON_NONE)); | 
 |     } | 
 |     return; | 
 |   } | 
 |  | 
 |   base::string16 hostname(base::UTF8ToUTF16(url.host())); | 
 |  | 
 |   base::string16 summary; | 
 |   base::string16 details; | 
 |   base::string16 certificate_details; | 
 |  | 
 |   // Summary and details. | 
 |   SectionStateIcon icon_id = ICON_NONE; | 
 |   if (!ssl.certificate) { | 
 |     // Not HTTPS. | 
 |     icon_id = ICON_STATE_INFO; | 
 |     summary.assign(l10n_util::GetStringUTF16(IDS_PAGE_INFO_NOT_SECURE_SUMMARY)); | 
 |     details.assign(l10n_util::GetStringUTF16(IDS_PAGE_INFO_NOT_SECURE_DETAILS)); | 
 |   } else { | 
 |     // It is possible to have |SECURITY_STYLE_AUTHENTICATION_BROKEN| and | 
 |     // non-error | 
 |     // |cert_status| for WKWebView because |security_style| and |cert_status| | 
 |     // are | 
 |     // calculated using different API, which may lead to different cert | 
 |     // verification results. | 
 |     if (net::IsCertStatusError(ssl.cert_status) || | 
 |         ssl.security_style == web::SECURITY_STYLE_AUTHENTICATION_BROKEN) { | 
 |       // HTTPS with major errors | 
 |       icon_id = ICON_STATE_ERROR; | 
 |       DCHECK(!net::IsCertStatusMinorError(ssl.cert_status)); | 
 |       summary.assign( | 
 |           l10n_util::GetStringUTF16(IDS_PAGE_INFO_NOT_SECURE_SUMMARY)); | 
 |       details.assign( | 
 |           l10n_util::GetStringUTF16(IDS_PAGE_INFO_NOT_SECURE_DETAILS)); | 
 |  | 
 |       certificate_details.assign(l10n_util::GetStringUTF16( | 
 |           IDS_PAGE_INFO_SECURITY_TAB_INSECURE_IDENTITY)); | 
 |       const base::string16 bullet = base::UTF8ToUTF16("\n • "); | 
 |       std::vector<ssl_errors::ErrorInfo> errors; | 
 |       ssl_errors::ErrorInfo::GetErrorsForCertStatus( | 
 |           ssl.certificate, ssl.cert_status, url, &errors); | 
 |       for (size_t i = 0; i < errors.size(); ++i) { | 
 |         certificate_details += bullet; | 
 |         certificate_details += errors[i].short_description(); | 
 |       } | 
 |     } else { | 
 |       // Valid HTTPS or HTTPS with minor errors. | 
 |       base::string16 issuer_name( | 
 |           base::UTF8ToUTF16(ssl.certificate->issuer().GetDisplayName())); | 
 |       if (!issuer_name.empty()) { | 
 |         // Show the issuer name if it's available. | 
 |         // TODO(crbug.com/502470): Implement a certificate viewer instead. | 
 |         certificate_details.assign(l10n_util::GetStringFUTF16( | 
 |             IDS_IOS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY, issuer_name)); | 
 |       } | 
 |       if (ssl.content_status == web::SSLStatus::DISPLAYED_INSECURE_CONTENT) { | 
 |         // HTTPS with mixed content. | 
 |         icon_id = ICON_STATE_INFO; | 
 |         summary.assign( | 
 |             l10n_util::GetStringUTF16(IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY)); | 
 |         details.assign( | 
 |             l10n_util::GetStringUTF16(IDS_PAGE_INFO_MIXED_CONTENT_DETAILS)); | 
 |       } else { | 
 |         // Valid HTTPS | 
 |         icon_id = ICON_STATE_OK; | 
 |         summary.assign(l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURE_SUMMARY)); | 
 |         details.assign(l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURE_DETAILS)); | 
 |  | 
 |         DCHECK(!(ssl.cert_status & net::CERT_STATUS_IS_EV)) | 
 |             << "Extended Validation should be disabled"; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   base::string16 description; | 
 |   base::string16 spacer = base::UTF8ToUTF16("\n\n"); | 
 |  | 
 |   description.assign(summary); | 
 |   description += spacer; | 
 |   description += details; | 
 |  | 
 |   if (!certificate_details.empty()) { | 
 |     description += spacer; | 
 |     description += certificate_details; | 
 |   } | 
 |  | 
 |   sections_.push_back(SectionInfo(icon_id, hostname, description, | 
 |                                   SECTION_INFO_CONNECTION, | 
 |                                   BUTTON_SHOW_SECURITY_HELP)); | 
 | } | 
 |  | 
 | PageInfoModel::~PageInfoModel() {} | 
 |  | 
 | int PageInfoModel::GetSectionCount() { | 
 |   return sections_.size(); | 
 | } | 
 |  | 
 | PageInfoModel::SectionInfo PageInfoModel::GetSectionInfo(int index) { | 
 |   DCHECK(index < static_cast<int>(sections_.size())); | 
 |   return sections_[index]; | 
 | } | 
 |  | 
 | gfx::Image* PageInfoModel::GetIconImage(SectionStateIcon icon_id) { | 
 |   ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 
 |   switch (icon_id) { | 
 |     case ICON_NONE: | 
 |     case ICON_STATE_INTERNAL_PAGE: | 
 |       return nullptr; | 
 |     case ICON_STATE_OK: | 
 |       return &rb.GetNativeImageNamed(IDR_IOS_PAGEINFO_GOOD); | 
 |     case ICON_STATE_ERROR: | 
 |       return &rb.GetNativeImageNamed(IDR_IOS_PAGEINFO_BAD); | 
 |     case ICON_STATE_INFO: | 
 |       return &rb.GetNativeImageNamed(IDR_IOS_PAGEINFO_INFO); | 
 |     case ICON_STATE_OFFLINE_PAGE: | 
 |       return &rb.GetNativeImageNamed(IDR_IOS_OMNIBOX_OFFLINE); | 
 |   } | 
 | } | 
 |  | 
 | base::string16 PageInfoModel::GetCertificateLabel() const { | 
 |   return certificate_label_; | 
 | } | 
 |  | 
 | PageInfoModel::PageInfoModel() : observer_(NULL) {} |