// Copyright 2019 The Fuchsia 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 "src/developer/forensics/crash_reports/report_util.h"

#include <fuchsia/mem/cpp/fidl.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/time.h>
#include <zircon/errors.h>

#include <string>
#include <variant>

#include "src/developer/forensics/crash_reports/constants.h"
#include "src/developer/forensics/crash_reports/dart_module_parser.h"
#include "src/developer/forensics/crash_reports/errors.h"
#include "src/developer/forensics/crash_reports/report.h"
#include "src/lib/fsl/vmo/strings.h"

namespace forensics {
namespace crash_reports {

std::string Shorten(std::string program_name) {
  // Remove leading whitespace
  const size_t first_non_whitespace = program_name.find_first_not_of(" ");
  if (first_non_whitespace == std::string::npos) {
    return "";
  }
  program_name = program_name.substr(first_non_whitespace);

  // Remove the "fuchsia-pkg://" prefix if present.
  const std::string fuchsia_pkg_prefix("fuchsia-pkg://");
  if (program_name.find(fuchsia_pkg_prefix) == 0) {
    program_name.erase(/*pos=*/0u, /*len=*/fuchsia_pkg_prefix.size());
  }
  std::replace(program_name.begin(), program_name.end(), '/', ':');

  // Remove all repeating ':'.
  for (size_t idx = program_name.find("::"); idx != std::string::npos;
       idx = program_name.find("::")) {
    program_name.erase(idx, 1);
  }

  // Remove trailing white space
  const size_t last_non_whitespace = program_name.find_last_not_of(" ");
  return (last_non_whitespace == std::string::npos)
             ? ""
             : program_name.substr(0, last_non_whitespace + 1);
}

std::string Logname(std::string name) {
  // Normalize |name|.
  name = Shorten(name);

  // Find the last colon in |name|.
  const size_t last_colon = name.find_last_of(":");
  if (last_colon == std::string::npos) {
    return name;
  }

  // Remove everything leading up to the last colon.
  name.erase(name.begin(), name.begin() + last_colon + 1);

  // Determine if there's a ".cm" suffix in |name|.
  const size_t cm_suffix = name.rfind(".cm");
  if (cm_suffix == std::string::npos) {
    return name;
  }

  // Erase the ".cm" and everything after it.
  name.erase(name.begin() + cm_suffix, name.end());
  return name;
}

namespace {

// The crash server expects certain keys from the client for certain fields.
const char kProgramUptimeMillisKey[] = "ptime";
const char kEventIdKey[] = "comments";
const char kCrashSignatureKey[] = "signature";
const char kDartTypeKey[] = "type";
const char kDartTypeValue[] = "DartError";
const char kDartExceptionMessageKey[] = "error_message";
const char kDartExceptionRuntimeTypeKey[] = "error_runtime_type";
const char kDartExceptionStackTraceKey[] = "DartError";
const char kDartModulesKey[] = "dart_modules";
const char kReportTimeMillis[] = "reportTimeMillis";
const char kIsFatalKey[] = "isFatal";
const char kProcessNameKey[] = "crash.process.name";
const char kThreadNameKey[] = "crash.thread.name";

// Extra keys that the crash server does *not* have a dependency on.
const char kProcessKoidKey[] = "crash.process.koid";
const char kThreadKoidKey[] = "crash.thread.koid";

std::pair<bool, std::optional<std::string>> ParseDartModules(
    const fuchsia::mem::Buffer& stack_trace) {
  if (!stack_trace.vmo.is_valid()) {
    return {false, std::nullopt};
  }

  std::string text_stack_trace(stack_trace.size, '\0');

  if (!fsl::StringFromVmo(stack_trace, &text_stack_trace)) {
    FX_LOGS(ERROR) << "Failed to read Dart stack trace vmo";
    return {false, std::nullopt};
  }

  return ParseDartModulesFromStackTrace(text_stack_trace);
}

void ExtractAnnotationsAndAttachments(fuchsia::feedback::CrashReport report,
                                      AnnotationMap* annotations,
                                      std::map<std::string, fuchsia::mem::Buffer>* attachments,
                                      std::optional<fuchsia::mem::Buffer>* minidump) {
  // Default annotations common to all crash reports.
  if (report.has_annotations()) {
    annotations->Set(report.annotations());
  }

  if (report.has_program_uptime()) {
    annotations->Set(kProgramUptimeMillisKey, zx::duration(report.program_uptime()).to_msecs());
  }

  if (report.has_event_id()) {
    annotations->Set(kEventIdKey, report.event_id());
  }

  if (report.has_crash_signature()) {
    annotations->Set(kCrashSignatureKey, report.crash_signature());
  }

  if (report.has_is_fatal()) {
    annotations->Set(kIsFatalKey, report.is_fatal());
  }

  // Dart-specific annotations.
  if (report.has_specific_report() && report.specific_report().is_dart()) {
    annotations->Set(kDartTypeKey, kDartTypeValue);

    const auto& dart_report = report.specific_report().dart();
    if (dart_report.has_exception_type()) {
      annotations->Set(kDartExceptionRuntimeTypeKey, dart_report.exception_type());
    } else {
      FX_LOGS(WARNING) << "no Dart exception type to attach to Crashpad report";
    }

    if (dart_report.has_exception_message()) {
      annotations->Set(kDartExceptionMessageKey, dart_report.exception_message());
    } else {
      FX_LOGS(WARNING) << "no Dart exception message to attach to Crashpad report";
    }

    if (dart_report.has_exception_stack_trace()) {
      if (const auto [is_unsymbolicated, dart_modules] =
              ParseDartModules(dart_report.exception_stack_trace());
          dart_modules.has_value()) {
        annotations->Set(kDartModulesKey, *dart_modules);
      } else if (is_unsymbolicated) {
        FX_LOGS(WARNING) << "Failed to parse Dart modules from stack trace";
      }
    }
  }

  // Native-specific annotations.
  if (report.has_specific_report() && report.specific_report().is_native()) {
    const auto& native_report = report.specific_report().native();
    if (native_report.has_process_name()) {
      annotations->Set(kProcessNameKey, native_report.process_name());
    }
    if (native_report.has_process_koid()) {
      annotations->Set(kProcessKoidKey, native_report.process_koid());
    }
    if (native_report.has_thread_name()) {
      annotations->Set(kThreadNameKey, native_report.thread_name());
    }
    if (native_report.has_thread_koid()) {
      annotations->Set(kThreadKoidKey, native_report.thread_koid());
    }

    // TODO(fxbug.dev/6564): add module annotations from minidump.
  }

  // Default attachments common to all crash reports.
  if (report.has_attachments()) {
    for (auto& attachment : *(report.mutable_attachments())) {
      (*attachments)[attachment.key] = std::move(attachment.value);
    }
  }

  // Native-specific attachment (minidump).
  if (report.has_specific_report() && report.specific_report().is_native()) {
    auto& native_report = report.mutable_specific_report()->native();
    if (native_report.has_minidump()) {
      *minidump = std::move(*native_report.mutable_minidump());
    } else {
      FX_LOGS(WARNING) << "no minidump to attach to Crashpad report";
      // We don't want to overwrite the client-provided signature.
      if (!report.has_crash_signature()) {
        annotations->Set(kCrashSignatureKey, "fuchsia-no-minidump");
      }
    }
  }

  // Dart-specific attachment (text stack trace).
  if (report.has_specific_report() && report.specific_report().is_dart()) {
    auto& dart_report = report.mutable_specific_report()->dart();
    if (dart_report.has_exception_stack_trace()) {
      (*attachments)[kDartExceptionStackTraceKey] =
          std::move(*dart_report.mutable_exception_stack_trace());
    } else {
      FX_LOGS(WARNING) << "no Dart exception stack trace to attach to Crashpad report";
      annotations->Set(kCrashSignatureKey, "fuchsia-no-dart-stack-trace");
    }
  }
}

void AddSnapshotAnnotations(const SnapshotUuid& snapshot_uuid, const Snapshot& snapshot,
                            AnnotationMap* annotations) {
  // The underlying snapshot may have been garbage collected or its collection timed out
  // (possibly due to shutdown). Add the annotations from the snapshot manager could collect itself
  // and annotations indicating why the annotations and archive collected from
  // fuchsia.feedback.DataProvider aren't present.
  //
  // Snapshots will not be missing due to reasons like not being persisted or not having a valid
  // snapshot uuid because neither can occur without a report entering the store and this flow is
  // triggered before the store is used.
  if (std::holds_alternative<MissingSnapshot>(snapshot)) {
    const auto& s = std::get<MissingSnapshot>(snapshot);

    annotations->Set(s.Annotations());
    annotations->Set(s.PresenceAnnotations());

    return;
  }

  // The underlying snapshot was successfully collected and not all of its data was dropped by the
  // snapshot manager (due to garbage collection). Add the annotations collected from
  // fuchsia.feedback.DataProvider and any annotations about why the collected archive may be
  // missing.
  const auto& s = std::get<ManagedSnapshot>(snapshot);
  annotations->Set(s.Annotations());
  annotations->Set(s.PresenceAnnotations());
}

void AddCrashServerAnnotations(const std::string& program_name,
                               const std::optional<timekeeper::time_utc>& current_time,
                               const ErrorOr<std::string>& device_id, const Product& product,
                               AnnotationMap* annotations) {
  // Product.
  annotations->Set("product", product.name)
      .Set("version", product.version)
      .Set("channel", product.channel);

  // Program.
  // TODO(fxbug.dev/57502): for historical reasons, we used ptype to benefit from Chrome's
  // "Process type" handling in the crash server UI. Remove once the UI can fallback on "Program".
  annotations->Set("ptype", program_name);
  annotations->Set("program", program_name);

  // We set the report time only if we were able to get an accurate one.
  if (current_time.has_value()) {
    annotations->Set(kReportTimeMillis, current_time.value().get() / zx::msec(1).get());
  } else {
    annotations->Set("debug.report-time.set", false);
  }

  // We set the device's global unique identifier only if the device has one.
  if (device_id.HasValue()) {
    annotations->Set("guid", device_id.Value());
  } else {
    annotations->Set("debug.guid.set", false).Set("debug.device-id.error", device_id.Error());
  }
}

}  // namespace

std::optional<Report> MakeReport(fuchsia::feedback::CrashReport report, const ReportId report_id,
                                 const SnapshotUuid& snapshot_uuid, const Snapshot& snapshot,
                                 const std::optional<timekeeper::time_utc>& current_time,
                                 const ErrorOr<std::string>& device_id,
                                 const AnnotationMap& default_annotations, const Product& product,
                                 const bool is_hourly_report) {
  const std::string program_name = report.program_name();
  const std::string shortname = Shorten(program_name);

  AnnotationMap annotations = default_annotations;
  std::map<std::string, fuchsia::mem::Buffer> attachments;
  std::optional<fuchsia::mem::Buffer> minidump;

  // Optional annotations and attachments filled by the client.
  ExtractAnnotationsAndAttachments(std::move(report), &annotations, &attachments, &minidump);

  // Snapshot annotations specific to this crash report.
  AddSnapshotAnnotations(snapshot_uuid, snapshot, &annotations);

  // Crash server annotations common to all crash reports.
  AddCrashServerAnnotations(program_name, current_time, device_id, product, &annotations);

  return Report::MakeReport(report_id, shortname, annotations, std::move(attachments),
                            snapshot_uuid, std::move(minidump), is_hourly_report);
}

}  // namespace crash_reports
}  // namespace forensics
