// Copyright (c) 2010 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/page_info_model.h"

#include <string>

#include "base/command_line.h"
#include "base/i18n/time_formatting.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ssl/ssl_error_info.h"
#include "chrome/browser/ssl/ssl_manager.h"
#include "content/browser/cert_store.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "net/base/cert_status_flags.h"
#include "net/base/ssl_connection_status_flags.h"
#include "net/base/ssl_cipher_suite_names.h"
#include "net/base/x509_certificate.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"

PageInfoModel::PageInfoModel(Profile* profile,
                             const GURL& url,
                             const NavigationEntry::SSLStatus& ssl,
                             bool show_history,
                             PageInfoModelObserver* observer)
    : observer_(observer) {
  Init();

  SectionStateIcon icon_id = ICON_STATE_OK;
  string16 headline;
  string16 description;
  scoped_refptr<net::X509Certificate> cert;

  // Identity section.
  string16 subject_name(UTF8ToUTF16(url.host()));
  bool empty_subject_name = false;
  if (subject_name.empty()) {
    subject_name.assign(
        l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY));
    empty_subject_name = true;
  }

  // Some of what IsCertStatusError classifies as errors we want to show as
  // warnings instead.
  static const int cert_warnings =
      net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION |
      net::CERT_STATUS_NO_REVOCATION_MECHANISM;
  int status_with_warnings_removed = ssl.cert_status() & ~cert_warnings;

  if (ssl.cert_id() &&
      CertStore::GetInstance()->RetrieveCert(ssl.cert_id(), &cert) &&
      !net::IsCertStatusError(status_with_warnings_removed)) {
    // No error found so far, check cert_status warnings.
    int cert_status = ssl.cert_status();
    if (cert_status & cert_warnings) {
      string16 issuer_name(UTF8ToUTF16(cert->issuer().GetDisplayName()));
      if (issuer_name.empty()) {
        issuer_name.assign(l10n_util::GetStringUTF16(
            IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY));
      }
      description.assign(l10n_util::GetStringFUTF16(
          IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY, issuer_name));

      description += ASCIIToUTF16("\n\n");
      if (cert_status & net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION) {
        description += l10n_util::GetStringUTF16(
            IDS_PAGE_INFO_SECURITY_TAB_UNABLE_TO_CHECK_REVOCATION);
      } else if (cert_status & net::CERT_STATUS_NO_REVOCATION_MECHANISM) {
        description += l10n_util::GetStringUTF16(
            IDS_PAGE_INFO_SECURITY_TAB_NO_REVOCATION_MECHANISM);
      } else {
        NOTREACHED() << "Need to specify string for this warning";
      }
      icon_id = ICON_STATE_WARNING_MINOR;
    } else if ((ssl.cert_status() & net::CERT_STATUS_IS_EV) != 0) {
      // EV HTTPS page.
      DCHECK(!cert->subject().organization_names.empty());
      headline =
          l10n_util::GetStringFUTF16(IDS_PAGE_INFO_EV_IDENTITY_TITLE,
              UTF8ToUTF16(cert->subject().organization_names[0]),
              UTF8ToUTF16(url.host()));
      // An EV Cert is required to have a city (localityName) and country but
      // state is "if any".
      DCHECK(!cert->subject().locality_name.empty());
      DCHECK(!cert->subject().country_name.empty());
      string16 locality;
      if (!cert->subject().state_or_province_name.empty()) {
        locality = l10n_util::GetStringFUTF16(
            IDS_PAGEINFO_ADDRESS,
            UTF8ToUTF16(cert->subject().locality_name),
            UTF8ToUTF16(cert->subject().state_or_province_name),
            UTF8ToUTF16(cert->subject().country_name));
      } else {
        locality = l10n_util::GetStringFUTF16(
            IDS_PAGEINFO_PARTIAL_ADDRESS,
            UTF8ToUTF16(cert->subject().locality_name),
            UTF8ToUTF16(cert->subject().country_name));
      }
      DCHECK(!cert->subject().organization_names.empty());
      description.assign(l10n_util::GetStringFUTF16(
          IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY_EV,
          UTF8ToUTF16(cert->subject().organization_names[0]),
          locality,
          UTF8ToUTF16(cert->issuer().GetDisplayName())));
    } else if ((ssl.cert_status() & net::CERT_STATUS_IS_DNSSEC) != 0) {
      // DNSSEC authenticated page.
      if (empty_subject_name)
        headline.clear();  // Don't display any title.
      else
        headline.assign(subject_name);
      description.assign(l10n_util::GetStringFUTF16(
          IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY, UTF8ToUTF16("DNSSEC")));
    } else {
      // Non-EV OK HTTPS page.
      if (empty_subject_name)
        headline.clear();  // Don't display any title.
      else
        headline.assign(subject_name);
      string16 issuer_name(UTF8ToUTF16(cert->issuer().GetDisplayName()));
      if (issuer_name.empty()) {
        issuer_name.assign(l10n_util::GetStringUTF16(
            IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY));
      }
      description.assign(l10n_util::GetStringFUTF16(
          IDS_PAGE_INFO_SECURITY_TAB_SECURE_IDENTITY, issuer_name));
    }
  } else {
    // HTTP or HTTPS with errors (not warnings).
    description.assign(l10n_util::GetStringUTF16(
        IDS_PAGE_INFO_SECURITY_TAB_INSECURE_IDENTITY));
    icon_id = ssl.security_style() == SECURITY_STYLE_UNAUTHENTICATED ?
        ICON_STATE_WARNING_MAJOR : ICON_STATE_ERROR;

    const string16 bullet = UTF8ToUTF16("\n • ");
    std::vector<SSLErrorInfo> errors;
    SSLErrorInfo::GetErrorsForCertStatus(ssl.cert_id(), ssl.cert_status(),
                                         url, &errors);
    for (size_t i = 0; i < errors.size(); ++i) {
      description += bullet;
      description += errors[i].short_description();
    }

    if (ssl.cert_status() & net::CERT_STATUS_NON_UNIQUE_NAME) {
      description += ASCIIToUTF16("\n\n");
      description += l10n_util::GetStringUTF16(
          IDS_PAGE_INFO_SECURITY_TAB_NON_UNIQUE_NAME);
    }
  }
  sections_.push_back(SectionInfo(
      icon_id,
      headline,
      description,
      SECTION_INFO_IDENTITY));

  // Connection section.
  // We consider anything less than 80 bits encryption to be weak encryption.
  // TODO(wtc): Bug 1198735: report mixed/unsafe content for unencrypted and
  // weakly encrypted connections.
  icon_id = ICON_STATE_OK;
  headline.clear();
  description.clear();
  if (!ssl.cert_id()) {
    // Not HTTPS.
    DCHECK_EQ(ssl.security_style(), SECURITY_STYLE_UNAUTHENTICATED);
    icon_id = ssl.security_style() == SECURITY_STYLE_UNAUTHENTICATED ?
        ICON_STATE_WARNING_MAJOR : ICON_STATE_ERROR;
    description.assign(l10n_util::GetStringFUTF16(
        IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT,
        subject_name));
  } else if (ssl.security_bits() < 0) {
    // Security strength is unknown.  Say nothing.
    icon_id = ICON_STATE_ERROR;
  } else if (ssl.security_bits() == 0) {
    DCHECK_NE(ssl.security_style(), SECURITY_STYLE_UNAUTHENTICATED);
    icon_id = ICON_STATE_ERROR;
    description.assign(l10n_util::GetStringFUTF16(
        IDS_PAGE_INFO_SECURITY_TAB_NOT_ENCRYPTED_CONNECTION_TEXT,
        subject_name));
  } else if (ssl.security_bits() < 80) {
    icon_id = ICON_STATE_ERROR;
    description.assign(l10n_util::GetStringFUTF16(
        IDS_PAGE_INFO_SECURITY_TAB_WEAK_ENCRYPTION_CONNECTION_TEXT,
        subject_name));
  } else {
    description.assign(l10n_util::GetStringFUTF16(
        IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_CONNECTION_TEXT,
        subject_name,
        base::IntToString16(ssl.security_bits())));
    if (ssl.displayed_insecure_content() || ssl.ran_insecure_content()) {
      icon_id = ssl.ran_insecure_content() ?
          ICON_STATE_ERROR : ICON_STATE_WARNING_MINOR;
      description.assign(l10n_util::GetStringFUTF16(
          IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_SENTENCE_LINK,
          description,
          l10n_util::GetStringUTF16(ssl.ran_insecure_content() ?
              IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_ERROR :
              IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTED_INSECURE_CONTENT_WARNING)));
    }
  }

  uint16 cipher_suite =
      net::SSLConnectionStatusToCipherSuite(ssl.connection_status());
  if (ssl.security_bits() > 0 && cipher_suite) {
    int ssl_version =
        net::SSLConnectionStatusToVersion(ssl.connection_status());
    const char* ssl_version_str;
    net::SSLVersionToString(&ssl_version_str, ssl_version);
    description += ASCIIToUTF16("\n\n");
    description += l10n_util::GetStringFUTF16(
        IDS_PAGE_INFO_SECURITY_TAB_SSL_VERSION,
        ASCIIToUTF16(ssl_version_str));

    bool did_fallback = (ssl.connection_status() &
                         net::SSL_CONNECTION_SSL3_FALLBACK) != 0;
    bool no_renegotiation =
        (ssl.connection_status() &
        net::SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION) != 0;
    const char *key_exchange, *cipher, *mac;
    net::SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, cipher_suite);

    description += ASCIIToUTF16("\n\n");
    description += l10n_util::GetStringFUTF16(
        IDS_PAGE_INFO_SECURITY_TAB_ENCRYPTION_DETAILS,
        ASCIIToUTF16(cipher), ASCIIToUTF16(mac), ASCIIToUTF16(key_exchange));

    description += ASCIIToUTF16("\n\n");
    uint8 compression_id =
        net::SSLConnectionStatusToCompression(ssl.connection_status());
    if (compression_id) {
      const char* compression;
      net::SSLCompressionToString(&compression, compression_id);
      description += l10n_util::GetStringFUTF16(
          IDS_PAGE_INFO_SECURITY_TAB_COMPRESSION_DETAILS,
          ASCIIToUTF16(compression));
    } else {
      description += l10n_util::GetStringUTF16(
          IDS_PAGE_INFO_SECURITY_TAB_NO_COMPRESSION);
    }

    if (did_fallback) {
      // For now, only SSLv3 fallback will trigger a warning icon.
      if (icon_id < ICON_STATE_WARNING_MINOR)
        icon_id = ICON_STATE_WARNING_MINOR;
      description += ASCIIToUTF16("\n\n");
      description += l10n_util::GetStringUTF16(
          IDS_PAGE_INFO_SECURITY_TAB_FALLBACK_MESSAGE);
    }
    if (no_renegotiation) {
      description += ASCIIToUTF16("\n\n");
      description += l10n_util::GetStringUTF16(
          IDS_PAGE_INFO_SECURITY_TAB_RENEGOTIATION_MESSAGE);
    }
  }

  if (!description.empty()) {
    sections_.push_back(SectionInfo(
        icon_id,
        headline,
        description,
        SECTION_INFO_CONNECTION));
  }

  // Request the number of visits.
  HistoryService* history = profile->GetHistoryService(
      Profile::EXPLICIT_ACCESS);
  if (show_history && history) {
    history->GetVisitCountToHost(
        url,
        &request_consumer_,
        NewCallback(this, &PageInfoModel::OnGotVisitCountToHost));
  }
}

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) {
  if (icon_id == ICON_NONE)
    return NULL;
  // The bubble uses new, various icons.
  return icons_[icon_id];
}

void PageInfoModel::OnGotVisitCountToHost(HistoryService::Handle handle,
                                          bool found_visits,
                                          int count,
                                          base::Time first_visit) {
  if (!found_visits) {
    // This indicates an error, such as the page wasn't http/https; do nothing.
    return;
  }

  bool visited_before_today = false;
  if (count) {
    base::Time today = base::Time::Now().LocalMidnight();
    base::Time first_visit_midnight = first_visit.LocalMidnight();
    visited_before_today = (first_visit_midnight < today);
  }

  string16 headline = l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_INFO_TITLE);

  if (!visited_before_today) {
    sections_.push_back(SectionInfo(
        ICON_STATE_WARNING_MAJOR,
        headline,
        l10n_util::GetStringUTF16(
            IDS_PAGE_INFO_SECURITY_TAB_FIRST_VISITED_TODAY),
        SECTION_INFO_FIRST_VISIT));
  } else {
    sections_.push_back(SectionInfo(
        ICON_STATE_INFO,
        headline,
        l10n_util::GetStringFUTF16(
            IDS_PAGE_INFO_SECURITY_TAB_VISITED_BEFORE_TODAY,
            base::TimeFormatShortDate(first_visit)),
        SECTION_INFO_FIRST_VISIT));
  }
  observer_->ModelChanged();
}

PageInfoModel::PageInfoModel() : observer_(NULL) {
  Init();
}

void PageInfoModel::Init() {
  // Loads the icons into the vector. The order must match the SectionStateIcon
  // enum.
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  icons_.push_back(&rb.GetNativeImageNamed(IDR_PAGEINFO_GOOD));
  icons_.push_back(&rb.GetNativeImageNamed(IDR_PAGEINFO_WARNING_MINOR));
  icons_.push_back(&rb.GetNativeImageNamed(IDR_PAGEINFO_WARNING_MAJOR));
  icons_.push_back(&rb.GetNativeImageNamed(IDR_PAGEINFO_BAD));
  icons_.push_back(&rb.GetNativeImageNamed(IDR_PAGEINFO_INFO));
}
