// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ssl/https_upgrades_navigation_throttle.h"

#include <utility>

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ssl/https_first_mode_settings_tracker.h"
#include "chrome/browser/ssl/https_only_mode_tab_helper.h"
#include "chrome/browser/ssl/https_upgrades_navigation_throttle.h"
#include "chrome/browser/ssl/https_upgrades_util.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/security_interstitials/content/security_interstitial_tab_helper.h"
#include "components/security_interstitials/content/stateful_ssl_host_state_delegate.h"
#include "components/security_interstitials/core/features.h"
#include "components/security_interstitials/core/https_only_mode_metrics.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/web_contents.h"
#include "net/base/net_errors.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "ui/base/page_transition_types.h"

using security_interstitials::https_only_mode::Event;

namespace {

// Time that the throttle will wait before canceling the upgraded navigation and
// showing the HTTPS-First Mode interstitial.
base::TimeDelta g_fallback_delay = base::Seconds(3);

// TODO(crbug.com/351990829): Consider setting the page title and favicon to be
// more like interstitials.
inline constexpr char kBlankPageHtml[] = "<html></html>";

}  // namespace

// static
void HttpsUpgradesNavigationThrottle::MaybeCreateAndAdd(
    content::NavigationThrottleRegistry& registry,
    std::unique_ptr<SecurityBlockingPageFactory> blocking_page_factory,
    Profile* profile) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // HTTPS-First Mode is only relevant for primary main-frame HTTP(S)
  // navigations.
  content::NavigationHandle& handle = registry.GetNavigationHandle();
  if (!registry.IsHTTPOrHTTPS() || !handle.IsInPrimaryMainFrame() ||
      handle.IsSameDocument()) {
    return;
  }

  security_interstitials::https_only_mode::HttpInterstitialState
      interstitial_state =
          ComputeInterstitialState(handle.GetWebContents(), handle.GetURL());

  HttpsFirstModeService* hfm_service =
      HttpsFirstModeServiceFactory::GetForProfile(profile);
  if (hfm_service) {
    // Can be null in some cases, e.g. when using Ash sign-in profile.
    hfm_service->IncrementRecentNavigationCount();
  }

  bool https_upgrades_enabled =
      interstitial_state.enabled_by_pref ||
      base::FeatureList::IsEnabled(features::kHttpsUpgrades);
  if (!https_upgrades_enabled) {
    return;
  }

  // Ensure that the HttpsOnlyModeTabHelper has been created (this does nothing
  // if it has already been created for the WebContents). There are cases where
  // the tab helper won't get created by the initialization in
  // chrome/browser/ui/tab_helpers.cc but the criteria for adding the throttle
  // are still met (see crbug.com/1233889 for one example).
  HttpsOnlyModeTabHelper::CreateForWebContents(handle.GetWebContents());

  registry.AddThrottle(std::make_unique<HttpsUpgradesNavigationThrottle>(
      registry, profile, std::move(blocking_page_factory), interstitial_state));
}

HttpsUpgradesNavigationThrottle::HttpsUpgradesNavigationThrottle(
    content::NavigationThrottleRegistry& registry,
    Profile* profile,
    std::unique_ptr<SecurityBlockingPageFactory> blocking_page_factory,
    security_interstitials::https_only_mode::HttpInterstitialState
        interstitial_state)
    : content::NavigationThrottle(registry),
      profile_(profile),
      blocking_page_factory_(std::move(blocking_page_factory)),
      interstitial_state_(interstitial_state) {}

HttpsUpgradesNavigationThrottle::~HttpsUpgradesNavigationThrottle() = default;

content::NavigationThrottle::ThrottleCheckResult
HttpsUpgradesNavigationThrottle::WillStartRequest() {
  // If the navigation is fallback to HTTP, trigger the HTTP interstitial (if
  // enabled). The interceptor creates a redirect for the fallback navigation,
  // which will trigger MaybeCreateLoader() in the interceptor for the redirect
  // but *doesn't* trigger WillStartRequest() because it's all part of the same
  // request. Here, we skip directly to showing the HTTP interstitial if this
  // is:
  //   (1) a back/forward navigation, and
  //   (2) the URL already failed upgrades before.
  // This lets us avoid triggering the Interceptor during a back/forward
  // navigation (which breaks history state) and acts like the browser
  // "remembering" the state of the tab as being on the interstitial for that
  // URL.
  //
  // Other cases for starting a navigation to a URL that previously failed
  // to be upgraded should go through the full upgrade flow -- better to assume
  // that something may have changed in the time since. For example: a user
  // reloading the tab showing the interstitial should re-try the upgrade.
  auto* handle = navigation_handle();
  auto* contents = handle->GetWebContents();
  auto* tab_helper = HttpsOnlyModeTabHelper::FromWebContents(contents);

  if ((handle->GetPageTransition() & ui::PAGE_TRANSITION_FORWARD_BACK &&
       tab_helper->has_failed_upgrade(handle->GetURL())) &&
      !handle->GetURL().SchemeIsCryptographic()) {
    if (IsInterstitialEnabled(interstitial_state_)) {
      security_interstitials::https_only_mode::RecordInterstitialReason(
          interstitial_state_);

      // Mark this as a fallback HTTP navigation and trigger the interstitial.
      tab_helper->set_is_navigation_fallback(true);

      if (base::FeatureList::IsEnabled(
              security_interstitials::features::kHttpsFirstDialogUi)) {
        // New dialog UI.
        // Rewrite the response to a blank page. DidFinishNavigation will
        // show the ABH dialog on top of this blank page.
        return {content::NavigationThrottle::CANCEL, net::ERR_BLOCKED_BY_CLIENT,
                kBlankPageHtml};
      } else {
        // Old full-page interstitial UI.
        ukm::SourceId source_id =
            ukm::ConvertToSourceId(navigation_handle()->GetNavigationId(),
                                   ukm::SourceIdType::NAVIGATION_ID);
        std::unique_ptr<security_interstitials::HttpsOnlyModeBlockingPage>
            blocking_page =
                blocking_page_factory_->CreateHttpsOnlyModeBlockingPage(
                    contents, handle->GetURL(), interstitial_state_,
                    /*url_type_param=*/std::nullopt,
                    base::BindRepeating(&RecordHttpsFirstModeUKM, source_id));
        std::string interstitial_html = blocking_page->GetHTMLContents();
        security_interstitials::SecurityInterstitialTabHelper::
            AssociateBlockingPage(handle, std::move(blocking_page));
        return content::NavigationThrottle::ThrottleCheckResult(
            content::NavigationThrottle::CANCEL, net::ERR_BLOCKED_BY_CLIENT,
            std::move(interstitial_html));
      }
    }

    // Otherwise, just record metrics and continue.
    // TODO(crbug.com/40904694): Record a separate histogram for Site Engagement
    // heuristic.
  }

  // TODO(crbug.com/40064769): There are some cases where the navigation may
  // "restart", such as if we encounter an exempted transient network error on
  // the upgraded HTTPS URL, show a net error page, and then reload the tab. In
  // these cases the navigation will proceed with the upgrade/fallback logic,
  // but the navigation timeout will no longer be set. Currently, re-starting
  // the timer here would trigger a DCHECK in NavigationRequest.

  // Navigation is HTTPS or an initial HTTP navigation (which will get
  // upgraded by the interceptor). Fallback HTTP navigations are handled in
  // WillRedirectRequest().
  return content::NavigationThrottle::ThrottleAction::PROCEED;
}

content::NavigationThrottle::ThrottleCheckResult
HttpsUpgradesNavigationThrottle::WillFailRequest() {
  // Fallback to HTTP on navigation failure is handled by
  // HttpsUpgradesInterceptor::MaybeCreateLoaderForResponse().
  return content::NavigationThrottle::PROCEED;
}

content::NavigationThrottle::ThrottleCheckResult
HttpsUpgradesNavigationThrottle::WillRedirectRequest() {
  // If the navigation is doing a fallback redirect to HTTP, trigger the HTTP
  // interstitial (if enabled). The interceptor creates a redirect for the
  // fallback navigation, which will trigger MaybeCreateLoader() in the
  // interceptor for the redirect but *doesn't* trigger WillStartRequest()
  // because it's all part of the same request.
  auto* handle = navigation_handle();
  auto* contents = handle->GetWebContents();
  auto* tab_helper = HttpsOnlyModeTabHelper::FromWebContents(contents);

  // Slow loading fallback URLs should be handled by the net stack.
  if (tab_helper->is_navigation_fallback()) {
    handle->CancelNavigationTimeout();
  }

  ukm::SourceId source_id = ukm::ConvertToSourceId(
      navigation_handle()->GetNavigationId(), ukm::SourceIdType::NAVIGATION_ID);
  if (tab_helper->is_navigation_fallback() &&
      !handle->GetURL().SchemeIsCryptographic() &&
      IsInterstitialEnabled(interstitial_state_)) {
    security_interstitials::https_only_mode::RecordInterstitialReason(
        interstitial_state_);

    if (base::FeatureList::IsEnabled(
            security_interstitials::features::kHttpsFirstDialogUi)) {
      // New dialog UI.
      // Rewrite the response to a blank page and cancel the navigation.
      // HttpsOnlyModeTabHelper::DidFinishNavigation() will
      // show the ABH dialog on top of this blank page.
      return {content::NavigationThrottle::CANCEL, net::ERR_BLOCKED_BY_CLIENT,
              kBlankPageHtml};
    } else {
      std::unique_ptr<security_interstitials::HttpsOnlyModeBlockingPage>
          blocking_page =
              blocking_page_factory_->CreateHttpsOnlyModeBlockingPage(
                  contents, handle->GetURL(), interstitial_state_,
                  /*url_type_param=*/std::nullopt,
                  base::BindRepeating(&RecordHttpsFirstModeUKM, source_id));
      std::string interstitial_html = blocking_page->GetHTMLContents();
      security_interstitials::SecurityInterstitialTabHelper::
          AssociateBlockingPage(handle, std::move(blocking_page));
      return content::NavigationThrottle::ThrottleCheckResult(
          content::NavigationThrottle::CANCEL, net::ERR_BLOCKED_BY_CLIENT,
          std::move(interstitial_html));
    }
  }

  // Otherwise, just record metrics and continue.
  // TODO(crbug.com/40904694): Record a separate histogram for Site Engagement
  // heuristic.

  // If the navigation was upgraded by the Interceptor, then the Throttle's
  // WillRedirectRequest() will get triggered by the artificial redirect to
  // HTTPS. The HTTPS upgrade will always happen after the Throttle's
  // WillStartRequest() (which only checks for fallback HTTP), so tracking
  // upgraded requests is deferred to WillRedirectRequest() here. Which
  // navigations to upgrade is determined by the Interceptor, not the Throttle.
  //
  // The navigation may get upgraded at various points during redirects:
  //   1. The Interceptor serves an artificial redirect to HTTPS if the
  //      navigation is upgraded. This means the Throttle will see the upgraded
  //      navigation state for the first time here in WillRedirectRequest().
  //   2. HTTPS->HTTP downgrades can occur later in the lifecycle of a
  //      navigation, and will also result in the Interceptor serving an
  //      artificial redirect to upgrade the navigation.
  //
  // The Interceptor logs the URLs that it sees and triggers fallback if it
  // encounters a redirect loop. Any cases that might not be caught by the
  // Interceptor should result in net::ERR_TOO_MANY_REDIRECTS, but in general
  // redirect loops should hit the cache and not cost too much. If they go too
  // long, the fallback timer will kick in. ERR_TOO_MANY_REDIRECTS should result
  // in the request failing and triggering fallback.
  if (tab_helper->is_navigation_upgraded()) {
    // Check if the timer is already started, as there may be additional
    // redirects on the navigation after the artificial upgrade redirect.
    bool timer_started =
        navigation_handle()->SetNavigationTimeout(g_fallback_delay);
    if (timer_started) {
      RecordHttpsFirstModeNavigation(Event::kUpgradeAttempted,
                                     interstitial_state_);
    }
  }

  return content::NavigationThrottle::PROCEED;
}

content::NavigationThrottle::ThrottleCheckResult
HttpsUpgradesNavigationThrottle::WillProcessResponse() {
  // Clear the status for this navigation as it will successfully commit.
  auto* tab_helper = HttpsOnlyModeTabHelper::FromWebContents(
      navigation_handle()->GetWebContents());
  if (tab_helper->is_navigation_upgraded()) {
    RecordHttpsFirstModeNavigation(Event::kUpgradeSucceeded,
                                   interstitial_state_);
    tab_helper->set_is_navigation_upgraded(false);
  }

  // Clear the fallback flag, if set.
  tab_helper->set_is_navigation_fallback(false);

  return content::NavigationThrottle::PROCEED;
}

const char* HttpsUpgradesNavigationThrottle::GetNameForLogging() {
  return "HttpsUpgradesNavigationThrottle";
}

// static
void HttpsUpgradesNavigationThrottle::set_timeout_for_testing(
    base::TimeDelta timeout) {
  g_fallback_delay = timeout;
}
