blob: 5ffd3556aa839f1798ea939fb7489590769cd2af [file] [log] [blame]
// 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/page_info/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/page_info/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/security/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,
bool is_offline_page,
PageInfoModelObserver* observer)
: observer_(observer) {
if (is_offline_page) {
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));
return;
}
if (url.SchemeIs(kChromeUIScheme)) {
base::string16 spec(base::UTF8ToUTF16(url.spec()));
sections_.push_back(
SectionInfo(ICON_STATE_INTERNAL_PAGE, spec,
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) {
ui::ResourceBundle& rb = ui::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) {}