// Copyright 2015 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 "content/child/blob_storage/blob_transport_controller.h"

#include <limits>
#include <memory>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/files/file.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/shared_memory.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/task_runner.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "content/child/blob_storage/blob_consolidation.h"
#include "content/child/child_process.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/fileapi/webblob_messages.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
#include "storage/common/blob_storage/blob_item_bytes_request.h"
#include "storage/common/blob_storage/blob_item_bytes_response.h"
#include "storage/common/data_element.h"
#include "third_party/WebKit/public/platform/Platform.h"

using base::File;
using base::SharedMemory;
using base::SharedMemoryHandle;
using storage::BlobItemBytesRequest;
using storage::BlobItemBytesResponse;
using storage::IPCBlobItemRequestStrategy;
using storage::DataElement;

using storage::BlobItemBytesResponse;
using storage::BlobItemBytesRequest;
using storage::BlobStatus;

namespace content {
using ConsolidatedItem = BlobConsolidation::ConsolidatedItem;
using ReadStatus = BlobConsolidation::ReadStatus;

namespace {
static base::LazyInstance<BlobTransportController>::Leaky g_controller =
    LAZY_INSTANCE_INITIALIZER;

// This keeps the process alive while blobs are being transferred.
// These need to be called on the main thread.
void IncChildProcessRefCount() {
  blink::Platform::current()->suddenTerminationChanged(false);
  ChildProcess::current()->AddRefProcess();
}

void DecChildProcessRefCount() {
  blink::Platform::current()->suddenTerminationChanged(true);
  ChildProcess::current()->ReleaseProcess();
}

void DecChildProcessRefCountTimes(size_t times) {
  for (size_t i = 0; i < times; i++) {
    DecChildProcessRefCount();
  }
}

bool WriteSingleChunk(base::File* file, const char* memory, size_t size) {
  size_t written = 0;
  while (written < size) {
    size_t writing_size = base::saturated_cast<int>(size - written);
    int actual_written =
        file->WriteAtCurrentPos(memory, static_cast<int>(writing_size));
    bool write_failed = actual_written < 0;
    UMA_HISTOGRAM_BOOLEAN("Storage.Blob.RendererFileWriteFailed", write_failed);
    if (write_failed)
      return false;
    written += actual_written;
  }
  return true;
}

bool WriteSingleRequestToDisk(const BlobConsolidation* consolidation,
                              const BlobItemBytesRequest& request,
                              File* file) {
  if (!file->IsValid())
    return false;
  int64_t seek_distance = file->Seek(
      File::FROM_BEGIN, base::checked_cast<int64_t>(request.handle_offset));
  bool seek_failed = seek_distance < 0;
  UMA_HISTOGRAM_BOOLEAN("Storage.Blob.RendererFileSeekFailed", seek_failed);
  if (seek_failed)
    return false;
  BlobConsolidation::ReadStatus status = consolidation->VisitMemory(
      request.renderer_item_index, request.renderer_item_offset, request.size,
      base::Bind(&WriteSingleChunk, file));
  if (status != BlobConsolidation::ReadStatus::OK)
    return false;
  return true;
}

base::Optional<std::vector<BlobItemBytesResponse>> WriteDiskRequests(
    scoped_refptr<BlobConsolidation> consolidation,
    std::unique_ptr<std::vector<BlobItemBytesRequest>> requests,
    const std::vector<IPC::PlatformFileForTransit>& file_handles) {
  std::vector<BlobItemBytesResponse> responses;
  // We grab ownership of the file handles here. When this vector is destroyed
  // it will close the files.
  std::vector<File> files;
  files.reserve(file_handles.size());
  for (const auto& file_handle : file_handles) {
    files.emplace_back(IPC::PlatformFileForTransitToFile(file_handle));
  }
  for (const auto& request : *requests) {
    if (!WriteSingleRequestToDisk(consolidation.get(), request,
                                  &files[request.handle_index])) {
      return base::nullopt;
    }
  }
  // The last modified time needs to be collected after we flush the file.
  std::vector<base::Time> last_modified_times;
  last_modified_times.resize(file_handles.size());
  for (size_t i = 0; i < files.size(); ++i) {
    auto& file = files[i];
    if (!file.Flush())
      return base::nullopt;
    File::Info info;
    if (!file.GetInfo(&info))
      return base::nullopt;
    last_modified_times[i] = info.last_modified;
  }

  for (const auto& request : *requests) {
    responses.push_back(BlobItemBytesResponse(request.request_number));
    responses.back().time_file_modified =
        last_modified_times[request.handle_index];
  }

  return responses;
}

}  // namespace

BlobTransportController* BlobTransportController::GetInstance() {
  return g_controller.Pointer();
}

// static
void BlobTransportController::InitiateBlobTransfer(
    const std::string& uuid,
    const std::string& content_type,
    scoped_refptr<BlobConsolidation> consolidation,
    scoped_refptr<ThreadSafeSender> sender,
    base::SingleThreadTaskRunner* io_runner,
    scoped_refptr<base::SingleThreadTaskRunner> main_runner) {
  if (main_runner->BelongsToCurrentThread()) {
    IncChildProcessRefCount();
  } else {
    main_runner->PostTask(FROM_HERE, base::Bind(&IncChildProcessRefCount));
  }

  storage::BlobStorageLimits quotas;
  std::vector<storage::DataElement> descriptions;
  BlobTransportController::GetDescriptions(
      consolidation.get(), quotas.max_ipc_memory_size, &descriptions);
  // I post the task first to make sure that we store our consolidation before
  // we get a request back from the browser.
  io_runner->PostTask(
      FROM_HERE,
      base::Bind(&BlobTransportController::StoreBlobDataForRequests,
                 base::Unretained(BlobTransportController::GetInstance()), uuid,
                 base::Passed(std::move(consolidation)),
                 base::Passed(std::move(main_runner))));
  sender->Send(
      new BlobStorageMsg_RegisterBlob(uuid, content_type, "", descriptions));
}

void BlobTransportController::OnMemoryRequest(
    const std::string& uuid,
    const std::vector<storage::BlobItemBytesRequest>& requests,
    std::vector<base::SharedMemoryHandle>* memory_handles,
    const std::vector<IPC::PlatformFileForTransit>& file_handles,
    base::TaskRunner* file_runner,
    IPC::Sender* sender) {
  std::vector<BlobItemBytesResponse> responses;
  auto it = blob_storage_.find(uuid);
  // Ignore invalid messages.
  if (it == blob_storage_.end())
    return;

  BlobConsolidation* consolidation = it->second.get();
  const auto& consolidated_items = consolidation->consolidated_items();

  std::unique_ptr<std::vector<BlobItemBytesRequest>> file_requests(
      new std::vector<BlobItemBytesRequest>());

  // Since we can be writing to the same shared memory handle from multiple
  // requests, we keep them in a vector and lazily create them.
  ScopedVector<SharedMemory> opened_memory;
  opened_memory.resize(memory_handles->size());

  // We need to calculate how much memory we expect to be writing to the memory
  // segments so we can correctly map it the first time.
  std::vector<size_t> shared_memory_sizes(memory_handles->size());
  for (const BlobItemBytesRequest& request : requests) {
    if (request.transport_strategy !=
        IPCBlobItemRequestStrategy::SHARED_MEMORY) {
      continue;
    }
    DCHECK_LT(request.handle_index, memory_handles->size())
        << "Invalid handle index.";
    shared_memory_sizes[request.handle_index] =
        std::max<size_t>(shared_memory_sizes[request.handle_index],
                         request.size + request.handle_offset);
  }

  for (const BlobItemBytesRequest& request : requests) {
    DCHECK_LT(request.renderer_item_index, consolidated_items.size())
        << "Invalid item index";

    const ConsolidatedItem& item =
        consolidated_items[request.renderer_item_index];
    DCHECK_LE(request.renderer_item_offset + request.size, item.length)
        << "Invalid data range";
    DCHECK_EQ(item.type, DataElement::TYPE_BYTES) << "Invalid element type";

    switch (request.transport_strategy) {
      case IPCBlobItemRequestStrategy::IPC: {
        responses.push_back(BlobItemBytesResponse(request.request_number));
        BlobItemBytesResponse& response = responses.back();
        ReadStatus status = consolidation->ReadMemory(
            request.renderer_item_index, request.renderer_item_offset,
            request.size, response.allocate_mutable_data(request.size));
        DCHECK(status == ReadStatus::OK)
            << "Error reading from consolidated blob: "
            << static_cast<int>(status);
        break;
      }
      case IPCBlobItemRequestStrategy::SHARED_MEMORY: {
        responses.push_back(BlobItemBytesResponse(request.request_number));
        SharedMemory* memory = opened_memory[request.handle_index];
        if (!memory) {
          SharedMemoryHandle& handle = (*memory_handles)[request.handle_index];
          size_t size = shared_memory_sizes[request.handle_index];
          DCHECK(SharedMemory::IsHandleValid(handle));
          std::unique_ptr<SharedMemory> shared_memory(
              new SharedMemory(handle, false));

          if (!shared_memory->Map(size)) {
            // This would happen if the renderer process doesn't have enough
            // memory to map the shared memory, which is possible if we don't
            // have much memory. If this scenario happens often, we could delay
            // the response until we have enough memory.  For now we just fail.
            CHECK(false) << "Unable to map shared memory to send blob " << uuid
                         << ".";
            return;
          }
          memory = shared_memory.get();
          opened_memory[request.handle_index] = shared_memory.release();
        }
        CHECK(memory->memory()) << "Couldn't map memory for blob transfer.";
        ReadStatus status = consolidation->ReadMemory(
            request.renderer_item_index, request.renderer_item_offset,
            request.size,
            static_cast<char*>(memory->memory()) + request.handle_offset);
        DCHECK(status == ReadStatus::OK)
            << "Error reading from consolidated blob: "
            << static_cast<int>(status);
        break;
      }
      case IPCBlobItemRequestStrategy::FILE:
        DCHECK_LT(request.handle_index, file_handles.size())
            << "Invalid handle index.";
        file_requests->push_back(request);
        break;
      case IPCBlobItemRequestStrategy::UNKNOWN:
        NOTREACHED();
        break;
    }
  }
  if (!file_requests->empty()) {
    base::PostTaskAndReplyWithResult(
        file_runner, FROM_HERE,
        base::Bind(&WriteDiskRequests, make_scoped_refptr(consolidation),
                   base::Passed(&file_requests), file_handles),
        base::Bind(&BlobTransportController::OnFileWriteComplete,
                   weak_factory_.GetWeakPtr(), sender, uuid));
  }

  if (!responses.empty())
    sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, responses));
}

void BlobTransportController::OnBlobFinalStatus(const std::string& uuid,
                                                storage::BlobStatus code) {
  DVLOG_IF(1, storage::BlobStatusIsError(code))
      << "Received blob error for blob " << uuid
      << " with code: " << static_cast<int>(code);
  DCHECK(!BlobStatusIsPending(code));
  ReleaseBlobConsolidation(uuid);
}

void BlobTransportController::CancelAllBlobTransfers() {
  weak_factory_.InvalidateWeakPtrs();
  if (!blob_storage_.empty() && main_thread_runner_) {
    main_thread_runner_->PostTask(
        FROM_HERE,
        base::Bind(&DecChildProcessRefCountTimes, blob_storage_.size()));
  }
  main_thread_runner_ = nullptr;
  blob_storage_.clear();
}

// static
void BlobTransportController::GetDescriptions(
    BlobConsolidation* consolidation,
    size_t max_data_population,
    std::vector<storage::DataElement>* out) {
  DCHECK(out->empty());
  DCHECK(consolidation);
  const auto& consolidated_items = consolidation->consolidated_items();

  size_t current_memory_population = 0;
  size_t current_item = 0;
  out->reserve(consolidated_items.size());
  for (const ConsolidatedItem& item : consolidated_items) {
    out->push_back(DataElement());
    auto& element = out->back();

    switch (item.type) {
      case DataElement::TYPE_BYTES: {
        size_t bytes_length = static_cast<size_t>(item.length);
        if (current_memory_population + bytes_length <= max_data_population) {
          element.SetToAllocatedBytes(bytes_length);
          consolidation->ReadMemory(current_item, 0, bytes_length,
                                    element.mutable_bytes());
          current_memory_population += bytes_length;
        } else {
          element.SetToBytesDescription(bytes_length);
        }
        break;
      }
      case DataElement::TYPE_FILE: {
        element.SetToFilePathRange(
            item.path, item.offset, item.length,
            base::Time::FromDoubleT(item.expected_modification_time));
        break;
      }
      case DataElement::TYPE_BLOB: {
        element.SetToBlobRange(item.blob_uuid, item.offset, item.length);
        break;
      }
      case DataElement::TYPE_FILE_FILESYSTEM: {
        element.SetToFileSystemUrlRange(
            item.filesystem_url, item.offset, item.length,
            base::Time::FromDoubleT(item.expected_modification_time));
        break;
      }
      case DataElement::TYPE_DISK_CACHE_ENTRY:
      case DataElement::TYPE_BYTES_DESCRIPTION:
      case DataElement::TYPE_UNKNOWN:
        NOTREACHED();
    }
    ++current_item;
  }
}

BlobTransportController::BlobTransportController() : weak_factory_(this) {}

BlobTransportController::~BlobTransportController() {}

void BlobTransportController::OnFileWriteComplete(
    IPC::Sender* sender,
    const std::string& uuid,
    const base::Optional<std::vector<storage::BlobItemBytesResponse>>& result) {
  if (blob_storage_.find(uuid) == blob_storage_.end())
    return;
  if (!result) {
    sender->Send(new BlobStorageMsg_SendBlobStatus(
        uuid, BlobStatus::ERR_FILE_WRITE_FAILED));
    ReleaseBlobConsolidation(uuid);
    return;
  }
  sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, result.value()));
}

void BlobTransportController::StoreBlobDataForRequests(
    const std::string& uuid,
    scoped_refptr<BlobConsolidation> consolidation,
    scoped_refptr<base::SingleThreadTaskRunner> main_runner) {
  if (!main_thread_runner_.get()) {
    main_thread_runner_ = std::move(main_runner);
  }
  blob_storage_[uuid] = std::move(consolidation);
}

void BlobTransportController::ReleaseBlobConsolidation(
    const std::string& uuid) {
  if (blob_storage_.erase(uuid)) {
    main_thread_runner_->PostTask(FROM_HERE,
                                  base::Bind(&DecChildProcessRefCount));
  }
}

}  // namespace content
