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

#include "pdf/document_loader_impl.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <utility>

#include "base/logging.h"
#include "base/numerics/safe_math.h"
#include "base/strings/string_util.h"
#include "pdf/url_loader_wrapper.h"
#include "ppapi/c/pp_errors.h"
#include "ui/gfx/range/range.h"

namespace chrome_pdf {

namespace {

// The distance from last received chunk, when we wait requesting data, using
// current connection (like playing a cassette tape) and do not send new range
// request (like rewind a cassette tape, and continue playing after).
// Experimentally chosen value.
constexpr int kChunkCloseDistance = 10;

// Return true if the HTTP response of |loader| is a successful one and loading
// should continue. 4xx error indicate subsequent requests will fail too.
// e.g. resource has been removed from the server while loading it. 301
// indicates a redirect was returned which won't be successful because we
// disable following redirects for PDF loading (we assume they are already
// resolved by the browser.
bool ResponseStatusSuccess(const URLLoaderWrapper* loader) {
  int32_t http_code = loader->GetStatusCode();
  return (http_code < 400 && http_code != 301) || http_code >= 500;
}

bool IsValidContentType(const std::string& type) {
  return (
      base::EndsWith(type, "/pdf", base::CompareCase::INSENSITIVE_ASCII) ||
      base::EndsWith(type, ".pdf", base::CompareCase::INSENSITIVE_ASCII) ||
      base::EndsWith(type, "/x-pdf", base::CompareCase::INSENSITIVE_ASCII) ||
      base::EndsWith(type, "/*", base::CompareCase::INSENSITIVE_ASCII) ||
      base::EndsWith(type, "/octet-stream",
                     base::CompareCase::INSENSITIVE_ASCII) ||
      base::EndsWith(type, "/acrobat", base::CompareCase::INSENSITIVE_ASCII) ||
      base::EndsWith(type, "/unknown", base::CompareCase::INSENSITIVE_ASCII));
}

}  // namespace

DocumentLoaderImpl::Chunk::Chunk() = default;

DocumentLoaderImpl::Chunk::~Chunk() = default;

void DocumentLoaderImpl::Chunk::Clear() {
  chunk_index = 0;
  data_size = 0;
  chunk_data.reset();
}

DocumentLoaderImpl::DocumentLoaderImpl(Client* client)
    : client_(client), loader_factory_(this) {}

DocumentLoaderImpl::~DocumentLoaderImpl() = default;

bool DocumentLoaderImpl::Init(std::unique_ptr<URLLoaderWrapper> loader,
                              const std::string& url) {
  DCHECK(url_.empty());
  DCHECK(!loader_);

  // Check that the initial response status is a valid one.
  if (!ResponseStatusSuccess(loader.get()))
    return false;

  std::string type = loader->GetContentType();

  // This happens for PDFs not loaded from http(s) sources.
  if (type == "text/plain") {
    if (!base::StartsWith(url, "http://",
                          base::CompareCase::INSENSITIVE_ASCII) &&
        !base::StartsWith(url, "https://",
                          base::CompareCase::INSENSITIVE_ASCII)) {
      type = "application/pdf";
    }
  }
  if (!type.empty() && !IsValidContentType(type))
    return false;

  if (base::StartsWith(loader->GetContentDisposition(), "attachment",
                       base::CompareCase::INSENSITIVE_ASCII))
    return false;

  url_ = url;
  loader_ = std::move(loader);

  if (!loader_->IsContentEncoded())
    SetDocumentSize(std::max(0, loader_->GetContentLength()));

  int64_t bytes_received = 0;
  int64_t total_bytes_to_be_received = 0;
  if (GetDocumentSize() == 0 &&
      loader_->GetDownloadProgress(&bytes_received,
                                   &total_bytes_to_be_received)) {
    SetDocumentSize(std::max(0, static_cast<int>(total_bytes_to_be_received)));
  }

  SetPartialLoadingEnabled(
      partial_loading_enabled_ &&
      !base::StartsWith(url, "file://", base::CompareCase::INSENSITIVE_ASCII) &&
      loader_->IsAcceptRangesBytes() && !loader_->IsContentEncoded() &&
      GetDocumentSize());

  ReadMore();
  return true;
}

bool DocumentLoaderImpl::IsDocumentComplete() const {
  return chunk_stream_.IsComplete();
}

void DocumentLoaderImpl::SetDocumentSize(uint32_t size) {
  chunk_stream_.set_eof_pos(size);
}

uint32_t DocumentLoaderImpl::GetDocumentSize() const {
  return chunk_stream_.eof_pos();
}

uint32_t DocumentLoaderImpl::BytesReceived() const {
  return bytes_received_;
}

void DocumentLoaderImpl::ClearPendingRequests() {
  pending_requests_.Clear();
}

bool DocumentLoaderImpl::GetBlock(uint32_t position,
                                  uint32_t size,
                                  void* buf) const {
  base::CheckedNumeric<uint32_t> addition_result = position;
  addition_result += size;
  if (!addition_result.IsValid())
    return false;
  return chunk_stream_.ReadData(
      gfx::Range(position, addition_result.ValueOrDie()), buf);
}

bool DocumentLoaderImpl::IsDataAvailable(uint32_t position,
                                         uint32_t size) const {
  base::CheckedNumeric<uint32_t> addition_result = position;
  addition_result += size;
  if (!addition_result.IsValid())
    return false;
  return chunk_stream_.IsRangeAvailable(
      gfx::Range(position, addition_result.ValueOrDie()));
}

void DocumentLoaderImpl::RequestData(uint32_t position, uint32_t size) {
  if (size == 0 || IsDataAvailable(position, size))
    return;

  const uint32_t document_size = GetDocumentSize();
  if (document_size != 0) {
    // Check for integer overflow.
    base::CheckedNumeric<uint32_t> addition_result = position;
    addition_result += size;
    if (!addition_result.IsValid())
      return;

    if (addition_result.ValueOrDie() > document_size)
      return;
  }

  // We have some artifact request from
  // PDFiumEngine::OnDocumentComplete() -> FPDFAvail_IsPageAvail after
  // document is complete.
  // We need this fix in PDFIum. Adding this as a work around.
  // Bug: http://code.google.com/p/chromium/issues/detail?id=79996
  // Test url:
  // http://www.icann.org/en/correspondence/holtzman-to-jeffrey-02mar11-en.pdf
  if (!loader_)
    return;

  RangeSet requested_chunks(chunk_stream_.GetChunksRange(position, size));
  requested_chunks.Subtract(chunk_stream_.filled_chunks());
  if (requested_chunks.IsEmpty()) {
    NOTREACHED();
    return;
  }
  pending_requests_.Union(requested_chunks);
}

void DocumentLoaderImpl::SetPartialLoadingEnabled(bool enabled) {
  partial_loading_enabled_ = enabled;
  if (!enabled) {
    is_partial_loader_active_ = false;
  }
}

bool DocumentLoaderImpl::ShouldCancelLoading() const {
  if (!loader_)
    return true;

  if (!partial_loading_enabled_)
    return false;

  if (pending_requests_.IsEmpty()) {
    // Cancel loading if this is unepected data from server.
    return !chunk_stream_.IsValidChunkIndex(chunk_.chunk_index) ||
           chunk_stream_.IsChunkAvailable(chunk_.chunk_index);
  }

  const gfx::Range current_range(chunk_.chunk_index,
                                 chunk_.chunk_index + kChunkCloseDistance);
  return !pending_requests_.Intersects(current_range);
}

void DocumentLoaderImpl::ContinueDownload() {
  if (!ShouldCancelLoading())
    return ReadMore();

  DCHECK(partial_loading_enabled_);
  DCHECK(!IsDocumentComplete());
  DCHECK_GT(GetDocumentSize(), 0U);

  const uint32_t range_start =
      pending_requests_.IsEmpty() ? 0 : pending_requests_.First().start();
  RangeSet candidates_for_request(
      gfx::Range(range_start, chunk_stream_.total_chunks_count()));
  candidates_for_request.Subtract(chunk_stream_.filled_chunks());
  DCHECK(!candidates_for_request.IsEmpty());
  gfx::Range next_request = candidates_for_request.First();
  if (candidates_for_request.Size() == 1 &&
      next_request.length() < kChunkCloseDistance) {
    // We have only request at the end, try to enlarge it to improve back order
    // reading.
    const int additional_chunks_count =
        kChunkCloseDistance - next_request.length();
    int new_start = std::max(
        0, static_cast<int>(next_request.start()) - additional_chunks_count);
    candidates_for_request =
        RangeSet(gfx::Range(new_start, next_request.end()));
    candidates_for_request.Subtract(chunk_stream_.filled_chunks());
    next_request = candidates_for_request.Last();
  }

  loader_.reset();
  chunk_.Clear();
  if (!is_partial_loader_active_) {
    client_->CancelBrowserDownload();
    is_partial_loader_active_ = true;
  }

  const uint32_t start = next_request.start() * DataStream::kChunkSize;
  const uint32_t length =
      std::min(GetDocumentSize() - start,
               next_request.length() * DataStream::kChunkSize);

  loader_ = client_->CreateURLLoader();

  loader_->OpenRange(
      url_, url_, start, length,
      loader_factory_.NewCallback(&DocumentLoaderImpl::DidOpenPartial));
}

void DocumentLoaderImpl::DidOpenPartial(int32_t result) {
  if (result != PP_OK) {
    return ReadComplete();
  }

  if (!ResponseStatusSuccess(loader_.get()))
    return ReadComplete();

  // Leave position untouched for multiparted responce for now, when we read the
  // data we'll get it.
  if (loader_->IsMultipart()) {
    // Needs more data to calc chunk index.
    return ReadMore();
  }

  // Need to make sure that the server returned a byte-range, since it's
  // possible for a server to just ignore our byte-range request and just
  // return the entire document even if it supports byte-range requests.
  // i.e. sniff response to
  // http://www.act.org/compass/sample/pdf/geometry.pdf
  int start_pos = 0;
  if (loader_->GetByteRangeStart(&start_pos)) {
    if (start_pos % DataStream::kChunkSize != 0)
      return ReadComplete();

    DCHECK(!chunk_.chunk_data);
    chunk_.chunk_index = chunk_stream_.GetChunkIndex(start_pos);
  } else {
    SetPartialLoadingEnabled(false);
  }
  return ContinueDownload();
}

void DocumentLoaderImpl::ReadMore() {
  loader_->ReadResponseBody(
      buffer_, sizeof(buffer_),
      loader_factory_.NewCallback(&DocumentLoaderImpl::DidRead));
}

void DocumentLoaderImpl::DidRead(int32_t result) {
  if (result < 0) {
    // An error occurred.
    // The renderer will detect that we're missing data and will display a
    // message.
    return ReadComplete();
  }
  if (result == 0) {
    loader_.reset();
    if (!is_partial_loader_active_)
      return ReadComplete();
    return ContinueDownload();
  }
  if (loader_->IsMultipart()) {
    int start_pos = 0;
    if (!loader_->GetByteRangeStart(&start_pos))
      return ReadComplete();

    DCHECK(!chunk_.chunk_data);
    chunk_.chunk_index = chunk_stream_.GetChunkIndex(start_pos);
  }
  if (!SaveBuffer(buffer_, result))
    return ReadMore();
  if (IsDocumentComplete())
    return ReadComplete();
  return ContinueDownload();
}

bool DocumentLoaderImpl::SaveBuffer(char* input, uint32_t input_size) {
  const uint32_t document_size = GetDocumentSize();
  bytes_received_ += input_size;
  bool chunk_saved = false;
  bool loading_pending_request = pending_requests_.Contains(chunk_.chunk_index);
  while (input_size > 0) {
    if (chunk_.data_size == 0)
      chunk_.chunk_data = std::make_unique<DataStream::ChunkData>();

    const uint32_t new_chunk_data_len =
        std::min(DataStream::kChunkSize - chunk_.data_size, input_size);
    memcpy(chunk_.chunk_data->data() + chunk_.data_size, input,
           new_chunk_data_len);
    chunk_.data_size += new_chunk_data_len;
    if (chunk_.data_size == DataStream::kChunkSize ||
        (document_size > 0 && document_size <= EndOfCurrentChunk())) {
      pending_requests_.Subtract(
          gfx::Range(chunk_.chunk_index, chunk_.chunk_index + 1));
      SaveChunkData();
      chunk_saved = true;
    }

    input += new_chunk_data_len;
    input_size -= new_chunk_data_len;
  }

  client_->OnNewDataReceived();

  if (IsDocumentComplete())
    return true;

  if (!chunk_saved)
    return false;

  if (loading_pending_request &&
      !pending_requests_.Contains(chunk_.chunk_index)) {
    client_->OnPendingRequestComplete();
  }
  return true;
}

void DocumentLoaderImpl::SaveChunkData() {
  chunk_stream_.SetChunkData(chunk_.chunk_index, std::move(chunk_.chunk_data));
  chunk_.data_size = 0;
  ++chunk_.chunk_index;
}

uint32_t DocumentLoaderImpl::EndOfCurrentChunk() const {
  return chunk_.chunk_index * DataStream::kChunkSize + chunk_.data_size;
}

void DocumentLoaderImpl::ReadComplete() {
  if (GetDocumentSize() != 0) {
    // If there is remaining data in |chunk_|, then save whatever can be saved.
    // e.g. In the underrun case.
    if (chunk_.data_size != 0)
      SaveChunkData();
  } else {
    uint32_t eof = EndOfCurrentChunk();
    if (!chunk_stream_.filled_chunks().IsEmpty()) {
      eof = std::max(
          chunk_stream_.filled_chunks().Last().end() * DataStream::kChunkSize,
          eof);
    }
    SetDocumentSize(eof);
    if (eof == EndOfCurrentChunk())
      SaveChunkData();
  }
  loader_.reset();
  if (IsDocumentComplete()) {
    client_->OnDocumentComplete();
  } else {
    client_->OnDocumentCanceled();
  }
}

}  // namespace chrome_pdf
