blob: 4bcfa6eb524c22ddb2603beaa1fb8e9ce46b4418 [file] [log] [blame] [edit]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/crash/cast_crashdump_uploader.h"
#include <sys/stat.h>
#include <optional>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
// TODO(slan): Find a replacement for LibcurlWrapper in Chromium to remove the
// breakpad dependency.
#include "chromecast/crash/libcurl_wrapper.h"
namespace chromecast {
namespace {
// Keep these in sync with
// //third_party/breakpad/breakpad/src/client/mac/sender/uploader.mm
const char kProdKey[] = "prod";
const char kVerKey[] = "ver";
const char kGuidKey[] = "guid";
const char kPtimeKey[] = "ptime";
const char kCtimeKey[] = "ctime";
const char kEmailKey[] = "email";
const char kCommentsKey[] = "comments";
} // namespace
CastCrashdumpData::CastCrashdumpData() {
}
CastCrashdumpData::CastCrashdumpData(const CastCrashdumpData& other) = default;
CastCrashdumpData::~CastCrashdumpData() {
}
CastCrashdumpUploader::CastCrashdumpUploader(const CastCrashdumpData& data)
: CastCrashdumpUploader(data, std::make_unique<LibcurlWrapper>()) {}
CastCrashdumpUploader::CastCrashdumpUploader(
const CastCrashdumpData& data,
std::unique_ptr<LibcurlWrapper> http_layer)
: http_layer_(std::move(http_layer)), data_(data) {
DCHECK(http_layer_);
}
CastCrashdumpUploader::~CastCrashdumpUploader() {
}
bool CastCrashdumpUploader::AddAttachment(const std::string& label,
const std::string& filename) {
std::optional<int64_t> file_size =
base::GetFileSize(base::FilePath(filename));
if (!file_size.has_value()) {
LOG(WARNING) << "file size of " << filename << " not readable";
return false;
}
LOG(INFO) << "file size of " << filename << ": " << file_size.value();
attachments_[label] = filename;
return true;
}
bool CastCrashdumpUploader::CheckRequiredParametersArePresent() {
return !(data_.product.empty() || data_.version.empty() ||
data_.guid.empty() || data_.minidump_pathname.empty());
}
bool CastCrashdumpUploader::Upload(std::string* response) {
if (!http_layer_->Init()) {
LOG(ERROR) << "http layer Init failed";
return false;
}
if (!CheckRequiredParametersArePresent()) {
LOG(ERROR) << "Missing required parameters";
return false;
}
struct stat st;
if (0 != stat(data_.minidump_pathname.c_str(), &st)) {
LOG(ERROR) << data_.minidump_pathname << " does not exist.";
return false;
}
std::string upload_filename = data_.upload_filename;
if (upload_filename.empty()) {
upload_filename = "upload_file_minidump";
}
if (!http_layer_->AddFile(data_.minidump_pathname, upload_filename)) {
LOG(ERROR) << "Failed to add file: " << data_.minidump_pathname;
return false;
}
// Populate |parameters_|.
parameters_[kProdKey] = data_.product;
parameters_[kVerKey] = data_.version;
parameters_[kGuidKey] = data_.guid;
parameters_[kPtimeKey] = data_.ptime;
parameters_[kCtimeKey] = data_.ctime;
parameters_[kEmailKey] = data_.email;
parameters_[kCommentsKey] = data_.comments;
// Add each attachement in |attachments_|.
for (auto iter = attachments_.begin(); iter != attachments_.end(); ++iter) {
// Search for the attachment.
if (0 != stat(iter->second.c_str(), &st)) {
LOG(ERROR) << iter->second << " could not be found";
return false;
}
// Add the attachment
if (!http_layer_->AddFile(iter->second, iter->first)) {
LOG(ERROR) << "Failed to add file: " << iter->second
<< " with label: " << iter->first;
return false;
}
}
LOG(INFO) << "Sending request to " << data_.crash_server;
long http_status_code;
std::string http_header_data;
return http_layer_->SendRequest(data_.crash_server,
parameters_,
&http_status_code,
&http_header_data,
response);
}
void CastCrashdumpUploader::SetParameter(const std::string& key,
const std::string& value) {
parameters_[key] = value;
}
} // namespace chromecast