// Copyright 2013 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/renderer/net/net_error_helper_core.h"

#include <stddef.h>

#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/i18n/rtl.h"
#include "base/json/json_reader.h"
#include "base/json/json_value_converter.h"
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/common/chrome_features.h"
#include "components/error_page/common/error_page_params.h"
#include "components/strings/grit/components_strings.h"
#include "components/url_formatter/url_formatter.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/renderer/render_thread.h"
#include "net/base/escape.h"
#include "net/base/net_errors.h"
#include "third_party/blink/public/platform/web_string.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
#include "url/url_constants.h"

using OfflineContentOnNetErrorFeatureState =
    error_page::LocalizedError::OfflineContentOnNetErrorFeatureState;

namespace {

// |NetErrorNavigationCorrectionTypes| enum id for Web search query.
// Other correction types uses the |kCorrectionResourceTable| array order.
const int kWebSearchQueryUMAId = 100;

// Number of URL correction suggestions to display.
const int kMaxUrlCorrectionsToDisplay = 1;

struct CorrectionTypeToResourceTable {
  int resource_id;
  const char* correction_type;
};

// Note: Ordering should be the same as |NetErrorNavigationCorrectionTypes| enum
// in histograms.xml.
const CorrectionTypeToResourceTable kCorrectionResourceTable[] = {
    {IDS_ERRORPAGES_SUGGESTION_VISIT_GOOGLE_CACHE, "cachedPage"},
    // "reloadPage" is has special handling.
    {IDS_ERRORPAGES_SUGGESTION_CORRECTED_URL, "urlCorrection"},
    {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "siteDomain"},
    {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "host"},
    {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "sitemap"},
    {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "pathParentFolder"},
    // "siteSearchQuery" is not yet supported.
    // TODO(mmenke):  Figure out what format "siteSearchQuery" uses for its
    // suggestions.
    // "webSearchQuery" has special handling.
    {IDS_ERRORPAGES_SUGGESTION_ALTERNATE_URL, "contentOverlap"},
    {IDS_ERRORPAGES_SUGGESTION_CORRECTED_URL, "emphasizedUrlCorrection"},
};

struct NavigationCorrection {
  NavigationCorrection() : is_porn(false), is_soft_porn(false) {}

  static void RegisterJSONConverter(
      base::JSONValueConverter<NavigationCorrection>* converter) {
    converter->RegisterStringField("correctionType",
                                   &NavigationCorrection::correction_type);
    converter->RegisterStringField("urlCorrection",
                                   &NavigationCorrection::url_correction);
    converter->RegisterStringField("clickType",
                                   &NavigationCorrection::click_type);
    converter->RegisterStringField("clickData",
                                   &NavigationCorrection::click_data);
    converter->RegisterBoolField("isPorn", &NavigationCorrection::is_porn);
    converter->RegisterBoolField("isSoftPorn",
                                 &NavigationCorrection::is_soft_porn);
  }

  std::string correction_type;
  std::string url_correction;
  std::string click_type;
  std::string click_data;
  bool is_porn;
  bool is_soft_porn;
};

struct NavigationCorrectionResponse {
  std::string event_id;
  std::string fingerprint;
  std::vector<std::unique_ptr<NavigationCorrection>> corrections;

  static void RegisterJSONConverter(
      base::JSONValueConverter<NavigationCorrectionResponse>* converter) {
    converter->RegisterStringField("result.eventId",
                                   &NavigationCorrectionResponse::event_id);
    converter->RegisterStringField("result.fingerprint",
                                   &NavigationCorrectionResponse::fingerprint);
    converter->RegisterRepeatedMessage(
        "result.UrlCorrections", &NavigationCorrectionResponse::corrections);
  }
};

base::TimeDelta GetAutoReloadTime(size_t reload_count) {
  static const int kDelaysMs[] = {0,      5000,   30000,  60000,
                                  300000, 600000, 1800000};
  if (reload_count >= base::size(kDelaysMs))
    reload_count = base::size(kDelaysMs) - 1;
  return base::TimeDelta::FromMilliseconds(kDelaysMs[reload_count]);
}

// Returns whether |error| is a DNS-related error (and therefore whether
// the tab helper should start a DNS probe after receiving it).
bool IsNetDnsError(const error_page::Error& error) {
  return error.domain() == error_page::Error::kNetErrorDomain &&
         net::IsDnsError(error.reason());
}

GURL SanitizeURL(const GURL& url) {
  GURL::Replacements remove_params;
  remove_params.ClearUsername();
  remove_params.ClearPassword();
  remove_params.ClearQuery();
  remove_params.ClearRef();
  return url.ReplaceComponents(remove_params);
}

// Sanitizes and formats a URL for upload to the error correction service.
std::string PrepareUrlForUpload(const GURL& url) {
  // TODO(yuusuke): Change to url_formatter::FormatUrl when Link Doctor becomes
  // unicode-capable.
  std::string spec_to_send = SanitizeURL(url).spec();

  // Notify navigation correction service of the url truncation by sending of
  // "?" at the end.
  if (url.has_query())
    spec_to_send.append("?");
  return spec_to_send;
}

// Given an Error, returns true if the FixURL service should be used
// for that error.  Also sets |error_param| to the string that should be sent to
// the FixURL service to identify the error type.
bool ShouldUseFixUrlServiceForError(const error_page::Error& error,
                                    std::string* error_param) {
  error_param->clear();

  // Don't use the correction service for HTTPS (for privacy reasons).
  GURL unreachable_url(error.url());
  if (GURL(unreachable_url).SchemeIsCryptographic())
    return false;

  const auto& domain = error.domain();
  if (domain == error_page::Error::kHttpErrorDomain && error.reason() == 404) {
    *error_param = "http404";
    return true;
  }
  if (IsNetDnsError(error)) {
    *error_param = "dnserror";
    return true;
  }
  if (domain == error_page::Error::kNetErrorDomain &&
      (error.reason() == net::ERR_CONNECTION_FAILED ||
       error.reason() == net::ERR_CONNECTION_REFUSED ||
       error.reason() == net::ERR_ADDRESS_UNREACHABLE ||
       error.reason() == net::ERR_CONNECTION_TIMED_OUT)) {
    *error_param = "connectionFailure";
    return true;
  }
  return false;
}

// Creates a request body for use with the fixurl service.  Sets parameters
// shared by all types of requests to the service.  |correction_params| must
// contain the parameters specific to the actual request type.
std::string CreateRequestBody(
    const std::string& method,
    const std::string& error_param,
    const NetErrorHelperCore::NavigationCorrectionParams& correction_params,
    std::unique_ptr<base::DictionaryValue> params_dict) {
  // Set params common to all request types.
  params_dict->SetString("key", correction_params.api_key);
  params_dict->SetString("clientName", "chrome");
  params_dict->SetString("error", error_param);

  if (!correction_params.language.empty())
    params_dict->SetString("language", correction_params.language);

  if (!correction_params.country_code.empty())
    params_dict->SetString("originCountry", correction_params.country_code);

  base::DictionaryValue request_dict;
  request_dict.SetString("method", method);
  request_dict.SetString("apiVersion", "v1");
  request_dict.Set("params", std::move(params_dict));

  std::string request_body;
  bool success = base::JSONWriter::Write(request_dict, &request_body);
  DCHECK(success);
  return request_body;
}

// If URL correction information should be retrieved remotely for a main frame
// load that failed with |error|, returns true and sets
// |correction_request_body| to be the body for the correction request.
std::string CreateFixUrlRequestBody(
    const error_page::Error& error,
    const NetErrorHelperCore::NavigationCorrectionParams& correction_params) {
  std::string error_param;
  bool result = ShouldUseFixUrlServiceForError(error, &error_param);
  DCHECK(result);

  // TODO(mmenke):  Investigate open sourcing the relevant protocol buffers and
  //                using those directly instead.
  std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());
  params->SetString("urlQuery", PrepareUrlForUpload(error.url()));
  return CreateRequestBody("linkdoctor.fixurl.fixurl", error_param,
                           correction_params, std::move(params));
}

std::string CreateClickTrackingUrlRequestBody(
    const error_page::Error& error,
    const NetErrorHelperCore::NavigationCorrectionParams& correction_params,
    const NavigationCorrectionResponse& response,
    const NavigationCorrection& correction) {
  std::string error_param;
  bool result = ShouldUseFixUrlServiceForError(error, &error_param);
  DCHECK(result);

  std::unique_ptr<base::DictionaryValue> params(new base::DictionaryValue());

  params->SetString("originalUrlQuery", PrepareUrlForUpload(error.url()));

  params->SetString("clickedUrlCorrection", correction.url_correction);
  params->SetString("clickType", correction.click_type);
  params->SetString("clickData", correction.click_data);

  params->SetString("eventId", response.event_id);
  params->SetString("fingerprint", response.fingerprint);

  return CreateRequestBody("linkdoctor.fixurl.clicktracking", error_param,
                           correction_params, std::move(params));
}

base::string16 FormatURLForDisplay(const GURL& url, bool is_rtl) {
  // Translate punycode into UTF8, unescape UTF8 URLs.
  base::string16 url_for_display(url_formatter::FormatUrl(
      url, url_formatter::kFormatUrlOmitNothing, net::UnescapeRule::NORMAL,
      nullptr, nullptr, nullptr));
  // URLs are always LTR.
  if (is_rtl)
    base::i18n::WrapStringWithLTRFormatting(&url_for_display);
  return url_for_display;
}

std::unique_ptr<NavigationCorrectionResponse> ParseNavigationCorrectionResponse(
    const std::string raw_response) {
  // TODO(mmenke):  Open source related protocol buffers and use them directly.
  std::unique_ptr<base::Value> parsed = base::JSONReader::Read(raw_response);
  std::unique_ptr<NavigationCorrectionResponse> response(
      new NavigationCorrectionResponse());
  base::JSONValueConverter<NavigationCorrectionResponse> converter;
  if (!parsed || !converter.Convert(*parsed, response.get()))
    response.reset();
  return response;
}

void LogCorrectionTypeShown(int type_id) {
  UMA_HISTOGRAM_ENUMERATION(
      "Net.ErrorPageCounts.NavigationCorrectionLinksShown", type_id,
      kWebSearchQueryUMAId + 1);
}

std::unique_ptr<error_page::ErrorPageParams> CreateErrorPageParams(
    const NavigationCorrectionResponse& response,
    const error_page::Error& error,
    const NetErrorHelperCore::NavigationCorrectionParams& correction_params,
    bool is_rtl) {
  // Version of URL for display in suggestions.  It has to be sanitized first
  // because any received suggestions will be relative to the sanitized URL.
  base::string16 original_url_for_display =
      FormatURLForDisplay(SanitizeURL(GURL(error.url())), is_rtl);

  std::unique_ptr<error_page::ErrorPageParams> params(
      new error_page::ErrorPageParams());
  params->override_suggestions.reset(new base::ListValue());
  std::unique_ptr<base::ListValue> parsed_corrections(new base::ListValue());
  for (auto it = response.corrections.begin(); it != response.corrections.end();
       ++it) {
    // Doesn't seem like a good idea to show these.
    if ((*it)->is_porn || (*it)->is_soft_porn)
      continue;

    int tracking_id = it - response.corrections.begin();

    if ((*it)->correction_type == "reloadPage") {
      params->suggest_reload = true;
      params->reload_tracking_id = tracking_id;
      continue;
    }

    if ((*it)->correction_type == "webSearchQuery") {
      // If there are multiple searches suggested, use the first suggestion.
      if (params->search_terms.empty()) {
        params->search_url = correction_params.search_url;
        params->search_terms = (*it)->url_correction;
        params->search_tracking_id = tracking_id;
        LogCorrectionTypeShown(kWebSearchQueryUMAId);
      }
      continue;
    }

    // Allow reload page and web search query to be empty strings, but not
    // links.
    if ((*it)->url_correction.empty() ||
        (params->override_suggestions->GetSize() >=
         kMaxUrlCorrectionsToDisplay)) {
      continue;
    }

    size_t correction_index;
    for (correction_index = 0;
         correction_index < base::size(kCorrectionResourceTable);
         ++correction_index) {
      if ((*it)->correction_type !=
          kCorrectionResourceTable[correction_index].correction_type) {
        continue;
      }
      std::unique_ptr<base::DictionaryValue> suggest(
          new base::DictionaryValue());
      suggest->SetString(
          "summary",
          l10n_util::GetStringUTF16(
              kCorrectionResourceTable[correction_index].resource_id));
      suggest->SetString("urlCorrection", (*it)->url_correction);
      suggest->SetString(
          "urlCorrectionForDisplay",
          FormatURLForDisplay(GURL((*it)->url_correction), is_rtl));
      suggest->SetString("originalUrlForDisplay", original_url_for_display);
      suggest->SetInteger("trackingId", tracking_id);
      suggest->SetInteger("type", static_cast<int>(correction_index));

      params->override_suggestions->Append(std::move(suggest));
      LogCorrectionTypeShown(static_cast<int>(correction_index));
      break;
    }
  }

  if (params->override_suggestions->empty() && !params->search_url.is_valid())
    params.reset();
  return params;
}

void ReportAutoReloadSuccess(const error_page::Error& error, size_t count) {
  if (error.domain() != error_page::Error::kNetErrorDomain)
    return;
  base::UmaHistogramSparse("Net.AutoReload.ErrorAtSuccess", -error.reason());
  UMA_HISTOGRAM_COUNTS_1M("Net.AutoReload.CountAtSuccess",
                          static_cast<base::HistogramBase::Sample>(count));
  if (count == 1) {
    base::UmaHistogramSparse("Net.AutoReload.ErrorAtFirstSuccess",
                             -error.reason());
  }
}

void ReportAutoReloadFailure(const error_page::Error& error, size_t count) {
  if (error.domain() != error_page::Error::kNetErrorDomain)
    return;
  base::UmaHistogramSparse("Net.AutoReload.ErrorAtStop", -error.reason());
  UMA_HISTOGRAM_COUNTS_1M("Net.AutoReload.CountAtStop",
                          static_cast<base::HistogramBase::Sample>(count));
}

// Tracks navigation correction service usage in UMA to enable more in depth
// analysis.
void TrackClickUMA(std::string type_id) {
  // Web search suggestion isn't in |kCorrectionResourceTable| array.
  if (type_id == "webSearchQuery") {
    UMA_HISTOGRAM_ENUMERATION(
        "Net.ErrorPageCounts.NavigationCorrectionLinksUsed",
        kWebSearchQueryUMAId, kWebSearchQueryUMAId + 1);
    return;
  }

  size_t correction_index;
  for (correction_index = 0;
       correction_index < base::size(kCorrectionResourceTable);
       ++correction_index) {
    if (kCorrectionResourceTable[correction_index].correction_type == type_id) {
      UMA_HISTOGRAM_ENUMERATION(
          "Net.ErrorPageCounts.NavigationCorrectionLinksUsed",
          static_cast<int>(correction_index), kWebSearchQueryUMAId + 1);
      break;
    }
  }
}

}  // namespace

struct NetErrorHelperCore::ErrorPageInfo {
  ErrorPageInfo(error_page::Error error,
                bool was_failed_post,
                bool was_ignoring_cache)
      : error(error),
        was_failed_post(was_failed_post),
        was_ignoring_cache(was_ignoring_cache),
        needs_dns_updates(false),
        needs_load_navigation_corrections(false),
        reload_button_in_page(false),
        show_saved_copy_button_in_page(false),
        show_cached_copy_button_in_page(false),
        download_button_in_page(false),
        is_finished_loading(false),
        auto_reload_triggered(false),
        offline_content_feature_state(
            OfflineContentOnNetErrorFeatureState::kDisabled),
        auto_fetch_allowed(false) {}

  // Information about the failed page load.
  error_page::Error error;
  bool was_failed_post;
  bool was_ignoring_cache;

  // Information about the status of the error page.

  // True if a page is a DNS error page and has not yet received a final DNS
  // probe status.
  bool needs_dns_updates;

  // True if a blank page was loaded, and navigation corrections need to be
  // loaded to generate the real error page.
  bool needs_load_navigation_corrections;

  // Navigation correction service paramers, which will be used in response to
  // certain types of network errors.  They are all stored here in case they
  // change over the course of displaying the error page.
  std::unique_ptr<NetErrorHelperCore::NavigationCorrectionParams>
      navigation_correction_params;

  std::unique_ptr<NavigationCorrectionResponse> navigation_correction_response;

  // All the navigation corrections that have been clicked, for tracking
  // purposes.
  std::set<int> clicked_corrections;

  // Track if specific buttons are included in an error page, for statistics.
  bool reload_button_in_page;
  bool show_saved_copy_button_in_page;
  bool show_cached_copy_button_in_page;
  bool download_button_in_page;

  // True if a page has completed loading, at which point it can receive
  // updates.
  bool is_finished_loading;

  // True if the auto-reload timer has fired and a reload is or has been in
  // flight.
  bool auto_reload_triggered;

  // State of the offline content on net error page feature. Only enabled if
  // the feature is enabled, and the error page is an offline error.
  OfflineContentOnNetErrorFeatureState offline_content_feature_state;

  // True if auto-fetch-on-dino-page is enabled and allowed for this error page.
  bool auto_fetch_allowed;
};

NetErrorHelperCore::NavigationCorrectionParams::NavigationCorrectionParams() {}

NetErrorHelperCore::NavigationCorrectionParams::NavigationCorrectionParams(
    const NavigationCorrectionParams& other) = default;

NetErrorHelperCore::NavigationCorrectionParams::~NavigationCorrectionParams() {}

bool NetErrorHelperCore::IsReloadableError(
    const NetErrorHelperCore::ErrorPageInfo& info) {
  GURL url = info.error.url();
  return info.error.domain() == error_page::Error::kNetErrorDomain &&
         info.error.reason() != net::ERR_ABORTED &&
         // For now, net::ERR_UNKNOWN_URL_SCHEME is only being displayed on
         // Chrome for Android.
         info.error.reason() != net::ERR_UNKNOWN_URL_SCHEME &&
         // Do not trigger if the server rejects a client certificate.
         // https://crbug.com/431387
         !net::IsClientCertificateError(info.error.reason()) &&
         // Some servers reject client certificates with a generic
         // handshake_failure alert.
         // https://crbug.com/431387
         info.error.reason() != net::ERR_SSL_PROTOCOL_ERROR &&
         // Do not trigger for XSS Auditor violations.
         info.error.reason() != net::ERR_BLOCKED_BY_XSS_AUDITOR &&
         // Do not trigger for blacklisted URLs.
         // https://crbug.com/803839
         info.error.reason() != net::ERR_BLOCKED_BY_ADMINISTRATOR &&
         !info.was_failed_post &&
         // Don't auto-reload non-http/https schemas.
         // https://crbug.com/471713
         url.SchemeIsHTTPOrHTTPS();
}

NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate,
                                       bool auto_reload_enabled,
                                       bool auto_reload_visible_only,
                                       bool is_visible)
    : delegate_(delegate),
      last_probe_status_(error_page::DNS_PROBE_POSSIBLE),
      can_show_network_diagnostics_dialog_(false),
      auto_reload_enabled_(auto_reload_enabled),
      auto_reload_visible_only_(auto_reload_visible_only),
      auto_reload_timer_(new base::OneShotTimer()),
      auto_reload_paused_(false),
      auto_reload_in_flight_(false),
      uncommitted_load_started_(false),
      online_(content::RenderThread::Get()->IsOnline()),
      visible_(is_visible),
      auto_reload_count_(0),
      navigation_from_button_(NO_BUTTON)
#if defined(OS_ANDROID)
      ,
      page_auto_fetcher_helper_(
          std::make_unique<PageAutoFetcherHelper>(delegate->GetRenderFrame()))
#endif
{
}

NetErrorHelperCore::~NetErrorHelperCore() {
  if (committed_error_page_info_ &&
      committed_error_page_info_->auto_reload_triggered) {
    ReportAutoReloadFailure(committed_error_page_info_->error,
                            auto_reload_count_);
  }
}

void NetErrorHelperCore::CancelPendingFetches() {
  // Cancel loading the alternate error page, and prevent any pending error page
  // load from starting a new error page load.  Swapping in the error page when
  // it's finished loading could abort the navigation, otherwise.
  if (committed_error_page_info_)
    committed_error_page_info_->needs_load_navigation_corrections = false;
  if (pending_error_page_info_)
    pending_error_page_info_->needs_load_navigation_corrections = false;
  delegate_->CancelFetchNavigationCorrections();
  auto_reload_timer_->Stop();
  auto_reload_paused_ = false;
}

void NetErrorHelperCore::OnStop() {
  if (committed_error_page_info_ &&
      committed_error_page_info_->auto_reload_triggered) {
    ReportAutoReloadFailure(committed_error_page_info_->error,
                            auto_reload_count_);
  }
  CancelPendingFetches();
  uncommitted_load_started_ = false;
  auto_reload_count_ = 0;
  auto_reload_in_flight_ = false;
}

void NetErrorHelperCore::OnWasShown() {
  visible_ = true;
  if (!auto_reload_visible_only_)
    return;
  if (auto_reload_paused_)
    MaybeStartAutoReloadTimer();
}

void NetErrorHelperCore::OnWasHidden() {
  visible_ = false;
  if (!auto_reload_visible_only_)
    return;
  PauseAutoReloadTimer();
}

void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) {
  if (frame_type != MAIN_FRAME)
    return;

  uncommitted_load_started_ = true;

  // If there's no pending error page information associated with the page load,
  // or the new page is not an error page, then reset pending error page state.
  if (!pending_error_page_info_ || page_type != ERROR_PAGE) {
    CancelPendingFetches();
  } else {
    // Halt auto-reload if it's currently scheduled. OnFinishLoad will trigger
    // auto-reload if appropriate.
    PauseAutoReloadTimer();
  }
}

void NetErrorHelperCore::OnCommitLoad(FrameType frame_type, const GURL& url) {
  if (frame_type != MAIN_FRAME)
    return;

  // If a page is committing, either it's an error page and autoreload will be
  // started again below, or it's a success page and we need to clear autoreload
  // state.
  auto_reload_in_flight_ = false;

  // uncommitted_load_started_ could already be false, since RenderFrameImpl
  // calls OnCommitLoad once for each in-page navigation (like a fragment
  // change) with no corresponding OnStartLoad.
  uncommitted_load_started_ = false;

#if defined(OS_ANDROID)
  // Don't need this state. It will be refreshed if another error page is
  // loaded.
  available_content_helper_.Reset();
#endif

  // Track if an error occurred due to a page button press.
  // This isn't perfect; if (for instance), the server is slow responding
  // to a request generated from the page reload button, and the user hits
  // the browser reload button, this code will still believe the
  // result is from the page reload button.
  if (committed_error_page_info_ && pending_error_page_info_ &&
      navigation_from_button_ != NO_BUTTON &&
      committed_error_page_info_->error.url() ==
          pending_error_page_info_->error.url()) {
    DCHECK(navigation_from_button_ == RELOAD_BUTTON ||
           navigation_from_button_ == SHOW_SAVED_COPY_BUTTON);
    RecordEvent(
        navigation_from_button_ == RELOAD_BUTTON
            ? error_page::NETWORK_ERROR_PAGE_RELOAD_BUTTON_ERROR
            : error_page::NETWORK_ERROR_PAGE_SHOW_SAVED_COPY_BUTTON_ERROR);
  }
  navigation_from_button_ = NO_BUTTON;

  if (committed_error_page_info_ && !pending_error_page_info_ &&
      committed_error_page_info_->auto_reload_triggered) {
    const error_page::Error& error = committed_error_page_info_->error;
    const GURL& error_url = error.url();
    if (url == error_url)
      ReportAutoReloadSuccess(error, auto_reload_count_);
    else if (url != content::kUnreachableWebDataURL)
      ReportAutoReloadFailure(error, auto_reload_count_);
  }

  committed_error_page_info_ = std::move(pending_error_page_info_);
}

void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) {
  if (frame_type != MAIN_FRAME)
    return;

  if (!committed_error_page_info_) {
    auto_reload_count_ = 0;
    return;
  }

  committed_error_page_info_->is_finished_loading = true;

  RecordEvent(error_page::NETWORK_ERROR_PAGE_SHOWN);
  if (committed_error_page_info_->reload_button_in_page) {
    RecordEvent(error_page::NETWORK_ERROR_PAGE_RELOAD_BUTTON_SHOWN);
  }
  if (committed_error_page_info_->show_saved_copy_button_in_page) {
    RecordEvent(error_page::NETWORK_ERROR_PAGE_SHOW_SAVED_COPY_BUTTON_SHOWN);
  }
  if (committed_error_page_info_->download_button_in_page) {
    RecordEvent(error_page::NETWORK_ERROR_PAGE_DOWNLOAD_BUTTON_SHOWN);
  }
  if (committed_error_page_info_->reload_button_in_page &&
      committed_error_page_info_->show_saved_copy_button_in_page) {
    RecordEvent(error_page::NETWORK_ERROR_PAGE_BOTH_BUTTONS_SHOWN);
  }
  if (committed_error_page_info_->show_cached_copy_button_in_page) {
    RecordEvent(error_page::NETWORK_ERROR_PAGE_CACHED_COPY_BUTTON_SHOWN);
  }

  delegate_->SetIsShowingDownloadButton(
      committed_error_page_info_->download_button_in_page);

  delegate_->EnablePageHelperFunctions(
      static_cast<net::Error>(committed_error_page_info_->error.reason()));

#if defined(OS_ANDROID)
  if (committed_error_page_info_->offline_content_feature_state ==
      OfflineContentOnNetErrorFeatureState::kEnabledList) {
    available_content_helper_.FetchAvailableContent(base::BindOnce(
        &Delegate::OfflineContentAvailable, base::Unretained(delegate_)));
  } else if (committed_error_page_info_->offline_content_feature_state ==
             OfflineContentOnNetErrorFeatureState::kEnabledSummary) {
    available_content_helper_.FetchSummary(
        base::BindOnce(&Delegate::OfflineContentSummaryAvailable,
                       base::Unretained(delegate_)));
  }

  if (committed_error_page_info_->auto_fetch_allowed) {
    page_auto_fetcher_helper_->TrySchedule(
        false, base::BindOnce(&Delegate::SetAutoFetchState,
                              base::Unretained(delegate_)));
  }
#endif  // OS_ANDROID

  if (committed_error_page_info_->needs_load_navigation_corrections) {
    // If there is another pending error page load, |fix_url| should have been
    // cleared.
    DCHECK(!pending_error_page_info_);
    DCHECK(!committed_error_page_info_->needs_dns_updates);
    delegate_->FetchNavigationCorrections(
        committed_error_page_info_->navigation_correction_params->url,
        CreateFixUrlRequestBody(
            committed_error_page_info_->error,
            *committed_error_page_info_->navigation_correction_params));
  } else if (auto_reload_enabled_ &&
             IsReloadableError(*committed_error_page_info_)) {
    MaybeStartAutoReloadTimer();
  }

  if (!committed_error_page_info_->needs_dns_updates ||
      last_probe_status_ == error_page::DNS_PROBE_POSSIBLE) {
    return;
  }
  DVLOG(1) << "Error page finished loading; sending saved status.";
  UpdateErrorPage();
}

void NetErrorHelperCore::PrepareErrorPage(FrameType frame_type,
                                          const error_page::Error& error,
                                          bool is_failed_post,
                                          bool is_ignoring_cache,
                                          std::string* error_html) {
  if (frame_type == MAIN_FRAME) {
    // If navigation corrections were needed before, that should have been
    // cancelled earlier by starting a new page load (Which has now failed).
    DCHECK(!committed_error_page_info_ ||
           !committed_error_page_info_->needs_load_navigation_corrections);

    pending_error_page_info_.reset(
        new ErrorPageInfo(error, is_failed_post, is_ignoring_cache));
    pending_error_page_info_->navigation_correction_params.reset(
        new NavigationCorrectionParams(navigation_correction_params_));
    PrepareErrorPageForMainFrame(pending_error_page_info_.get(), error_html);
  } else {
    // These values do not matter, as error pages in iframes hide the buttons.
    bool reload_button_in_page;
    bool show_saved_copy_button_in_page;
    bool show_cached_copy_button_in_page;
    bool download_button_in_page;
    OfflineContentOnNetErrorFeatureState offline_content_feature_state;
    bool auto_fetch_allowed;
    if (error_html) {
      delegate_->GenerateLocalizedErrorPage(
          error, is_failed_post,
          false /* No diagnostics dialogs allowed for subframes. */, nullptr,
          &reload_button_in_page, &show_saved_copy_button_in_page,
          &show_cached_copy_button_in_page, &download_button_in_page,
          &offline_content_feature_state, &auto_fetch_allowed, error_html);
    }
  }
}

void NetErrorHelperCore::OnNetErrorInfo(error_page::DnsProbeStatus status) {
  DCHECK_NE(error_page::DNS_PROBE_POSSIBLE, status);

  last_probe_status_ = status;

  if (!committed_error_page_info_ ||
      !committed_error_page_info_->needs_dns_updates ||
      !committed_error_page_info_->is_finished_loading) {
    return;
  }

  UpdateErrorPage();
}

void NetErrorHelperCore::OnSetCanShowNetworkDiagnosticsDialog(
    bool can_show_network_diagnostics_dialog) {
  can_show_network_diagnostics_dialog_ = can_show_network_diagnostics_dialog;
}

void NetErrorHelperCore::OnSetNavigationCorrectionInfo(
    const GURL& navigation_correction_url,
    const std::string& language,
    const std::string& country_code,
    const std::string& api_key,
    const GURL& search_url) {
  navigation_correction_params_.url = navigation_correction_url;
  navigation_correction_params_.language = language;
  navigation_correction_params_.country_code = country_code;
  navigation_correction_params_.api_key = api_key;
  navigation_correction_params_.search_url = search_url;
}

void NetErrorHelperCore::OnEasterEggHighScoreReceived(int high_score) {
  if (!committed_error_page_info_ ||
      !committed_error_page_info_->is_finished_loading) {
    return;
  }

  delegate_->InitializeErrorPageEasterEggHighScore(high_score);
}

void NetErrorHelperCore::PrepareErrorPageForMainFrame(
    ErrorPageInfo* pending_error_page_info,
    std::string* error_html) {
  std::string error_param;
  error_page::Error error = pending_error_page_info->error;

  if (pending_error_page_info->navigation_correction_params &&
      pending_error_page_info->navigation_correction_params->url.is_valid() &&
      ShouldUseFixUrlServiceForError(error, &error_param)) {
    pending_error_page_info->needs_load_navigation_corrections = true;
    return;
  }

  if (IsNetDnsError(pending_error_page_info->error)) {
    // The last probe status needs to be reset if this is a DNS error.  This
    // means that if a DNS error page is committed but has not yet finished
    // loading, a DNS probe status scheduled to be sent to it may be thrown
    // out, but since the new error page should trigger a new DNS probe, it
    // will just get the results for the next page load.
    last_probe_status_ = error_page::DNS_PROBE_POSSIBLE;
    pending_error_page_info->needs_dns_updates = true;
    error = GetUpdatedError(error);
  }
  if (error_html) {
    delegate_->GenerateLocalizedErrorPage(
        error, pending_error_page_info->was_failed_post,
        can_show_network_diagnostics_dialog_, nullptr,
        &pending_error_page_info->reload_button_in_page,
        &pending_error_page_info->show_saved_copy_button_in_page,
        &pending_error_page_info->show_cached_copy_button_in_page,
        &pending_error_page_info->download_button_in_page,
        &pending_error_page_info->offline_content_feature_state,
        &pending_error_page_info->auto_fetch_allowed, error_html);
  }
}

void NetErrorHelperCore::UpdateErrorPage() {
  DCHECK(committed_error_page_info_->needs_dns_updates);
  DCHECK(committed_error_page_info_->is_finished_loading);
  DCHECK_NE(error_page::DNS_PROBE_POSSIBLE, last_probe_status_);

  UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus",
                            last_probe_status_, error_page::DNS_PROBE_MAX);
  // Every status other than error_page::DNS_PROBE_POSSIBLE and
  // error_page::DNS_PROBE_STARTED is a final status code.  Once one is reached,
  // the page does not need further updates.
  if (last_probe_status_ != error_page::DNS_PROBE_STARTED)
    committed_error_page_info_->needs_dns_updates = false;

  // There is no need to worry about the button display statistics here because
  // the presentation of the reload and show saved copy buttons can't be changed
  // by a DNS error update.
  delegate_->UpdateErrorPage(GetUpdatedError(committed_error_page_info_->error),
                             committed_error_page_info_->was_failed_post,
                             can_show_network_diagnostics_dialog_);
}

void NetErrorHelperCore::OnNavigationCorrectionsFetched(
    const std::string& corrections,
    bool is_rtl) {
  // Loading suggestions only starts when a blank error page finishes loading,
  // and is cancelled with a new load.
  DCHECK(!pending_error_page_info_);
  DCHECK(committed_error_page_info_->is_finished_loading);
  DCHECK(committed_error_page_info_->needs_load_navigation_corrections);
  DCHECK(committed_error_page_info_->navigation_correction_params);

  pending_error_page_info_.reset(
      new ErrorPageInfo(committed_error_page_info_->error,
                        committed_error_page_info_->was_failed_post,
                        committed_error_page_info_->was_ignoring_cache));
  pending_error_page_info_->navigation_correction_response =
      ParseNavigationCorrectionResponse(corrections);

  std::string error_html;
  std::unique_ptr<error_page::ErrorPageParams> params;
  if (pending_error_page_info_->navigation_correction_response) {
    // Copy navigation correction parameters used for the request, so tracking
    // requests can still be sent if the configuration changes.
    pending_error_page_info_->navigation_correction_params.reset(
        new NavigationCorrectionParams(
            *committed_error_page_info_->navigation_correction_params));
    params = CreateErrorPageParams(
        *pending_error_page_info_->navigation_correction_response,
        pending_error_page_info_->error,
        *pending_error_page_info_->navigation_correction_params, is_rtl);
    delegate_->GenerateLocalizedErrorPage(
        pending_error_page_info_->error,
        pending_error_page_info_->was_failed_post,
        can_show_network_diagnostics_dialog_, std::move(params),
        &pending_error_page_info_->reload_button_in_page,
        &pending_error_page_info_->show_saved_copy_button_in_page,
        &pending_error_page_info_->show_cached_copy_button_in_page,
        &pending_error_page_info_->download_button_in_page,
        &pending_error_page_info_->offline_content_feature_state,
        &pending_error_page_info_->auto_fetch_allowed, &error_html);
  } else {
    // Since |navigation_correction_params| in |pending_error_page_info_| is
    // NULL, this won't trigger another attempt to load corrections.
    PrepareErrorPageForMainFrame(pending_error_page_info_.get(), &error_html);
  }

  // TODO(mmenke):  Once the new API is in place, look into replacing this
  //                double page load by just updating the error page, like DNS
  //                probes do.
  delegate_->LoadErrorPage(error_html, pending_error_page_info_->error.url());
}

error_page::Error NetErrorHelperCore::GetUpdatedError(
    const error_page::Error& error) const {
  // If a probe didn't run or wasn't conclusive, restore the original error.
  if (last_probe_status_ == error_page::DNS_PROBE_NOT_RUN ||
      last_probe_status_ == error_page::DNS_PROBE_FINISHED_INCONCLUSIVE) {
    return error;
  }

  return error_page::Error::DnsProbeError(error.url(), last_probe_status_,
                                          error.stale_copy_in_cache());
}

void NetErrorHelperCore::Reload(bool bypass_cache) {
  if (!committed_error_page_info_) {
    return;
  }
  delegate_->ReloadPage(bypass_cache);
}

bool NetErrorHelperCore::MaybeStartAutoReloadTimer() {
  // Automation tools expect to be in control of reloads.
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kEnableAutomation)) {
    return false;
  }

  if (!committed_error_page_info_ ||
      !committed_error_page_info_->is_finished_loading ||
      pending_error_page_info_ || uncommitted_load_started_) {
    return false;
  }

  StartAutoReloadTimer();
  return true;
}

void NetErrorHelperCore::StartAutoReloadTimer() {
  DCHECK(committed_error_page_info_);
  DCHECK(IsReloadableError(*committed_error_page_info_));

  committed_error_page_info_->auto_reload_triggered = true;

  if (!online_ || (!visible_ && auto_reload_visible_only_)) {
    auto_reload_paused_ = true;
    return;
  }

  auto_reload_paused_ = false;
  base::TimeDelta delay = GetAutoReloadTime(auto_reload_count_);
  auto_reload_timer_->Stop();
  auto_reload_timer_->Start(
      FROM_HERE, delay,
      base::Bind(&NetErrorHelperCore::AutoReloadTimerFired,
                 base::Unretained(this)));
}

void NetErrorHelperCore::AutoReloadTimerFired() {
  // AutoReloadTimerFired only runs if:
  // 1. StartAutoReloadTimer was previously called, which requires that
  //    committed_error_page_info_ is populated;
  // 2. No other page load has started since (1), since OnStartLoad stops the
  //    auto-reload timer.
  DCHECK(committed_error_page_info_);

  auto_reload_count_++;
  auto_reload_in_flight_ = true;
  Reload(committed_error_page_info_->was_ignoring_cache);
}

void NetErrorHelperCore::PauseAutoReloadTimer() {
  if (!auto_reload_timer_->IsRunning())
    return;
  DCHECK(committed_error_page_info_);
  DCHECK(!auto_reload_paused_);
  DCHECK(committed_error_page_info_->auto_reload_triggered);
  auto_reload_timer_->Stop();
  auto_reload_paused_ = true;
}

void NetErrorHelperCore::NetworkStateChanged(bool online) {
  bool was_online = online_;
  online_ = online;
  if (!was_online && online) {
    // Transitioning offline -> online
    if (auto_reload_paused_)
      MaybeStartAutoReloadTimer();
  } else if (was_online && !online) {
    // Transitioning online -> offline
    if (auto_reload_timer_->IsRunning())
      auto_reload_count_ = 0;
    PauseAutoReloadTimer();
  }
}

bool NetErrorHelperCore::ShouldSuppressErrorPage(FrameType frame_type,
                                                 const GURL& url) {
  // Don't suppress child frame errors.
  if (frame_type != MAIN_FRAME)
    return false;

  // If there's no auto reload attempt in flight, this error page didn't come
  // from auto reload, so don't suppress it.
  if (!auto_reload_in_flight_)
    return false;

  uncommitted_load_started_ = false;
  // This serves to terminate the auto-reload in flight attempt. If
  // ShouldSuppressErrorPage is called, the auto-reload yielded an error, which
  // means the request was already sent.
  auto_reload_in_flight_ = false;
  MaybeStartAutoReloadTimer();
  return true;
}

#if defined(OS_ANDROID)
void NetErrorHelperCore::SetPageAutoFetcherHelperForTesting(
    std::unique_ptr<PageAutoFetcherHelper> page_auto_fetcher_helper) {
  page_auto_fetcher_helper_ = std::move(page_auto_fetcher_helper);
}
#endif

void NetErrorHelperCore::ExecuteButtonPress(Button button) {
  // If there's no committed error page, should not be invoked.
  DCHECK(committed_error_page_info_);

  switch (button) {
    case RELOAD_BUTTON:
      RecordEvent(error_page::NETWORK_ERROR_PAGE_RELOAD_BUTTON_CLICKED);
      if (committed_error_page_info_->show_saved_copy_button_in_page) {
        RecordEvent(error_page::NETWORK_ERROR_PAGE_BOTH_BUTTONS_RELOAD_CLICKED);
      }
      navigation_from_button_ = RELOAD_BUTTON;
      Reload(false);
      return;
    case SHOW_SAVED_COPY_BUTTON:
      RecordEvent(
          error_page::NETWORK_ERROR_PAGE_SHOW_SAVED_COPY_BUTTON_CLICKED);
      navigation_from_button_ = SHOW_SAVED_COPY_BUTTON;
      if (committed_error_page_info_->reload_button_in_page) {
        RecordEvent(
            error_page::
                NETWORK_ERROR_PAGE_BOTH_BUTTONS_SHOWN_SAVED_COPY_CLICKED);
      }
      delegate_->LoadPageFromCache(committed_error_page_info_->error.url());
      return;
    case MORE_BUTTON:
      // Visual effects on page are handled in Javascript code.
      RecordEvent(error_page::NETWORK_ERROR_PAGE_MORE_BUTTON_CLICKED);
      return;
    case EASTER_EGG:
      RecordEvent(error_page::NETWORK_ERROR_EASTER_EGG_ACTIVATED);
      delegate_->RequestEasterEggHighScore();
      return;
    case SHOW_CACHED_COPY_BUTTON:
      RecordEvent(error_page::NETWORK_ERROR_PAGE_CACHED_COPY_BUTTON_CLICKED);
      return;
    case DIAGNOSE_ERROR:
      RecordEvent(error_page::NETWORK_ERROR_DIAGNOSE_BUTTON_CLICKED);
      delegate_->DiagnoseError(committed_error_page_info_->error.url());
      return;
    case DOWNLOAD_BUTTON:
      RecordEvent(error_page::NETWORK_ERROR_PAGE_DOWNLOAD_BUTTON_CLICKED);
      delegate_->DownloadPageLater();
      return;
    case NO_BUTTON:
      NOTREACHED();
      return;
  }
}

void NetErrorHelperCore::TrackClick(int tracking_id) {
  // It's technically possible for |navigation_correction_params| to be NULL but
  // for |navigation_correction_response| not to be NULL, if the paramters
  // changed between loading the original error page and loading the error page
  if (!committed_error_page_info_ ||
      !committed_error_page_info_->navigation_correction_response) {
    return;
  }

  NavigationCorrectionResponse* response =
      committed_error_page_info_->navigation_correction_response.get();

  // |tracking_id| is less than 0 when the error page was not generated by the
  // navigation correction service.  |tracking_id| should never be greater than
  // the array size, but best to be safe, since it contains data from a remote
  // site, though none of that data should make it into Javascript callbacks.
  if (tracking_id < 0 ||
      static_cast<size_t>(tracking_id) >= response->corrections.size()) {
    return;
  }

  // Only report a clicked link once.
  if (committed_error_page_info_->clicked_corrections.count(tracking_id))
    return;

  TrackClickUMA(response->corrections[tracking_id]->correction_type);

  committed_error_page_info_->clicked_corrections.insert(tracking_id);
  std::string request_body = CreateClickTrackingUrlRequestBody(
      committed_error_page_info_->error,
      *committed_error_page_info_->navigation_correction_params, *response,
      *response->corrections[tracking_id]);
  delegate_->SendTrackingRequest(
      committed_error_page_info_->navigation_correction_params->url,
      request_body);
}

void NetErrorHelperCore::LaunchOfflineItem(const std::string& id,
                                           const std::string& name_space) {
#if defined(OS_ANDROID)
  available_content_helper_.LaunchItem(id, name_space);
#endif
}

void NetErrorHelperCore::LaunchDownloadsPage() {
#if defined(OS_ANDROID)
  available_content_helper_.LaunchDownloadsPage();
#endif
}

void NetErrorHelperCore::SavePageForLater() {
#if defined(OS_ANDROID)
  page_auto_fetcher_helper_->TrySchedule(
      /*user_requested=*/true, base::BindOnce(&Delegate::SetAutoFetchState,
                                              base::Unretained(delegate_)));
#endif
}

void NetErrorHelperCore::CancelSavePage() {
#if defined(OS_ANDROID)
  page_auto_fetcher_helper_->CancelSchedule();
#endif
}

void NetErrorHelperCore::ListVisibilityChanged(bool is_visible) {
#if defined(OS_ANDROID)
  available_content_helper_.ListVisibilityChanged(is_visible);
#endif
}
