// 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 "shell/crash/crash_upload.h"

#include "base/bind.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/strings/string_util.h"
#include "base/task_runner_util.h"
#include "mojo/data_pipe_utils/data_pipe_utils.h"
#include "mojo/services/network/public/interfaces/url_loader.mojom.h"

namespace breakpad {

namespace {

#ifdef NDEBUG
const char kCrashUploadURL[] = "https://clients2.google.com/cr/report";
#else
const char kCrashUploadURL[] = "https://clients2.google.com/cr/staging_report";
#endif
// Minimal delay between two requests to the crash server. This delay is ensured
// by saving a sentinel file each time a request is made.
const int kDelayBetweenCrashesInSeconds = 3600;

// The max size of a multipart/* boundary is 70, but the boundary is prefixed by
// 2 hyphens, and suffixed by an end of line character.
const int kMaxBoundarySize = 73;

struct MinidumpAndBoundary {
  MinidumpAndBoundary() {}
  MinidumpAndBoundary(const base::FilePath& minidump,
                      const std::string& boundary)
      : minidump(minidump), boundary(boundary) {}

  // The path to the minidump file.
  base::FilePath minidump;
  // The boundary for the multipart mime header. This is computed from the
  // content of the minidump.
  std::string boundary;
};

void OnCrashServerResponse(const base::FilePath& minidump,
                           mojo::URLResponsePtr response) {
  base::DeleteFile(minidump, false);
  if (response->status_code == 200) {
    std::string crash_id;
    mojo::common::BlockingCopyToString(response->body.Pass(), &crash_id);
    LOG(INFO) << "Crash uploaded with id: '" << crash_id << "'";
  } else {
    LOG(ERROR) << "Unable to upload crash report. HTTP status: "
               << response->status_code;
  }
}

void OnUploadCrashComplete(const base::FilePath& minidump,
                           scoped_refptr<base::TaskRunner> file_task_runner,
                           mojo::URLLoaderPtr url_loader,
                           mojo::URLResponsePtr response) {
  file_task_runner->PostTask(FROM_HERE,
                             base::Bind(&OnCrashServerResponse, minidump,
                                        base::Passed(response.Pass())));
}

void IgnoreResult(bool result) {
}

// Returns the path to the sentinel. The sentinel is a file whose last modified
// time record the time at which the last request to the crash server was made.
base::FilePath GetFileSentinel(const base::FilePath& dumps_path) {
  return dumps_path.Append("upload.sentinel");
}

void UpdateFileSentinel(const base::FilePath& dumps_path) {
  base::FilePath sentinel = GetFileSentinel(dumps_path);
  int write_return_value = WriteFile(sentinel, nullptr, 0);
  DCHECK_EQ(0, write_return_value);
  bool touch_return_value =
      base::TouchFile(sentinel, base::Time::Now(), base::Time::Now());
  DCHECK(touch_return_value);
}

bool CanUploadCrash(const base::FilePath& dumps_path) {
  base::FilePath sentinel = GetFileSentinel(dumps_path);
  if (!base::PathExists(sentinel))
    return true;
  base::File::Info info;
  if (!GetFileInfo(sentinel, &info)) {
    // Something very wrong happened. Recreate the sentinel and wait for next
    // restart.
    bool return_value = base::DeleteFile(sentinel, true);
    DCHECK(return_value);
    UpdateFileSentinel(dumps_path);
    return false;
  }
  return (base::Time::Now() - info.last_modified) >
         base::TimeDelta::FromSeconds(kDelayBetweenCrashesInSeconds);
}

void UploadCrash(scoped_refptr<base::TaskRunner> file_task_runner,
                 mojo::NetworkServicePtr network_service,
                 const base::FilePath& dumps_path,
                 const MinidumpAndBoundary& minidump_and_boundary) {
  const base::FilePath& minidump = minidump_and_boundary.minidump;
  const std::string& boundary = minidump_and_boundary.boundary;
  if (minidump.empty())
    return;
  mojo::URLRequestPtr request = mojo::URLRequest::New();
  request->url = kCrashUploadURL;
  request->method = "POST";
  auto header = mojo::HttpHeader::New();
  header->name = "Content-Type";
  header->value = "multipart/form-data; boundary=" + boundary;
  request->headers.push_back(header.Pass());
  mojo::DataPipe pipe;
  request->body.push_back(pipe.consumer_handle.Pass());
  mojo::common::CopyFromFile(minidump, pipe.producer_handle.Pass(), 0,
                             file_task_runner.get(), base::Bind(&IgnoreResult));

  mojo::URLLoaderPtr url_loader;
  network_service->CreateURLLoader(GetProxy(&url_loader));
  mojo::URLLoader* loader_ptr = url_loader.get();

  // Update the sentinel before starting the network request. This will prevent
  // any other request to the crash server for one hour.
  UpdateFileSentinel(dumps_path);

  loader_ptr->Start(
      request.Pass(),
      base::Bind(&OnUploadCrashComplete, minidump, file_task_runner,
                 base::Passed(url_loader.Pass())));
}

MinidumpAndBoundary GetMinidumpAndBoundary(const base::FilePath& dumps_path) {
  // Find the last modified minidump. Delete all the other ones.
  base::FilePath minidump;
  base::Time last_modified_time;
  base::FileEnumerator files(dumps_path, false, base::FileEnumerator::FILES,
                             FILE_PATH_LITERAL("*.dmp"));
  for (base::FilePath file = files.Next(); !file.empty(); file = files.Next()) {
    if (minidump.empty()) {
      minidump = file;
      last_modified_time = files.GetInfo().GetLastModifiedTime();
    } else {
      if (files.GetInfo().GetLastModifiedTime() < last_modified_time) {
        base::DeleteFile(file, false);
      } else {
        base::DeleteFile(minidump, false);
        minidump = file;
        last_modified_time = files.GetInfo().GetLastModifiedTime();
      }
    }
  }

  if (minidump.empty() || !CanUploadCrash(dumps_path))
    return MinidumpAndBoundary();
  // Find multipart boundary.
  std::string start_of_file;
  base::ReadFileToString(minidump, &start_of_file, kMaxBoundarySize);
  if (!StartsWithASCII(start_of_file, "--", true)) {
    LOG(WARNING) << "Corrupted minidump: " << minidump.value();
    base::DeleteFile(minidump, false);
    return MinidumpAndBoundary();
  }
  size_t space_index = start_of_file.find_first_of(base::kWhitespaceASCII);
  if (space_index == std::string::npos || space_index <= 2) {
    // The boundary is either too big, or too short.
    LOG(WARNING) << "Corrupted minidump: " << minidump.value();
    base::DeleteFile(minidump, false);
    return MinidumpAndBoundary();
  }
  return MinidumpAndBoundary(minidump,
                             start_of_file.substr(2, space_index - 2));
}

}  // namespace

void UploadCrashes(const base::FilePath& dumps_path,
                   scoped_refptr<base::TaskRunner> file_task_runner,
                   mojo::NetworkServicePtr network_service) {
  base::PostTaskAndReplyWithResult(
      file_task_runner.get(), FROM_HERE,
      base::Bind(&GetMinidumpAndBoundary, dumps_path),
      base::Bind(&UploadCrash, file_task_runner,
                 base::Passed(network_service.Pass()), dumps_path));
}

}  // namespace breakpad
