910e62b5创建于 1月15日历史提交
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/attribution_reporting/attribution_resolver_delegate_impl.h"

#include <stddef.h>
#include <stdint.h>

#include <cstdlib>
#include <iterator>
#include <optional>
#include <utility>
#include <vector>

#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
#include "base/time/time.h"
#include "base/types/expected_macros.h"
#include "base/uuid.h"
#include "components/attribution_reporting/aggregatable_trigger_config.h"
#include "components/attribution_reporting/attribution_scopes_data.h"
#include "components/attribution_reporting/event_level_epsilon.h"
#include "components/attribution_reporting/event_report_windows.h"
#include "components/attribution_reporting/features.h"
#include "components/attribution_reporting/max_event_level_reports.h"
#include "components/attribution_reporting/privacy_math.h"
#include "components/attribution_reporting/source_registration_time_config.mojom.h"
#include "components/attribution_reporting/source_type.mojom.h"
#include "components/attribution_reporting/trigger_config.h"
#include "content/browser/attribution_reporting/attribution_config.h"
#include "content/browser/attribution_reporting/attribution_report.h"
#include "content/browser/attribution_reporting/stored_source.h"

namespace content {

namespace {

using ::attribution_reporting::mojom::SourceType;

}  // namespace

// static
std::unique_ptr<AttributionResolverDelegate>
AttributionResolverDelegateImpl::CreateForTesting(
    AttributionNoiseMode noise_mode,
    AttributionDelayMode delay_mode,
    const AttributionConfig& config) {
  return base::WrapUnique(
      new AttributionResolverDelegateImpl(noise_mode, delay_mode, config));
}

AttributionResolverDelegateImpl::AttributionResolverDelegateImpl(
    AttributionNoiseMode noise_mode,
    AttributionDelayMode delay_mode)
    : AttributionResolverDelegateImpl(noise_mode,
                                      delay_mode,
                                      AttributionConfig()) {}

AttributionResolverDelegateImpl::AttributionResolverDelegateImpl(
    AttributionNoiseMode noise_mode,
    AttributionDelayMode delay_mode,
    const AttributionConfig& config)
    : AttributionResolverDelegate(config),
      noise_mode_(noise_mode),
      delay_mode_(delay_mode) {
  DETACH_FROM_SEQUENCE(sequence_checker_);
}

AttributionResolverDelegateImpl::~AttributionResolverDelegateImpl() = default;

base::TimeDelta
AttributionResolverDelegateImpl::GetDeleteExpiredSourcesFrequency() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return base::Minutes(5);
}

base::TimeDelta
AttributionResolverDelegateImpl::GetDeleteExpiredRateLimitsFrequency() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return base::Minutes(5);
}

base::TimeDelta
AttributionResolverDelegateImpl::GetDeleteExpiredOsRegistrationsFrequency()
    const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return base::Minutes(5);
}

base::Time AttributionResolverDelegateImpl::GetEventLevelReportTime(
    const attribution_reporting::EventReportWindows& event_report_windows,
    base::Time source_time,
    base::Time trigger_time) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  switch (delay_mode_) {
    case AttributionDelayMode::kDefault:
      return event_report_windows.ComputeReportTime(source_time, trigger_time);
    case AttributionDelayMode::kNone:
      return trigger_time;
  }
}

base::Time AttributionResolverDelegateImpl::GetAggregatableReportTime(
    base::Time trigger_time) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  switch (delay_mode_) {
    case AttributionDelayMode::kDefault:
      switch (noise_mode_) {
        case AttributionNoiseMode::kDefault:
          return trigger_time + config_.aggregate_limit.min_delay +
                 base::RandDouble() * config_.aggregate_limit.delay_span;
        case AttributionNoiseMode::kNone:
          return trigger_time + config_.aggregate_limit.min_delay +
                 config_.aggregate_limit.delay_span;
      }

    case AttributionDelayMode::kNone:
      return trigger_time;
  }
}

base::Uuid AttributionResolverDelegateImpl::NewReportID() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return base::Uuid::GenerateRandomV4();
}

std::optional<AttributionResolverDelegate::OfflineReportDelayConfig>
AttributionResolverDelegateImpl::GetOfflineReportDelayConfig() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (noise_mode_ == AttributionNoiseMode::kDefault &&
      delay_mode_ == AttributionDelayMode::kDefault) {
    // Add uniform random noise in the range of [0, 1 minutes] to the report
    // time.
    // TODO(crbug.com/40687765): This delay is very conservative.
    // Consider increasing this delay once we can be sure reports are still
    // sent at reasonable times, and not delayed for many browser sessions due
    // to short session up-times.
    return OfflineReportDelayConfig{
        .min = base::Minutes(0),
        .max = base::Minutes(1),
    };
  }

  return std::nullopt;
}

void AttributionResolverDelegateImpl::ShuffleReports(
    std::vector<AttributionReport>& reports) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  switch (noise_mode_) {
    case AttributionNoiseMode::kDefault:
      base::RandomShuffle(reports.begin(), reports.end());
      break;
    case AttributionNoiseMode::kNone:
      break;
  }
}

AttributionResolverDelegate::GetRandomizedResponseResult
AttributionResolverDelegateImpl::GetRandomizedResponse(
    SourceType source_type,
    const attribution_reporting::TriggerDataSet& trigger_data,
    const attribution_reporting::EventReportWindows& event_report_windows,
    const attribution_reporting::MaxEventLevelReports max_event_level_reports,
    attribution_reporting::EventLevelEpsilon epsilon,
    const std::optional<attribution_reporting::AttributionScopesData>&
        scopes_data) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  ASSIGN_OR_RETURN(
      auto response,
      attribution_reporting::DoRandomizedResponse(
          trigger_data, event_report_windows, max_event_level_reports, epsilon,
          source_type, scopes_data, config_.privacy_math_config));

  switch (noise_mode_) {
    case AttributionNoiseMode::kDefault:
      break;
    case AttributionNoiseMode::kNone:
      // TODO(apaseltiner): When noise is disabled, we shouldn't even bother
      // generating the response in the first place.
      response.response() = std::nullopt;
      break;
  }

  return response;
}

bool AttributionResolverDelegateImpl::
    GenerateNullAggregatableReportForLookbackDay(
        int lookback_day,
        attribution_reporting::mojom::SourceRegistrationTimeConfig
            source_registration_time_config) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  switch (noise_mode_) {
    case AttributionNoiseMode::kDefault:
      break;
    case AttributionNoiseMode::kNone:
      return false;
  }

  double rate;
  switch (source_registration_time_config) {
    case attribution_reporting::mojom::SourceRegistrationTimeConfig::kInclude:
      rate = config_.aggregate_limit
                 .null_reports_rate_include_source_registration_time;
      break;
    case attribution_reporting::mojom::SourceRegistrationTimeConfig::kExclude:
      rate = config_.aggregate_limit
                 .null_reports_rate_exclude_source_registration_time;
      break;
  }

  return attribution_reporting::GenerateWithRate(rate);
}

}  // namespace content