// 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/browser/tracing/background_tracing_config_impl.h"

#include <set>
#include <utility>

#include "base/json/json_reader.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/process_handle.h"
#include "base/system/sys_info.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/tracing/common/trace_startup_config.h"
#include "content/browser/tracing/background_tracing_rule.h"
#include "net/base/network_change_notifier.h"

using base::trace_event::TraceConfig;

namespace content {

namespace {

const char kConfigsKey[] = "configs";

const char kConfigModeKey[] = "mode";
const char kConfigModePreemptive[] = "PREEMPTIVE_TRACING_MODE";
const char kConfigModeReactive[] = "REACTIVE_TRACING_MODE";
const char kConfigModeSystem[] = "SYSTEM_TRACING_MODE";

const char kConfigScenarioName[] = "scenario_name";
const char kEnabledDataSourcesKey[] = "enabled_data_sources";

const char kConfigCategoryKey[] = "category";
const char kConfigCustomCategoriesKey[] = "custom_categories";
const char kConfigTraceConfigKey[] = "trace_config";
const char kConfigCategoryBenchmarkStartup[] = "BENCHMARK_STARTUP";
const char kConfigCategoryCustom[] = "CUSTOM";
const char kConfigCustomConfig[] = "CUSTOM_CONFIG";

const char kConfigLowRamBufferSizeKb[] = "low_ram_buffer_size_kb";
const char kConfigMediumRamBufferSizeKb[] = "medium_ram_buffer_size_kb";
const char kConfigMobileNetworkBuferSizeKb[] = "mobile_network_buffer_size_kb";
const char kConfigMaxBufferSizeKb[] = "max_buffer_size_kb";
const char kConfigUploadLimitKb[] = "upload_limit_kb";
const char kConfigUploadLimitNetworkKb[] = "upload_limit_network_kb";
const char kConfigInterningResetIntervalMs[] = "interning_reset_interval_ms";

}  // namespace

BackgroundTracingConfigImpl::BackgroundTracingConfigImpl(
    TracingMode tracing_mode)
    : BackgroundTracingConfig(tracing_mode),
      category_preset_(BackgroundTracingConfigImpl::BENCHMARK_STARTUP) {}

BackgroundTracingConfigImpl::~BackgroundTracingConfigImpl() {}

// static
std::string BackgroundTracingConfigImpl::CategoryPresetToString(
    BackgroundTracingConfigImpl::CategoryPreset category_preset) {
  switch (category_preset) {
    case BackgroundTracingConfigImpl::BENCHMARK_STARTUP:
      return kConfigCategoryBenchmarkStartup;
    case BackgroundTracingConfigImpl::CUSTOM_CATEGORY_PRESET:
      return kConfigCategoryCustom;
    case BackgroundTracingConfigImpl::CUSTOM_TRACE_CONFIG:
      return kConfigCustomConfig;
    case BackgroundTracingConfigImpl::CATEGORY_PRESET_UNSET:
      NOTREACHED();
      return "";
  }
}

// static
bool BackgroundTracingConfigImpl::StringToCategoryPreset(
    const std::string& category_preset_string,
    BackgroundTracingConfigImpl::CategoryPreset* category_preset) {
  if (category_preset_string == kConfigCategoryBenchmarkStartup) {
    *category_preset = BackgroundTracingConfigImpl::BENCHMARK_STARTUP;
    return true;
  }

  return false;
}

base::Value BackgroundTracingConfigImpl::ToDict() {
  base::Value dict(base::Value::Type::DICTIONARY);

  if (category_preset_ == CUSTOM_CATEGORY_PRESET) {
    dict.SetStringKey(kConfigCustomCategoriesKey, custom_categories_);
  } else if (category_preset_ == CUSTOM_TRACE_CONFIG) {
    absl::optional<base::Value> trace_config =
        base::JSONReader::Read(trace_config_.ToString());
    if (trace_config) {
      dict.SetKey(kConfigTraceConfigKey, std::move(*trace_config));
    }
  }
  if (!enabled_data_sources_.empty()) {
    dict.SetStringKey(kEnabledDataSourcesKey, enabled_data_sources_);
  }

  switch (tracing_mode()) {
    case BackgroundTracingConfigImpl::PREEMPTIVE:
      dict.SetStringKey(kConfigModeKey, kConfigModePreemptive);
      dict.SetStringKey(kConfigCategoryKey,
                        CategoryPresetToString(category_preset_));
      break;
    case BackgroundTracingConfigImpl::REACTIVE:
      dict.SetStringKey(kConfigModeKey, kConfigModeReactive);
      break;
    case BackgroundTracingConfigImpl::SYSTEM:
      dict.SetStringKey(kConfigModeKey, kConfigModeSystem);
      break;
  }

  base::ListValue configs_list;
  for (const auto& rule : rules_) {
    DCHECK(rule);
    configs_list.Append(rule->ToDict());
  }

  dict.SetKey(kConfigsKey, std::move(configs_list));

  if (!scenario_name_.empty())
    dict.SetStringKey(kConfigScenarioName, scenario_name_);

  return dict;
}

void BackgroundTracingConfigImpl::SetPackageNameFilteringEnabled(bool enabled) {
  trace_config_.SetEventPackageNameFilterEnabled(enabled);
}

void BackgroundTracingConfigImpl::AddPreemptiveRule(const base::Value& dict) {
  AddRule(dict);
}

void BackgroundTracingConfigImpl::AddReactiveRule(
    const base::Value& dict,
    BackgroundTracingConfigImpl::CategoryPreset category_preset) {
  BackgroundTracingRule* rule = AddRule(dict);
  if (rule) {
    rule->set_category_preset(category_preset);
  }
}

void BackgroundTracingConfigImpl::AddSystemRule(const base::Value& dict) {
  AddRule(dict);
}

TraceConfig BackgroundTracingConfigImpl::GetTraceConfig() const {
  base::trace_event::TraceRecordMode record_mode =
      (tracing_mode() == BackgroundTracingConfigImpl::REACTIVE)
          ? base::trace_event::RECORD_UNTIL_FULL
          : base::trace_event::RECORD_CONTINUOUSLY;

  TraceConfig chrome_config;
  if (category_preset() == CUSTOM_TRACE_CONFIG) {
    chrome_config = trace_config_;
    if (!chrome_config.process_filter_config().included_process_ids().empty()) {
      // |included_process_ids| are not allowed in BackgroundTracing because
      // PIDs can't be known ahead of time.
      chrome_config.SetProcessFilterConfig(TraceConfig::ProcessFilterConfig());
    }
  } else if (category_preset() == CUSTOM_CATEGORY_PRESET) {
    chrome_config = TraceConfig(custom_categories_, record_mode);
  } else {
    chrome_config = GetConfigForCategoryPreset(category_preset(), record_mode);
  }

  chrome_config.SetTraceBufferSizeInKb(GetMaximumTraceBufferSizeKb());
  chrome_config.SetEventPackageNameFilterEnabled(
      trace_config_.IsEventPackageNameFilterEnabled());

#if BUILDFLAG(IS_ANDROID)
  // For legacy tracing backend, set low trace buffer size on Android in order
  // to upload small trace files.
  if (tracing_mode() == BackgroundTracingConfigImpl::PREEMPTIVE) {
    chrome_config.SetTraceBufferSizeInEvents(20000);
  }
#endif

  return chrome_config;
}

size_t BackgroundTracingConfigImpl::GetTraceUploadLimitKb() const {
#if BUILDFLAG(IS_ANDROID)
  auto type = net::NetworkChangeNotifier::GetConnectionType();
  UMA_HISTOGRAM_ENUMERATION(
      "Tracing.Background.NetworkConnectionTypeWhenUploaded", type,
      net::NetworkChangeNotifier::CONNECTION_LAST + 1);
  if (net::NetworkChangeNotifier::IsConnectionCellular(type)) {
    return upload_limit_network_kb_;
  }
#endif
  return upload_limit_kb_;
}

// static
std::unique_ptr<BackgroundTracingConfigImpl>
BackgroundTracingConfigImpl::FromDict(base::Value&& dict) {
  DCHECK(dict.is_dict());

  const std::string* mode = dict.FindStringKey(kConfigModeKey);
  if (!mode)
    return nullptr;

  std::unique_ptr<BackgroundTracingConfigImpl> config;

  if (*mode == kConfigModePreemptive) {
    config = PreemptiveFromDict(dict);
  } else if (*mode == kConfigModeReactive) {
    config = ReactiveFromDict(dict);
  } else if (*mode == kConfigModeSystem) {
    config = SystemFromDict(dict);
  } else {
    return nullptr;
  }

  if (config) {
    if (const std::string* scenario = dict.FindStringKey(kConfigScenarioName)) {
      config->scenario_name_ = *scenario;
    }
    config->SetBufferSizeLimits(&dict);
  }

  return config;
}

// static
std::unique_ptr<BackgroundTracingConfigImpl>
BackgroundTracingConfigImpl::PreemptiveFromDict(const base::Value& dict) {
  DCHECK(dict.is_dict());

  std::unique_ptr<BackgroundTracingConfigImpl> config(
      new BackgroundTracingConfigImpl(BackgroundTracingConfigImpl::PREEMPTIVE));

  if (const base::Value* trace_config =
          dict.FindDictKey(kConfigTraceConfigKey)) {
    config->trace_config_ = TraceConfig(*trace_config);
    config->category_preset_ = CUSTOM_TRACE_CONFIG;
  } else if (const std::string* categories =
                 dict.FindStringKey(kConfigCustomCategoriesKey)) {
    config->custom_categories_ = *categories;
    config->category_preset_ = CUSTOM_CATEGORY_PRESET;
  } else {
    const std::string* category_preset_string =
        dict.FindStringKey(kConfigCategoryKey);
    if (!category_preset_string)
      return nullptr;

    if (!StringToCategoryPreset(*category_preset_string,
                                &config->category_preset_)) {
      return nullptr;
    }
  }
  if (const std::string* enabled_data_sources =
          dict.FindStringKey(kEnabledDataSourcesKey)) {
    config->enabled_data_sources_ = *enabled_data_sources;
  }

  const base::Value* configs_list = dict.FindListKey(kConfigsKey);
  if (!configs_list)
    return nullptr;

  for (const auto& config_dict : configs_list->GetListDeprecated()) {
    if (!config_dict.is_dict())
      return nullptr;

    config->AddPreemptiveRule(config_dict);
  }

  if (config->rules().empty())
    return nullptr;

  return config;
}

// static
std::unique_ptr<BackgroundTracingConfigImpl>
BackgroundTracingConfigImpl::ReactiveFromDict(const base::Value& dict) {
  DCHECK(dict.is_dict());

  std::unique_ptr<BackgroundTracingConfigImpl> config(
      new BackgroundTracingConfigImpl(BackgroundTracingConfigImpl::REACTIVE));

  bool has_global_categories = false;
  if (const base::Value* trace_config =
          dict.FindDictKey(kConfigTraceConfigKey)) {
    config->trace_config_ = TraceConfig(*trace_config);
    config->category_preset_ = CUSTOM_TRACE_CONFIG;
    has_global_categories = true;
  } else if (const std::string* categories =
                 dict.FindStringKey(kConfigCustomCategoriesKey)) {
    config->custom_categories_ = *categories;
    config->category_preset_ = CUSTOM_CATEGORY_PRESET;
    has_global_categories = true;
  } else if (const std::string* category_preset_string =
                 dict.FindStringKey(kConfigCategoryKey)) {
    if (!StringToCategoryPreset(*category_preset_string,
                                &config->category_preset_)) {
      return nullptr;
    }
    has_global_categories = true;
  }

  if (const std::string* enabled_data_sources =
          dict.FindStringKey(kEnabledDataSourcesKey)) {
    config->enabled_data_sources_ = *enabled_data_sources;
  }

  const base::Value* configs_list = dict.FindListKey(kConfigsKey);
  if (!configs_list)
    return nullptr;

  for (const auto& config_dict : configs_list->GetListDeprecated()) {
    if (!config_dict.is_dict())
      return nullptr;

    // TODO(oysteine): Remove the per-rule category preset when configs have
    // been updated to just specify the per-config category preset.
    if (!has_global_categories) {
      if (const std::string* category_preset_string =
              config_dict.FindStringKey(kConfigCategoryKey)) {
        if (!StringToCategoryPreset(*category_preset_string,
                                    &config->category_preset_)) {
          return nullptr;
        }
      }
    }

    config->AddReactiveRule(config_dict, config->category_preset_);
  }

  if (config->rules().empty())
    return nullptr;

  return config;
}

// static
std::unique_ptr<BackgroundTracingConfigImpl>
BackgroundTracingConfigImpl::SystemFromDict(const base::Value& dict) {
  DCHECK(dict.is_dict());

  auto config = std::make_unique<BackgroundTracingConfigImpl>(
      BackgroundTracingConfigImpl::SYSTEM);

  const base::Value* configs_list = dict.FindListKey(kConfigsKey);
  if (!configs_list)
    return nullptr;

  for (const auto& config_dict : configs_list->GetListDeprecated()) {
    if (!config_dict.is_dict())
      return nullptr;

    config->AddSystemRule(config_dict);
  }

  if (config->rules().empty())
    return nullptr;

  return config;
}

// static
TraceConfig BackgroundTracingConfigImpl::GetConfigForCategoryPreset(
    BackgroundTracingConfigImpl::CategoryPreset preset,
    base::trace_event::TraceRecordMode record_mode) {
  switch (preset) {
    case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_STARTUP: {
      auto config =
          tracing::TraceStartupConfig::GetDefaultBrowserStartupConfig();
      config.SetTraceRecordMode(record_mode);
      return config;
    }
    default:
      NOTREACHED();
      return TraceConfig();
  }
}

BackgroundTracingRule* BackgroundTracingConfigImpl::AddRule(
    const base::Value& dict) {
  std::unique_ptr<BackgroundTracingRule> rule =
      BackgroundTracingRule::CreateRuleFromDict(dict);
  if (rule) {
    has_crash_scenario_ = rule->is_crash();
    rules_.push_back(std::move(rule));
    return rules_.back().get();
  }
  return nullptr;
}

void BackgroundTracingConfigImpl::SetBufferSizeLimits(const base::Value* dict) {
  if (auto low_ram_buffer_size_kb =
          dict->FindIntKey(kConfigLowRamBufferSizeKb)) {
    low_ram_buffer_size_kb_ = *low_ram_buffer_size_kb;
  }
  if (auto medium_ram_buffer_size_kb =
          dict->FindIntKey(kConfigMediumRamBufferSizeKb)) {
    medium_ram_buffer_size_kb_ = *medium_ram_buffer_size_kb;
  }
  if (auto mobile_network_buffer_size_kb =
          dict->FindIntKey(kConfigMobileNetworkBuferSizeKb)) {
    mobile_network_buffer_size_kb_ = *mobile_network_buffer_size_kb;
  }
  if (auto max_buffer_size_kb = dict->FindIntKey(kConfigMaxBufferSizeKb)) {
    max_buffer_size_kb_ = *max_buffer_size_kb;
  }
  if (auto upload_limit_kb = dict->FindIntKey(kConfigUploadLimitKb)) {
    upload_limit_kb_ = *upload_limit_kb;
  }
  if (auto upload_limit_network_kb =
          dict->FindIntKey(kConfigUploadLimitNetworkKb)) {
    upload_limit_network_kb_ = *upload_limit_network_kb;
  }
  if (auto interning_reset_interval_ms =
          dict->FindIntKey(kConfigInterningResetIntervalMs)) {
    interning_reset_interval_ms_ = *interning_reset_interval_ms;
  }
}

int BackgroundTracingConfigImpl::GetMaximumTraceBufferSizeKb() const {
  int64_t ram_mb = base::SysInfo::AmountOfPhysicalMemoryMB();
  if (ram_mb > 0 && ram_mb <= 1024) {
    return low_ram_buffer_size_kb_;
  }
#if BUILDFLAG(IS_ANDROID)
  auto type = net::NetworkChangeNotifier::GetConnectionType();
  UMA_HISTOGRAM_ENUMERATION(
      "Tracing.Background.NetworkConnectionTypeWhenStarted", type,
      net::NetworkChangeNotifier::CONNECTION_LAST + 1);
  if (net::NetworkChangeNotifier::IsConnectionCellular(type)) {
    return mobile_network_buffer_size_kb_;
  }
#endif

  if (ram_mb > 0 && ram_mb <= 2 * 1024) {
    return medium_ram_buffer_size_kb_;
  }

  return max_buffer_size_kb_;
}

}  // namespace content
