// 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 "components/error_page/renderer/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/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/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "build/build_config.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/url_constants.h"
#include "net/base/escape.h"
#include "net/base/net_errors.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
#include "url/url_constants.h"

namespace error_page {

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 >= arraysize(kDelaysMs))
    reload_count = arraysize(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 IsBlinkDnsError(const blink::WebURLError& error) {
  return (error.domain.Utf8() == net::kErrorDomain) &&
         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 a WebURLError, 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 blink::WebURLError& error,
                                    std::string* error_param) {
  error_param->clear();

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

  std::string domain = error.domain.Utf8();
  if (domain == url::kHttpScheme && error.reason == 404) {
    *error_param = "http404";
    return true;
  }
  if (IsBlinkDnsError(error)) {
    *error_param = "dnserror";
    return true;
  }
  if (domain == net::kErrorDomain &&
      (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 blink::WebURLError& 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.unreachable_url));
  return CreateRequestBody("linkdoctor.fixurl.fixurl", error_param,
                           correction_params, std::move(params));
}

std::string CreateClickTrackingUrlRequestBody(
    const blink::WebURLError& 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.unreachable_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<ErrorPageParams> CreateErrorPageParams(
    const NavigationCorrectionResponse& response,
    const blink::WebURLError& 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.unreachable_url)), is_rtl);

  std::unique_ptr<ErrorPageParams> params(new 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 < arraysize(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 blink::WebURLError& error, size_t count) {
  if (error.domain.Utf8() != net::kErrorDomain)
    return;
  UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AutoReload.ErrorAtSuccess", -error.reason);
  UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtSuccess",
                       static_cast<base::HistogramBase::Sample>(count));
  if (count == 1) {
    UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AutoReload.ErrorAtFirstSuccess",
                                -error.reason);
  }
}

void ReportAutoReloadFailure(const blink::WebURLError& error, size_t count) {
  if (error.domain.Utf8() != net::kErrorDomain)
    return;
  UMA_HISTOGRAM_SPARSE_SLOWLY("Net.AutoReload.ErrorAtStop", -error.reason);
  UMA_HISTOGRAM_COUNTS("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 < arraysize(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(blink::WebURLError 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) {}

  // Information about the failed page load.
  blink::WebURLError 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;
};

NetErrorHelperCore::NavigationCorrectionParams::NavigationCorrectionParams() {
}

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

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

bool NetErrorHelperCore::IsReloadableError(
    const NetErrorHelperCore::ErrorPageInfo& info) {
  GURL url = info.error.unreachable_url;
  return info.error.domain.Utf8() == net::kErrorDomain &&
         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 &&
         !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_(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::Timer(false, false)),
      auto_reload_paused_(false),
      auto_reload_in_flight_(false),
      uncommitted_load_started_(false),
      // TODO(ellyjones): Make online_ accurate at object creation.
      online_(true),
      visible_(is_visible),
      auto_reload_count_(0),
      navigation_from_button_(NO_BUTTON) {
}

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();
}

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;

  // 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.unreachable_url ==
          pending_error_page_info_->error.unreachable_url) {
    DCHECK(navigation_from_button_ == RELOAD_BUTTON ||
           navigation_from_button_ == SHOW_SAVED_COPY_BUTTON);
    RecordEvent(navigation_from_button_ == RELOAD_BUTTON ?
        NETWORK_ERROR_PAGE_RELOAD_BUTTON_ERROR :
        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 blink::WebURLError& error = committed_error_page_info_->error;
    const GURL& error_url = error.unreachable_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(NETWORK_ERROR_PAGE_SHOWN);
  if (committed_error_page_info_->reload_button_in_page) {
    RecordEvent(NETWORK_ERROR_PAGE_RELOAD_BUTTON_SHOWN);
  }
  if (committed_error_page_info_->show_saved_copy_button_in_page) {
    RecordEvent(NETWORK_ERROR_PAGE_SHOW_SAVED_COPY_BUTTON_SHOWN);
  }
  if (committed_error_page_info_->download_button_in_page) {
    RecordEvent(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(NETWORK_ERROR_PAGE_BOTH_BUTTONS_SHOWN);
  }
  if (committed_error_page_info_->show_cached_copy_button_in_page) {
    RecordEvent(NETWORK_ERROR_PAGE_CACHED_COPY_BUTTON_SHOWN);
  }

  delegate_->SetIsShowingDownloadButton(
      committed_error_page_info_->download_button_in_page);

  delegate_->EnablePageHelperFunctions();

  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_ == DNS_PROBE_POSSIBLE) {
    return;
  }
  DVLOG(1) << "Error page finished loading; sending saved status.";
  UpdateErrorPage();
}

void NetErrorHelperCore::GetErrorHTML(FrameType frame_type,
                                      const blink::WebURLError& 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_));
    GetErrorHtmlForMainFrame(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;

    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,
        error_html);
  }
}

void NetErrorHelperCore::OnNetErrorInfo(DnsProbeStatus status) {
  DCHECK_NE(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::GetErrorHtmlForMainFrame(
    ErrorPageInfo* pending_error_page_info,
    std::string* error_html) {
  std::string error_param;
  blink::WebURLError 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 (IsBlinkDnsError(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_ = DNS_PROBE_POSSIBLE;
    pending_error_page_info->needs_dns_updates = true;
    error = GetUpdatedError(error);
  }

  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, error_html);
}

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

  UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus",
                            last_probe_status_,
                            DNS_PROBE_MAX);
  // Every status other than DNS_PROBE_POSSIBLE and DNS_PROBE_STARTED is a
  // final status code.  Once one is reached, the page does not need further
  // updates.
  if (last_probe_status_ != 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<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,
        &error_html);
  } else {
    // Since |navigation_correction_params| in |pending_error_page_info_| is
    // NULL, this won't trigger another attempt to load corrections.
    GetErrorHtmlForMainFrame(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.unreachable_url);
}

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

  blink::WebURLError updated_error;
  updated_error.domain = blink::WebString::FromUTF8(kDnsProbeErrorDomain);
  updated_error.reason = last_probe_status_;
  updated_error.unreachable_url = error.unreachable_url;
  updated_error.stale_copy_in_cache = error.stale_copy_in_cache;

  return updated_error;
}

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

bool NetErrorHelperCore::MaybeStartAutoReloadTimer() {
  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;
}

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(NETWORK_ERROR_PAGE_RELOAD_BUTTON_CLICKED);
      if (committed_error_page_info_->show_saved_copy_button_in_page) {
        RecordEvent(NETWORK_ERROR_PAGE_BOTH_BUTTONS_RELOAD_CLICKED);
      }
      navigation_from_button_ = RELOAD_BUTTON;
      Reload(false);
      return;
    case SHOW_SAVED_COPY_BUTTON:
      RecordEvent(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(NETWORK_ERROR_PAGE_BOTH_BUTTONS_SHOWN_SAVED_COPY_CLICKED);
      }
      delegate_->LoadPageFromCache(
          committed_error_page_info_->error.unreachable_url);
      return;
    case MORE_BUTTON:
      // Visual effects on page are handled in Javascript code.
      RecordEvent(NETWORK_ERROR_PAGE_MORE_BUTTON_CLICKED);
      return;
    case EASTER_EGG:
      RecordEvent(NETWORK_ERROR_EASTER_EGG_ACTIVATED);
      return;
    case SHOW_CACHED_COPY_BUTTON:
      RecordEvent(NETWORK_ERROR_PAGE_CACHED_COPY_BUTTON_CLICKED);
      return;
    case DIAGNOSE_ERROR:
      RecordEvent(NETWORK_ERROR_DIAGNOSE_BUTTON_CLICKED);
      delegate_->DiagnoseError(
          committed_error_page_info_->error.unreachable_url);
      return;
    case DOWNLOAD_BUTTON:
      RecordEvent(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);
}

}  // namespace error_page
