// Copyright (c) 2019 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 "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h"
#include <algorithm>

#include "base/metrics/histogram_functions.h"
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h"
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h"
#include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h"
#include "components/safe_browsing/core/proto/webprotect.pb.h"

namespace safe_browsing {

namespace {

constexpr int kMinBytesPerSecond = 1;
constexpr int kMaxBytesPerSecond = 100 * 1024 * 1024;  // 100 MB/s

// TODO(drubery): This function would be simpler if the ClientDownloadResponse
// and MalwareDeepScanningVerdict used the same enum.
std::string MalwareVerdictToThreatType(
    MalwareDeepScanningVerdict::Verdict verdict) {
  switch (verdict) {
    case MalwareDeepScanningVerdict::CLEAN:
      return "SAFE";
    case MalwareDeepScanningVerdict::UWS:
      return "POTENTIALLY_UNWANTED";
    case MalwareDeepScanningVerdict::MALWARE:
      return "DANGEROUS";
    case MalwareDeepScanningVerdict::VERDICT_UNSPECIFIED:
    default:
      return "UNKNOWN";
  }
}

}  // namespace

void MaybeReportDeepScanningVerdict(Profile* profile,
                                    const GURL& url,
                                    const std::string& file_name,
                                    const std::string& download_digest_sha256,
                                    const std::string& mime_type,
                                    const std::string& trigger,
                                    const int64_t content_size,
                                    BinaryUploadService::Result result,
                                    DeepScanningClientResponse response) {
  DCHECK(std::all_of(download_digest_sha256.begin(),
                     download_digest_sha256.end(), [](const char& c) {
                       return (c >= '0' && c <= '9') ||
                              (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
                     }));
  std::string unscanned_reason;
  switch (result) {
    case BinaryUploadService::Result::SUCCESS:
    case BinaryUploadService::Result::UNAUTHORIZED:
      // Don't report an unscanned file event on these results.
      break;

    case BinaryUploadService::Result::FILE_TOO_LARGE:
      unscanned_reason = "fileTooLarge";
      break;
    case BinaryUploadService::Result::TIMEOUT:
      unscanned_reason = "scanTimedOut";
      break;
    case BinaryUploadService::Result::FILE_ENCRYPTED:
      unscanned_reason = "filePasswordProtected";
      break;
    case BinaryUploadService::Result::UNKNOWN:
      unscanned_reason = "unknownError";
      break;
    case BinaryUploadService::Result::UPLOAD_FAILURE:
      unscanned_reason = "uploadFailure";
      break;
    case BinaryUploadService::Result::FAILED_TO_GET_TOKEN:
      unscanned_reason = "failedToGetToken";
      break;
    case BinaryUploadService::Result::UNSUPPORTED_FILE_TYPE:
      unscanned_reason = "unsupportedFileType";
  }

  if (!unscanned_reason.empty()) {
    extensions::SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile)
        ->OnUnscannedFileEvent(url, file_name, download_digest_sha256,
                               mime_type, trigger, unscanned_reason,
                               content_size);
  }

  if (result != BinaryUploadService::Result::SUCCESS)
    return;

  if (response.has_malware_scan_verdict() &&
      response.malware_scan_verdict().verdict() ==
          MalwareDeepScanningVerdict::SCAN_FAILURE) {
    extensions::SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile)
        ->OnUnscannedFileEvent(url, file_name, download_digest_sha256,
                               mime_type, trigger, "malwareScanFailed",
                               content_size);
  }

  if (response.has_dlp_scan_verdict() &&
      response.dlp_scan_verdict().status() != DlpDeepScanningVerdict::SUCCESS) {
    extensions::SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile)
        ->OnUnscannedFileEvent(url, file_name, download_digest_sha256,
                               mime_type, trigger, "dlpScanFailed",
                               content_size);
  }

  if (response.malware_scan_verdict().verdict() ==
          MalwareDeepScanningVerdict::UWS ||
      response.malware_scan_verdict().verdict() ==
          MalwareDeepScanningVerdict::MALWARE) {
    extensions::SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile)
        ->OnDangerousDeepScanningResult(
            url, file_name, download_digest_sha256,
            MalwareVerdictToThreatType(
                response.malware_scan_verdict().verdict()),
            mime_type, trigger, content_size);
  }

  if (response.dlp_scan_verdict().status() == DlpDeepScanningVerdict::SUCCESS) {
    if (!response.dlp_scan_verdict().triggered_rules().empty()) {
      extensions::SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile)
          ->OnSensitiveDataEvent(response.dlp_scan_verdict(), url, file_name,
                                 download_digest_sha256, mime_type, trigger,
                                 content_size);
    }
  }
}

std::string DeepScanAccessPointToString(DeepScanAccessPoint access_point) {
  switch (access_point) {
    case DeepScanAccessPoint::DOWNLOAD:
      return "Download";
    case DeepScanAccessPoint::UPLOAD:
      return "Upload";
    case DeepScanAccessPoint::DRAG_AND_DROP:
      return "DragAndDrop";
    case DeepScanAccessPoint::PASTE:
      return "Paste";
  }
  NOTREACHED();
  return "";
}

void RecordDeepScanMetrics(DeepScanAccessPoint access_point,
                           base::TimeDelta duration,
                           int64_t total_bytes,
                           const BinaryUploadService::Result& result,
                           const DeepScanningClientResponse& response) {
  // Don't record UMA metrics for this result.
  if (result == BinaryUploadService::Result::UNAUTHORIZED)
    return;
  bool dlp_verdict_success = response.has_dlp_scan_verdict()
                                 ? response.dlp_scan_verdict().status() ==
                                       DlpDeepScanningVerdict::SUCCESS
                                 : true;
  bool malware_verdict_success =
      response.has_malware_scan_verdict()
          ? response.malware_scan_verdict().verdict() !=
                MalwareDeepScanningVerdict::VERDICT_UNSPECIFIED
          : true;
  bool success = dlp_verdict_success && malware_verdict_success;
  std::string result_value = BinaryUploadServiceResultToString(result, success);

  // Update |success| so non-SUCCESS results don't log the bytes/sec metric.
  success &= (result == BinaryUploadService::Result::SUCCESS);

  RecordDeepScanMetrics(access_point, duration, total_bytes, result_value,
                        success);
}

void RecordDeepScanMetrics(DeepScanAccessPoint access_point,
                           base::TimeDelta duration,
                           int64_t total_bytes,
                           const std::string& result,
                           bool success) {
  // Don't record metrics if the duration is unusable.
  if (duration.InMilliseconds() == 0)
    return;

  std::string access_point_string = DeepScanAccessPointToString(access_point);
  if (success) {
    base::UmaHistogramCustomCounts(
        "SafeBrowsing.DeepScan." + access_point_string + ".BytesPerSeconds",
        (1000 * total_bytes) / duration.InMilliseconds(),
        /*min=*/kMinBytesPerSecond,
        /*max=*/kMaxBytesPerSecond,
        /*buckets=*/50);
  }

  // The scanning timeout is 5 minutes, so the bucket maximum time is 30 minutes
  // in order to be lenient and avoid having lots of data in the overlow bucket.
  base::UmaHistogramCustomTimes("SafeBrowsing.DeepScan." + access_point_string +
                                    "." + result + ".Duration",
                                duration, base::TimeDelta::FromMilliseconds(1),
                                base::TimeDelta::FromMinutes(30), 50);
  base::UmaHistogramCustomTimes(
      "SafeBrowsing.DeepScan." + access_point_string + ".Duration", duration,
      base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(30),
      50);
}

std::array<const base::FilePath::CharType*, 21> SupportedDlpFileTypes() {
  // Keep sorted for efficient access.
  static constexpr const std::array<const base::FilePath::CharType*, 21>
      kSupportedDLPFileTypes = {
          FILE_PATH_LITERAL(".7z"),   FILE_PATH_LITERAL(".bzip"),
          FILE_PATH_LITERAL(".cab"),  FILE_PATH_LITERAL(".doc"),
          FILE_PATH_LITERAL(".docx"), FILE_PATH_LITERAL(".eps"),
          FILE_PATH_LITERAL(".gzip"), FILE_PATH_LITERAL(".odt"),
          FILE_PATH_LITERAL(".pdf"),  FILE_PATH_LITERAL(".ppt"),
          FILE_PATH_LITERAL(".pptx"), FILE_PATH_LITERAL(".ps"),
          FILE_PATH_LITERAL(".rar"),  FILE_PATH_LITERAL(".rtf"),
          FILE_PATH_LITERAL(".tar"),  FILE_PATH_LITERAL(".txt"),
          FILE_PATH_LITERAL(".wpd"),  FILE_PATH_LITERAL(".xls"),
          FILE_PATH_LITERAL(".xlsx"), FILE_PATH_LITERAL(".xps"),
          FILE_PATH_LITERAL(".zip")};
  // TODO: Replace this DCHECK with a static assert once std::is_sorted is
  // constexpr in C++20.
  DCHECK(std::is_sorted(
      kSupportedDLPFileTypes.begin(), kSupportedDLPFileTypes.end(),
      [](const base::FilePath::StringType& a,
         const base::FilePath::StringType& b) { return a.compare(b) < 0; }));

  return kSupportedDLPFileTypes;
}

bool FileTypeSupported(bool for_malware_scan,
                       bool for_dlp_scan,
                       const base::FilePath& path) {
  // At least one of the booleans needs to be true.
  DCHECK(for_malware_scan || for_dlp_scan);

  // Accept any file type for malware scans.
  if (for_malware_scan)
    return true;

  // Accept any file type in the supported list for DLP scans.
  if (for_dlp_scan) {
    base::FilePath::StringType extension(path.FinalExtension());
    std::transform(extension.begin(), extension.end(), extension.begin(),
                   tolower);

    auto dlp_types = SupportedDlpFileTypes();
    return std::binary_search(dlp_types.begin(), dlp_types.end(), extension);
  }

  return false;
}

DeepScanningClientResponse SimpleDeepScanningClientResponseForTesting(
    base::Optional<bool> dlp_success,
    base::Optional<bool> malware_success) {
  DeepScanningClientResponse response;

  if (dlp_success.has_value()) {
    response.mutable_dlp_scan_verdict()->set_status(
        DlpDeepScanningVerdict::SUCCESS);
    if (!dlp_success.value()) {
      DlpDeepScanningVerdict::TriggeredRule* rule =
          response.mutable_dlp_scan_verdict()->add_triggered_rules();
      rule->set_rule_name("rule");
      rule->set_action(DlpDeepScanningVerdict::TriggeredRule::BLOCK);
    }
  }

  if (malware_success.has_value()) {
    if (malware_success.value()) {
      response.mutable_malware_scan_verdict()->set_verdict(
          MalwareDeepScanningVerdict::CLEAN);
    } else {
      response.mutable_malware_scan_verdict()->set_verdict(
          MalwareDeepScanningVerdict::MALWARE);
    }
  }

  return response;
}

std::string BinaryUploadServiceResultToString(
    const BinaryUploadService::Result& result,
    bool success) {
  switch (result) {
    case BinaryUploadService::Result::SUCCESS:
      if (success)
        return "Success";
      else
        return "FailedToGetVerdict";
    case BinaryUploadService::Result::UPLOAD_FAILURE:
      return "UploadFailure";
    case BinaryUploadService::Result::TIMEOUT:
      return "Timeout";
    case BinaryUploadService::Result::FILE_TOO_LARGE:
      return "FileTooLarge";
    case BinaryUploadService::Result::FAILED_TO_GET_TOKEN:
      return "FailedToGetToken";
    case BinaryUploadService::Result::UNKNOWN:
      return "Unknown";
    case BinaryUploadService::Result::UNAUTHORIZED:
      return "";
    case BinaryUploadService::Result::FILE_ENCRYPTED:
      return "FileEncrypted";
    case BinaryUploadService::Result::UNSUPPORTED_FILE_TYPE:
      return "UnsupportedFileType";
  }
}

}  // namespace safe_browsing
