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

#include "chrome/browser/offline_pages/offline_page_request_handler.h"

#include <utility>

#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/offline_pages/offline_page_model_factory.h"
#include "chrome/browser/offline_pages/offline_page_tab_helper.h"
#include "chrome/browser/offline_pages/offline_page_utils.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "components/offline_pages/core/offline_clock.h"
#include "components/offline_pages/core/offline_page_model.h"
#include "components/offline_pages/core/request_header/offline_page_header.h"
#include "components/previews/core/previews_experiments.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/resource_type.h"
#include "net/base/file_stream.h"
#include "net/base/filename_util.h"
#include "net/base/io_buffer.h"
#include "net/base/network_change_notifier.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request_redirect_job.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"

namespace offline_pages {

namespace {

// This enum is used to tell all possible outcomes of handling network requests
// that might serve offline contents.
enum class RequestResult {
  // Offline page was shown for current URL.
  OFFLINE_PAGE_SERVED,
  // Redirected from original URL to final URL in preparation to show the
  // offline page under final URL. OFFLINE_PAGE_SERVED is most likely to be
  // reported next if no other error is encountered.
  REDIRECTED,
  // Tab was gone.
  NO_TAB_ID,
  // Web contents was gone.
  NO_WEB_CONTENTS,
  // The offline page found was not fresh enough, i.e. not created in the past
  // day. This only applies in prohibitively slow network.
  PAGE_NOT_FRESH,
  // Offline page was not found, by searching with either final URL or original
  // URL.
  OFFLINE_PAGE_NOT_FOUND,
  // Digest for the archive file does not match with the one saved in the
  // metadata database.
  DIGEST_MISMATCH,
  // The archive file does not exist.
  FILE_NOT_FOUND,
};

// Consistent with the buffer size used in url request data reading.
const size_t kMaxBufferSizeForValidation = 4096;

void GetFileSize(const base::FilePath& file_path, int64_t* file_size) {
  bool succeeded = base::GetFileSize(file_path, file_size);
  if (!succeeded) {
    // Use -1 to indicate that file is not found.
    *file_size = -1;
  }
}

void UpdateDigest(
    const scoped_refptr<OfflinePageRequestHandler::ThreadSafeArchiveValidator>&
        validator,
    scoped_refptr<net::IOBuffer> buffer,
    size_t len) {
  validator->Update(buffer->data(), len);
}

OfflinePageRequestHandler::AggregatedRequestResult
RequestResultToAggregatedRequestResult(
    RequestResult request_result,
    OfflinePageRequestHandler::NetworkState network_state) {
  if (request_result == RequestResult::NO_TAB_ID)
    return OfflinePageRequestHandler::AggregatedRequestResult::NO_TAB_ID;

  if (request_result == RequestResult::NO_WEB_CONTENTS)
    return OfflinePageRequestHandler::AggregatedRequestResult::NO_WEB_CONTENTS;

  if (request_result == RequestResult::FILE_NOT_FOUND)
    return OfflinePageRequestHandler::AggregatedRequestResult::FILE_NOT_FOUND;

  if (request_result == RequestResult::PAGE_NOT_FRESH) {
    DCHECK_EQ(
        OfflinePageRequestHandler::NetworkState::PROHIBITIVELY_SLOW_NETWORK,
        network_state);
    return OfflinePageRequestHandler::AggregatedRequestResult::
        PAGE_NOT_FRESH_ON_PROHIBITIVELY_SLOW_NETWORK;
  }

  if (request_result == RequestResult::OFFLINE_PAGE_NOT_FOUND) {
    switch (network_state) {
      case OfflinePageRequestHandler::NetworkState::DISCONNECTED_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            PAGE_NOT_FOUND_ON_DISCONNECTED_NETWORK;
      case OfflinePageRequestHandler::NetworkState::PROHIBITIVELY_SLOW_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            PAGE_NOT_FOUND_ON_PROHIBITIVELY_SLOW_NETWORK;
      case OfflinePageRequestHandler::NetworkState::FLAKY_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            PAGE_NOT_FOUND_ON_FLAKY_NETWORK;
      case OfflinePageRequestHandler::NetworkState::
          FORCE_OFFLINE_ON_CONNECTED_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            PAGE_NOT_FOUND_ON_CONNECTED_NETWORK;
      case OfflinePageRequestHandler::NetworkState::CONNECTED_NETWORK:
        break;
    }
    NOTREACHED();
  }

  if (request_result == RequestResult::REDIRECTED) {
    switch (network_state) {
      case OfflinePageRequestHandler::NetworkState::DISCONNECTED_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            REDIRECTED_ON_DISCONNECTED_NETWORK;
      case OfflinePageRequestHandler::NetworkState::PROHIBITIVELY_SLOW_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            REDIRECTED_ON_PROHIBITIVELY_SLOW_NETWORK;
      case OfflinePageRequestHandler::NetworkState::FLAKY_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            REDIRECTED_ON_FLAKY_NETWORK;
      case OfflinePageRequestHandler::NetworkState::
          FORCE_OFFLINE_ON_CONNECTED_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            REDIRECTED_ON_CONNECTED_NETWORK;
      case OfflinePageRequestHandler::NetworkState::CONNECTED_NETWORK:
        break;
    }
    NOTREACHED();
  }

  if (request_result == RequestResult::DIGEST_MISMATCH) {
    switch (network_state) {
      case OfflinePageRequestHandler::NetworkState::DISCONNECTED_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            DIGEST_MISMATCH_ON_DISCONNECTED_NETWORK;
      case OfflinePageRequestHandler::NetworkState::PROHIBITIVELY_SLOW_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            DIGEST_MISMATCH_ON_PROHIBITIVELY_SLOW_NETWORK;
      case OfflinePageRequestHandler::NetworkState::FLAKY_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            DIGEST_MISMATCH_ON_FLAKY_NETWORK;
      case OfflinePageRequestHandler::NetworkState::
          FORCE_OFFLINE_ON_CONNECTED_NETWORK:
      case OfflinePageRequestHandler::NetworkState::CONNECTED_NETWORK:
        return OfflinePageRequestHandler::AggregatedRequestResult::
            DIGEST_MISMATCH_ON_CONNECTED_NETWORK;
    }
    NOTREACHED();
  }

  DCHECK_EQ(RequestResult::OFFLINE_PAGE_SERVED, request_result);
  DCHECK_NE(OfflinePageRequestHandler::NetworkState::CONNECTED_NETWORK,
            network_state);
  switch (network_state) {
    case OfflinePageRequestHandler::NetworkState::DISCONNECTED_NETWORK:
      return OfflinePageRequestHandler::AggregatedRequestResult::
          SHOW_OFFLINE_ON_DISCONNECTED_NETWORK;
    case OfflinePageRequestHandler::NetworkState::PROHIBITIVELY_SLOW_NETWORK:
      return OfflinePageRequestHandler::AggregatedRequestResult::
          SHOW_OFFLINE_ON_PROHIBITIVELY_SLOW_NETWORK;
    case OfflinePageRequestHandler::NetworkState::FLAKY_NETWORK:
      return OfflinePageRequestHandler::AggregatedRequestResult::
          SHOW_OFFLINE_ON_FLAKY_NETWORK;
    case OfflinePageRequestHandler::NetworkState::
        FORCE_OFFLINE_ON_CONNECTED_NETWORK:
      return OfflinePageRequestHandler::AggregatedRequestResult::
          SHOW_OFFLINE_ON_CONNECTED_NETWORK;
    case OfflinePageRequestHandler::NetworkState::CONNECTED_NETWORK:
      break;
  }
  NOTREACHED();

  return OfflinePageRequestHandler::AggregatedRequestResult::
      AGGREGATED_REQUEST_RESULT_MAX;
}

void ReportOpenResult(int result) {
  base::UmaHistogramSparse("OfflinePages.RequestJob.OpenFileErrorCode",
                           -result);
}

void ReportSeekResult(int result) {
  if (result < 0) {
    base::UmaHistogramSparse("OfflinePages.RequestJob.SeekFileErrorCode",
                             static_cast<int>(-result));
  }
}

void ReportReadResult(int result) {
  if (result < 0) {
    base::UmaHistogramSparse("OfflinePages.RequestJob.ReadFileErrorCode",
                             -result);
  }
}

void ReportRequestResult(
    RequestResult request_result,
    OfflinePageRequestHandler::NetworkState network_state) {
  OfflinePageRequestHandler::ReportAggregatedRequestResult(
      RequestResultToAggregatedRequestResult(request_result, network_state));
}

void ReportOfflinePageSize(
    OfflinePageRequestHandler::NetworkState network_state,
    const OfflinePageItem& offline_page) {
  if (offline_page.client_id.name_space.empty())
    return;

  // The two histograms report values between 1KiB and 100MiB.
  switch (network_state) {
    case OfflinePageRequestHandler::NetworkState::
        DISCONNECTED_NETWORK:  // Fall-through
    case OfflinePageRequestHandler::NetworkState::
        PROHIBITIVELY_SLOW_NETWORK:  // Fall-through
    case OfflinePageRequestHandler::NetworkState::FLAKY_NETWORK:
      base::UmaHistogramCounts100000("OfflinePages.PageSizeOnAccess.Offline." +
                                         offline_page.client_id.name_space,
                                     offline_page.file_size / 1024);
      return;
    case OfflinePageRequestHandler::NetworkState::
        FORCE_OFFLINE_ON_CONNECTED_NETWORK:
      base::UmaHistogramCounts100000("OfflinePages.PageSizeOnAccess.Online." +
                                         offline_page.client_id.name_space,
                                     offline_page.file_size / 1024);
      return;
    case OfflinePageRequestHandler::NetworkState::CONNECTED_NETWORK:
      break;
  }
  NOTREACHED();
}

void ReportAccessEntryPoint(
    const std::string& name_space,
    OfflinePageRequestHandler::AccessEntryPoint entry_point) {
  base::UmaHistogramEnumeration(
      "OfflinePages.AccessEntryPoint." + name_space, entry_point,
      OfflinePageRequestHandler::AccessEntryPoint::COUNT);
}

void ReportExistenceOfRangeHeader(bool has_range_header) {
  base::UmaHistogramBoolean("OfflinePages.RequestJob.RangeHeader",
                            has_range_header);
}

void ReportIntentDataChangedAfterValidation(bool changed) {
  UMA_HISTOGRAM_BOOLEAN(
      "OfflinePages.RequestJob.IntentDataChangedAfterValidation", changed);
}

OfflinePageModel* GetOfflinePageModel(
    content::ResourceRequestInfo::WebContentsGetter web_contents_getter) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  content::WebContents* web_contents = web_contents_getter.Run();
  return web_contents ? OfflinePageModelFactory::GetForBrowserContext(
                            web_contents->GetBrowserContext())
                      : nullptr;
}

void NotifyAvailableOfflinePagesOnIO(
    base::WeakPtr<OfflinePageRequestHandler> job,
    const std::vector<OfflinePageRequestHandler::Candidate>& candidates) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (job)
    job->OnOfflinePagesAvailable(candidates);
}

// Notifies OfflinePageRequestHandler about all the matched offline pages.
void NotifyAvailableOfflinePagesOnUI(
    base::WeakPtr<OfflinePageRequestHandler> job,
    const std::vector<OfflinePageRequestHandler::Candidate>& candidates) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // Delegates to IO thread since OfflinePageRequestHandler should only be
  // accessed from IO thread.
  base::PostTaskWithTraits(
      FROM_HERE, {content::BrowserThread::IO},
      base::BindOnce(&NotifyAvailableOfflinePagesOnIO, job, candidates));
}

// Failed to find an offline page.
void FailedToFindOfflinePage(
    RequestResult request_error_result,
    OfflinePageRequestHandler::NetworkState network_state,
    base::WeakPtr<OfflinePageRequestHandler> job) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK_NE(RequestResult::OFFLINE_PAGE_SERVED, request_error_result);

  ReportRequestResult(request_error_result, network_state);
  NotifyAvailableOfflinePagesOnUI(
      job, std::vector<OfflinePageRequestHandler::Candidate>());
}

// Handles the result of finding matched offline pages.
void SelectPagesForURLDone(
    const GURL& url,
    const OfflinePageHeader& offline_header,
    OfflinePageRequestHandler::NetworkState network_state,
    base::WeakPtr<OfflinePageRequestHandler> job,
    content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
    const std::vector<OfflinePageItem>& offline_pages) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // Bail out if no page is found.
  if (offline_pages.empty()) {
    FailedToFindOfflinePage(RequestResult::OFFLINE_PAGE_NOT_FOUND,
                            network_state, job);
    return;
  }

  // Bail out if web_contents is gone.
  OfflinePageModel* offline_page_model =
      GetOfflinePageModel(web_contents_getter);
  if (!offline_page_model) {
    FailedToFindOfflinePage(RequestResult::NO_WEB_CONTENTS, network_state, job);
    return;
  }

  std::vector<OfflinePageRequestHandler::Candidate> candidates;
  for (const auto& offline_page : offline_pages) {
    OfflinePageRequestHandler::Candidate candidate;
    candidate.offline_page = offline_page;
    candidate.archive_is_in_internal_dir =
        offline_page_model->IsArchiveInInternalDir(offline_page.file_path);
    candidates.push_back(candidate);
  }

  NotifyAvailableOfflinePagesOnUI(job, candidates);
}

// Handles the result of finding an offline page with the requested offline ID.
void GetPageByOfflineIdDone(
    const GURL& url,
    const OfflinePageHeader& offline_header,
    OfflinePageRequestHandler::NetworkState network_state,
    content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
    base::WeakPtr<OfflinePageRequestHandler> job,
    const OfflinePageItem* offline_page) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // If the found offline page does not match the request URL, fail.
  if (!offline_page || offline_page->url != url) {
    FailedToFindOfflinePage(RequestResult::OFFLINE_PAGE_NOT_FOUND,
                            network_state, job);
    return;
  }

  std::vector<OfflinePageItem> offline_pages;
  offline_pages.push_back(*offline_page);
  SelectPagesForURLDone(url, offline_header, network_state, job,
                        web_contents_getter, offline_pages);
}

// Tries to find all the offline pages to serve for |url|.
void GetPagesToServeURL(
    const GURL& url,
    const OfflinePageHeader& offline_header,
    OfflinePageRequestHandler::NetworkState network_state,
    content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
    OfflinePageRequestHandler::Delegate::TabIdGetter tab_id_getter,
    base::WeakPtr<OfflinePageRequestHandler> job) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  content::WebContents* web_contents = web_contents_getter.Run();
  if (!web_contents) {
    FailedToFindOfflinePage(RequestResult::NO_WEB_CONTENTS, network_state, job);
    return;
  }
  int tab_id;
  if (!tab_id_getter.Run(web_contents, &tab_id)) {
    FailedToFindOfflinePage(RequestResult::NO_TAB_ID, network_state, job);
    return;
  }

  // If an int64 offline ID is present in the offline header, try to load that
  // particular version.
  if (!offline_header.id.empty()) {
    int64_t offline_id;
    if (base::StringToInt64(offline_header.id, &offline_id)) {
      OfflinePageModel* offline_page_model =
          OfflinePageModelFactory::GetForBrowserContext(
              web_contents->GetBrowserContext());
      if (!offline_page_model) {
        FailedToFindOfflinePage(RequestResult::OFFLINE_PAGE_NOT_FOUND,
                                network_state, job);
        return;
      }
      offline_page_model->GetPageByOfflineId(
          offline_id, base::Bind(&GetPageByOfflineIdDone, url, offline_header,
                                 network_state, web_contents_getter, job));
      return;
    }
  }

  OfflinePageUtils::SelectPagesForURL(
      web_contents->GetBrowserContext(), url, tab_id,
      base::BindOnce(&SelectPagesForURLDone, url, offline_header, network_state,
                     job, web_contents_getter));
}

// Do all the things needed to be done on UI thread after a trusted offline
// page has been visited.
void VisitTrustedOfflinePageOnUI(
    const OfflinePageHeader& offline_header,
    OfflinePageRequestHandler::NetworkState network_state,
    content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
    const OfflinePageItem& offline_page,
    bool archive_is_in_internal_dir) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // |web_contents_getter| is passed from IO thread. We need to check if
  // web contents is still valid.
  content::WebContents* web_contents = web_contents_getter.Run();
  if (!web_contents)
    return;

  OfflinePageModel* offline_page_model =
      OfflinePageModelFactory::GetForBrowserContext(
          web_contents->GetBrowserContext());
  if (!offline_page_model)
    return;

  // Mark the offline page as being accessed.
  offline_page_model->MarkPageAccessed(offline_page.offline_id);

  // Save an cached copy of OfflinePageItem such that Tab code can get
  // the loaded offline page immediately.
  OfflinePageTabHelper* tab_helper =
      OfflinePageTabHelper::FromWebContents(web_contents);
  DCHECK(tab_helper);
  tab_helper->SetOfflinePage(
      offline_page, offline_header,
      archive_is_in_internal_dir
          ? OfflinePageTrustedState::TRUSTED_AS_IN_INTERNAL_DIR
          : OfflinePageTrustedState::TRUSTED_AS_UNMODIFIED_AND_IN_PUBLIC_DIR,
      network_state ==
          OfflinePageRequestHandler::NetworkState::PROHIBITIVELY_SLOW_NETWORK);
}

void ClearOfflinePageData(
    content::ResourceRequestInfo::WebContentsGetter web_contents_getter) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  // |web_contents_getter| is passed from IO thread. We need to check if
  // web contents is still valid.
  content::WebContents* web_contents = web_contents_getter.Run();
  if (!web_contents)
    return;

  // Save an cached copy of OfflinePageItem such that Tab code can get
  // the loaded offline page immediately.
  OfflinePageTabHelper* tab_helper =
      OfflinePageTabHelper::FromWebContents(web_contents);
  DCHECK(tab_helper);
  tab_helper->ClearOfflinePage();
}

}  // namespace

// static
void OfflinePageRequestHandler::ReportAggregatedRequestResult(
    AggregatedRequestResult result) {
  UMA_HISTOGRAM_ENUMERATION(
      "OfflinePages.AggregatedRequestResult2", static_cast<int>(result),
      static_cast<int>(AggregatedRequestResult::AGGREGATED_REQUEST_RESULT_MAX));
}

OfflinePageRequestHandler::OfflinePageRequestHandler(
    const GURL& url,
    const net::HttpRequestHeaders& extra_request_headers,
    Delegate* delegate)
    : url_(url),
      delegate_(delegate),
      network_state_(NetworkState::CONNECTED_NETWORK),
      candidate_index_(0),
      has_range_header_(false),
      weak_ptr_factory_(this) {
  std::string offline_header_value;
  extra_request_headers.GetHeader(kOfflinePageHeader, &offline_header_value);
  // Note that |offline_header| will be empty if parsing from the header value
  // fails.
  offline_header_ = OfflinePageHeader(offline_header_value);

  if (extra_request_headers.HasHeader(net::HttpRequestHeaders::kRange))
    has_range_header_ = true;
}

OfflinePageRequestHandler::~OfflinePageRequestHandler() {}

OfflinePageRequestHandler::NetworkState
OfflinePageRequestHandler::GetNetworkState() const {
  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);

  if (offline_header_.reason == OfflinePageHeader::Reason::NET_ERROR)
    return OfflinePageRequestHandler::NetworkState::FLAKY_NETWORK;

  if (net::NetworkChangeNotifier::IsOffline())
    return OfflinePageRequestHandler::NetworkState::DISCONNECTED_NETWORK;

  // If RELOAD is present in the offline header, load the live page.
  if (offline_header_.reason == OfflinePageHeader::Reason::RELOAD)
    return OfflinePageRequestHandler::NetworkState::CONNECTED_NETWORK;

  // If other reason is present in the offline header, force loading the offline
  // page even when the network is connected.
  if (offline_header_.reason != OfflinePageHeader::Reason::NONE) {
    return OfflinePageRequestHandler::NetworkState::
        FORCE_OFFLINE_ON_CONNECTED_NETWORK;
  }

  // Checks if previews are allowed, the network is slow, and the request is
  // allowed to be shown for previews. When reloading from an offline page or
  // through other force checks, previews should not be considered; previews
  // eligiblity is only checked when |offline_header.reason| is Reason::NONE.
  if (delegate_->ShouldAllowPreview())
    return OfflinePageRequestHandler::NetworkState::PROHIBITIVELY_SLOW_NETWORK;

  // Otherwise, the network state is a good network.
  return OfflinePageRequestHandler::NetworkState::CONNECTED_NETWORK;
}

void OfflinePageRequestHandler::Start() {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(&OfflinePageRequestHandler::StartAsync,
                                weak_ptr_factory_.GetWeakPtr()));
}

void OfflinePageRequestHandler::StartAsync() {
  network_state_ = GetNetworkState();
  if (network_state_ == NetworkState::CONNECTED_NETWORK) {
    delegate_->FallbackToDefault();
    return;
  }

  base::PostTaskWithTraits(
      FROM_HERE, {content::BrowserThread::UI},
      base::BindOnce(&GetPagesToServeURL, url_, offline_header_, network_state_,
                     delegate_->GetWebContentsGetter(),
                     delegate_->GetTabIdGetter(),
                     weak_ptr_factory_.GetWeakPtr()));
}

void OfflinePageRequestHandler::Kill() {
  stream_.reset();
  weak_ptr_factory_.InvalidateWeakPtrs();
}

bool OfflinePageRequestHandler::IsServingOfflinePage() const {
  return candidates_.size() > 0 && candidate_index_ < candidates_.size();
}

scoped_refptr<net::HttpResponseHeaders>
OfflinePageRequestHandler::GetRedirectHeaders() {
  return fake_headers_for_redirect_;
}

int OfflinePageRequestHandler::ReadRawData(net::IOBuffer* dest, int dest_size) {
  DCHECK_NE(dest_size, 0);

  return stream_->Read(
      dest, dest_size,
      base::Bind(&OfflinePageRequestHandler::DidReadForServing,
                 weak_ptr_factory_.GetWeakPtr(), base::WrapRefCounted(dest)));
}

void OfflinePageRequestHandler::OnOfflinePagesAvailable(
    const std::vector<Candidate>& candidates) {
  // If no offline page is found, restart the job to fall back to the default
  // handling.
  if (candidates.empty()) {
    delegate_->FallbackToDefault();
    return;
  }

  file_task_runner_ = base::CreateTaskRunnerWithTraits(
      {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});

  // Start the file validation from the 1st offline page.
  candidates_ = candidates;
  candidate_index_ = 0;
  ValidateFile();
}

void OfflinePageRequestHandler::OnTrustedOfflinePageFound() {
  // If the match is for original URL, trigger the redirect.
  // Note: If the offline page has same orginal URL and final URL, don't trigger
  // the redirect. Some websites might route the redirect finally back to itself
  // after intermediate redirects for authentication. Previously this case was
  // not handled and some pages might be saved with same URLs. Though we fixed
  // the problem, we still need to support those pages already saved with this
  if (url_ == GetCurrentOfflinePage().original_url_if_different &&
      url_ != GetCurrentOfflinePage().url) {
    ReportRequestResult(RequestResult::REDIRECTED, network_state_);
    Redirect(GetCurrentOfflinePage().url);
    return;
  }

  // If the page is being loaded on a slow network, only use the offline page
  // if it was created within the past day.
  if (network_state_ == NetworkState::PROHIBITIVELY_SLOW_NETWORK &&
      OfflineTimeNow() - GetCurrentOfflinePage().creation_time >
          previews::params::OfflinePreviewFreshnessDuration()) {
    ReportRequestResult(RequestResult::PAGE_NOT_FRESH, network_state_);
    delegate_->FallbackToDefault();
    return;
  }

  // No need to open the file if it has already been opened for the validation.
  if (stream_) {
    DidOpenForServing(net::OK);
    return;
  }

  // If a file:// or content:// intent is being processed, open the file:// or
  // content:// denoted in the intent instead. Otherwise, open the archive file
  // associated with the offline page.
  base::FilePath file_path;
  if (IsProcessingFileUrlIntent()) {
    bool valid = net::FileURLToFilePath(offline_header_.intent_url, &file_path);
    DCHECK(valid);
#if defined(OS_ANDROID)
  } else if (IsProcessingContentUrlIntent()) {
    file_path = base::FilePath(offline_header_.intent_url.spec());
    DCHECK(file_path.IsContentUri());
#endif  // defined(OS_ANDROID)
  } else {
    file_path = GetCurrentOfflinePage().file_path;
  }
  OpenFile(file_path, base::Bind(&OfflinePageRequestHandler::DidOpenForServing,
                                 weak_ptr_factory_.GetWeakPtr()));
}

void OfflinePageRequestHandler::VisitTrustedOfflinePage() {
  ReportRequestResult(RequestResult::OFFLINE_PAGE_SERVED, network_state_);
  ReportAccessEntryPoint(GetCurrentOfflinePage().client_id.name_space,
                         GetAccessEntryPoint());
  ReportOfflinePageSize(network_state_, GetCurrentOfflinePage());
  ReportExistenceOfRangeHeader(has_range_header_);

  delegate_->SetOfflinePageNavigationUIData(true /*is_offline_page*/);

  base::PostTaskWithTraits(
      FROM_HERE, {content::BrowserThread::UI},
      base::BindOnce(&VisitTrustedOfflinePageOnUI, offline_header_,
                     network_state_, delegate_->GetWebContentsGetter(),
                     GetCurrentOfflinePage(),
                     candidates_[candidate_index_].archive_is_in_internal_dir));
}

void OfflinePageRequestHandler::Redirect(const GURL& redirected_url) {
  std::string header_string = base::StringPrintf(
      "HTTP/1.1 %i Internal Redirect\n"
      // Clear referrer to avoid leak when going online.
      "Referrer-Policy: no-referrer\n"
      "Location: %s\n"
      "Non-Authoritative-Reason: offline redirects",
      // 302 is used to remove response bodies in order to
      // avoid leak when going online.
      net::URLRequestRedirectJob::REDIRECT_302_FOUND,
      redirected_url.spec().c_str());

  fake_headers_for_redirect_ =
      new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
          header_string.c_str(), header_string.length()));
  DCHECK(fake_headers_for_redirect_->IsRedirect(nullptr));

  delegate_->NotifyHeadersComplete(0);
}

OfflinePageRequestHandler::AccessEntryPoint
OfflinePageRequestHandler::GetAccessEntryPoint() const {
  switch (offline_header_.reason) {
    case OfflinePageHeader::Reason::DOWNLOAD:
      return AccessEntryPoint::DOWNLOADS;
    case OfflinePageHeader::Reason::NOTIFICATION:
      return AccessEntryPoint::NOTIFICATION;
    case OfflinePageHeader::Reason::FILE_URL_INTENT:
      return AccessEntryPoint::FILE_URL_INTENT;
    case OfflinePageHeader::Reason::CONTENT_URL_INTENT:
      return AccessEntryPoint::CONTENT_URL_INTENT;
    case OfflinePageHeader::Reason::PROGRESS_BAR:
      return AccessEntryPoint::PROGRESS_BAR;
    case OfflinePageHeader::Reason::SUGGESTION:
      return AccessEntryPoint::NTP_SUGGESTIONS_OR_BOOKMARKS;
    case OfflinePageHeader::Reason::NET_ERROR_SUGGESTION:
      return AccessEntryPoint::NET_ERROR_PAGE;
    case OfflinePageHeader::Reason::NONE:
    case OfflinePageHeader::Reason::NET_ERROR:
    case OfflinePageHeader::Reason::RELOAD:
      break;
  }

  ui::PageTransition transition =
      static_cast<ui::PageTransition>(delegate_->GetPageTransition());
  if (ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_LINK)) {
    return PageTransitionGetQualifier(transition) ==
                   static_cast<int>(ui::PAGE_TRANSITION_FROM_API)
               ? AccessEntryPoint::CCT
               : AccessEntryPoint::LINK;
  } else if (ui::PageTransitionCoreTypeIs(transition,
                                          ui::PAGE_TRANSITION_TYPED) ||
             ui::PageTransitionCoreTypeIs(transition,
                                          ui::PAGE_TRANSITION_GENERATED)) {
    return AccessEntryPoint::OMNIBOX;
  } else if (ui::PageTransitionCoreTypeIs(transition,
                                          ui::PAGE_TRANSITION_AUTO_BOOKMARK)) {
    // Note that this also includes launching from bookmark which tends to be
    // less likely. For now we don't separate these two.
    return AccessEntryPoint::NTP_SUGGESTIONS_OR_BOOKMARKS;
  } else if (ui::PageTransitionCoreTypeIs(transition,
                                          ui::PAGE_TRANSITION_RELOAD)) {
    return AccessEntryPoint::RELOAD;
  }

  return AccessEntryPoint::UNKNOWN;
}

const OfflinePageItem& OfflinePageRequestHandler::GetCurrentOfflinePage()
    const {
  return candidates_[candidate_index_].offline_page;
}

bool OfflinePageRequestHandler::IsProcessingFileUrlIntent() const {
  return offline_header_.reason == OfflinePageHeader::Reason::FILE_URL_INTENT;
}

bool OfflinePageRequestHandler::IsProcessingContentUrlIntent() const {
  return offline_header_.reason ==
         OfflinePageHeader::Reason::CONTENT_URL_INTENT;
}

bool OfflinePageRequestHandler::IsProcessingFileOrContentUrlIntent() const {
  return IsProcessingFileUrlIntent() || IsProcessingContentUrlIntent();
}

void OfflinePageRequestHandler::OpenFile(
    const base::FilePath& file_path,
    const base::Callback<void(int)>& callback) {
  if (!stream_)
    stream_ = std::make_unique<net::FileStream>(file_task_runner_);

  int flags =
      base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_ASYNC;
#if defined(OS_ANDROID)
  if (!file_path.IsContentUri())
    flags |= base::File::FLAG_EXCLUSIVE_READ;
#else
  flags |= base::File::FLAG_EXCLUSIVE_READ;
#endif  // defined(OS_ANDROID)
  int result = stream_->Open(file_path, flags, callback);
  if (result != net::ERR_IO_PENDING)
    callback.Run(result);
}

void OfflinePageRequestHandler::UpdateDigestOnBackground(
    scoped_refptr<net::IOBuffer> buffer,
    size_t len,
    base::OnceCallback<void(void)> digest_updated_callback) {
  DCHECK_GT(len, 0u);

  if (!archive_validator_)
    archive_validator_ = new ThreadSafeArchiveValidator();

  // Delegate to background task runner to update the hash since it is time
  // consuming. Once it is done, |digest_updated_callback| will be called to
  // continue the reading.
  file_task_runner_->PostTaskAndReply(
      FROM_HERE, base::BindOnce(&UpdateDigest, archive_validator_, buffer, len),
      std::move(digest_updated_callback));
}

void OfflinePageRequestHandler::FinalizeDigestOnBackground(
    base::OnceCallback<void(const std::string&)> digest_finalized_callback) {
  if (!archive_validator_)
    archive_validator_ = new ThreadSafeArchiveValidator();

  // Delegate to background task runner to finalize the hash to get the digest
  // since it is time consuming. Once it is done, |digest_finalized_callback|
  // will be called with the digest.
  base::PostTaskAndReplyWithResult(
      file_task_runner_.get(), FROM_HERE,
      base::BindOnce(&ThreadSafeArchiveValidator::Finish, archive_validator_),
      std::move(digest_finalized_callback));
}

void OfflinePageRequestHandler::ValidateFile() {
  // If the archive file is in internal directory, the offline page can be
  // deemed as trusted without going through valication.
  if (candidates_[candidate_index_].archive_is_in_internal_dir) {
    OnTrustedOfflinePageFound();
    return;
  }

  // Otherwise, the archive file is in public directory. If the digest is empty,
  // the validation can fail immediately.
  if (GetCurrentOfflinePage().digest.empty()) {
    OnFileValidationDone(FileValidationResult::FILE_VALIDATION_FAILED);
    return;
  }

  // If a file:// or content:// URL intent is being viewed, skip the validation.
  // The digest for the file:// or content:// denoted in the intent was computed
  // and used to find the offline page. However, we will not validate and read
  // from the archive archive file assoicated with the offline page since it may
  // not exist or even got modified. We will read from the file:// or content://
  // denoted in the intent  and compute the digest of the read data to make sure
  // it does not get changed.
  if (IsProcessingFileOrContentUrlIntent()) {
    OnFileValidationDone(FileValidationResult::FILE_VALIDATION_SUCCEEDED);
    return;
  }

  GetFileSizeForValidation();
}

void OfflinePageRequestHandler::GetFileSizeForValidation() {
  int64_t* file_size = new int64_t(0);
  file_task_runner_->PostTaskAndReply(
      FROM_HERE,
      base::BindOnce(&GetFileSize, GetCurrentOfflinePage().file_path,
                     base::Unretained(file_size)),
      base::BindOnce(&OfflinePageRequestHandler::DidGetFileSizeForValidation,
                     weak_ptr_factory_.GetWeakPtr(), base::Owned(file_size)));
}

void OfflinePageRequestHandler::DidGetFileSizeForValidation(
    const int64_t* actual_file_size) {
  if (*actual_file_size == -1) {
    OnFileValidationDone(FileValidationResult::FILE_NOT_FOUND);
    return;
  }

  if (*actual_file_size != GetCurrentOfflinePage().file_size) {
    OnFileValidationDone(FileValidationResult::FILE_VALIDATION_FAILED);
    return;
  }

  // Open file to compute the digest.
  OpenFile(GetCurrentOfflinePage().file_path,
           base::Bind(&OfflinePageRequestHandler::DidOpenForValidation,
                      weak_ptr_factory_.GetWeakPtr()));
}

void OfflinePageRequestHandler::DidOpenForValidation(int result) {
  ReportOpenResult(result);

  if (result != net::OK) {
    OnFileValidationDone(FileValidationResult::FILE_VALIDATION_FAILED);
    return;
  }

  if (!buffer_)
    buffer_ = base::MakeRefCounted<net::IOBuffer>(kMaxBufferSizeForValidation);

  ReadForValidation();
}

void OfflinePageRequestHandler::ReadForValidation() {
  int result =
      stream_->Read(buffer_.get(), kMaxBufferSizeForValidation,
                    base::Bind(&OfflinePageRequestHandler::DidReadForValidation,
                               weak_ptr_factory_.GetWeakPtr()));
  if (result != net::ERR_IO_PENDING)
    DidReadForValidation(result);
}

void OfflinePageRequestHandler::DidReadForValidation(int result) {
  ReportReadResult(result);

  if (result < 0) {
    OnFileValidationDone(FileValidationResult::FILE_VALIDATION_FAILED);
    return;
  }

  if (result > 0) {
    UpdateDigestOnBackground(
        buffer_, result,
        base::BindOnce(&OfflinePageRequestHandler::ReadForValidation,
                       weak_ptr_factory_.GetWeakPtr()));
    return;
  }

  // When |result| is 0 (net::OK), it indicates EOF. We need to finalize the
  // hash to get the actual digest.
  FinalizeDigestOnBackground(base::BindOnce(
      &OfflinePageRequestHandler::DidComputeActualDigestForValidation,
      weak_ptr_factory_.GetWeakPtr()));
}

void OfflinePageRequestHandler::DidComputeActualDigestForValidation(
    const std::string& actual_digest) {
  DCHECK(!GetCurrentOfflinePage().digest.empty());
  bool is_trusted = actual_digest == GetCurrentOfflinePage().digest;
  OnFileValidationDone(is_trusted
                           ? FileValidationResult::FILE_VALIDATION_SUCCEEDED
                           : FileValidationResult::FILE_VALIDATION_FAILED);
}

void OfflinePageRequestHandler::OnFileValidationDone(
    FileValidationResult result) {
  if (result == FileValidationResult::FILE_VALIDATION_SUCCEEDED) {
    OnTrustedOfflinePageFound();
    return;
  }

  // The stream is no longer needed.
  stream_.reset();

  // Move to next archive file if there is more.
  candidate_index_++;
  if (candidate_index_ < candidates_.size()) {
    ValidateFile();
    return;
  }

  // Otherwise, no trusted offline page can be found so we fall back to the
  // default handling.
  ReportRequestResult(result == FileValidationResult::FILE_NOT_FOUND
                          ? RequestResult::FILE_NOT_FOUND
                          : RequestResult::DIGEST_MISMATCH,
                      network_state_);
  delegate_->FallbackToDefault();
}

void OfflinePageRequestHandler::DidOpenForServing(int result) {
  ReportOpenResult(result);

  // Handle the file opening failure.
  if (result != net::OK) {
    ReportRequestResult(RequestResult::FILE_NOT_FOUND, network_state_);

    // If the file:// or content:// intent is being processed, don't fall
    // back to the default handling. Instead, we should fail the request.
    if (IsProcessingFileOrContentUrlIntent())
      delegate_->NotifyStartError(net::ERR_FAILED);
    else
      delegate_->FallbackToDefault();
    return;
  }

  // Now we're going to read the archive file to serve the offline page. Do
  // all the necessary reporting and bookkeeping for using this offline page.
  VisitTrustedOfflinePage();

  // Note that we always seek to the beginning of the file because the file may
  // have already been read for validation purpose.
  int seek_result =
      stream_->Seek(0, base::Bind(&OfflinePageRequestHandler::DidSeekForServing,
                                  weak_ptr_factory_.GetWeakPtr()));
  if (seek_result != net::ERR_IO_PENDING)
    DidSeekForServing(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
}

void OfflinePageRequestHandler::DidSeekForServing(int64_t result) {
  DCHECK_LE(result, 0);

  ReportSeekResult(result);

  if (result < 0) {
    delegate_->NotifyStartError(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE);
    return;
  }

  delegate_->NotifyHeadersComplete(GetCurrentOfflinePage().file_size);
}

void OfflinePageRequestHandler::DidReadForServing(
    scoped_refptr<net::IOBuffer> buf,
    int result) {
  ReportReadResult(result);

  if (result < 0 || !IsProcessingFileOrContentUrlIntent()) {
    buf = nullptr;
    NotifyReadRawDataComplete(result);
    return;
  }

  // At this point, we have result >= 0 && IsProcessingFileOrContentUrlIntent()
  // which means the read succeeds for processing the file:// or content:// URL
  // intent. We need to compute the digest to ensure that the file:// or
  // content:// we read is not modified since the time we received the intent,
  // validated the data provided by file:// or content:// URL, and decided to
  // turn it into the corresponding http/https URL and let
  // OfflinePageRequestHandler handle it.
  if (result > 0) {
    UpdateDigestOnBackground(
        buf, result,
        base::BindOnce(&OfflinePageRequestHandler::NotifyReadRawDataComplete,
                       weak_ptr_factory_.GetWeakPtr(), result));

  } else {
    // When |result| is 0 (net::OK), it indicates EOF. We need to finalize the
    // hash to get the actual digest.
    FinalizeDigestOnBackground(base::BindOnce(
        &OfflinePageRequestHandler::DidComputeActualDigestForServing,
        weak_ptr_factory_.GetWeakPtr(), result));
  }
}

void OfflinePageRequestHandler::NotifyReadRawDataComplete(int result) {
  delegate_->NotifyReadRawDataComplete(result);
}

void OfflinePageRequestHandler::DidComputeActualDigestForServing(
    int result,
    const std::string& actual_digest) {
  // If the actual digest does not match, fail the request job.
  bool mismatch = actual_digest != GetCurrentOfflinePage().digest;
  ReportIntentDataChangedAfterValidation(mismatch);
  if (mismatch) {
    // Note: Do not call delegate_->SetOfflinePageNavigationUIData to clear
    // the offline bit since SetOfflinePageNavigationUIData is supposed to
    // be called before the response is being received. Furthermore, there is
    // no need to clear the offline bit since the error code should already
    // indicate that the offline page is not loaded.
    base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
                             base::BindOnce(&ClearOfflinePageData,
                                            delegate_->GetWebContentsGetter()));
    result = net::ERR_FAILED;
  }

  NotifyReadRawDataComplete(result);
}

}  // namespace offline_pages
