blob: 718adc196a50af95134db0229aca2f4c792b7c2a [file] [log] [blame]
// 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.
#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_MANAGER_IMPL_H_
#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_MANAGER_IMPL_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <vector>
#include "base/containers/flat_set.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ref.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/threading/sequence_bound.h"
#include "content/browser/aggregation_service/aggregation_service.h"
#include "content/browser/aggregation_service/report_scheduler_timer.h"
#include "content/browser/attribution_reporting/attribution_manager.h"
#include "content/browser/attribution_reporting/attribution_report.h"
#include "content/browser/attribution_reporting/attribution_reporting.mojom-forward.h"
#include "content/browser/attribution_reporting/process_aggregatable_debug_report_result.mojom-forward.h"
#include "content/common/content_export.h"
#include "content/public/browser/storage_partition.h"
namespace attribution_reporting {
struct OsRegistrationItem;
} // namespace attribution_reporting
namespace base {
class FilePath;
class Time;
class UpdateableSequencedTaskRunner;
class ValueView;
} // namespace base
namespace storage {
class SpecialStoragePolicy;
} // namespace storage
namespace url {
class Origin;
} // namespace url
namespace content {
class AggregatableDebugReport;
class AggregatableReport;
class AggregatableReportRequest;
class AttributionDataHostManager;
class AttributionDebugReport;
class AttributionOsLevelManager;
class AttributionReportSender;
class AttributionResolver;
class AttributionResolverDelegate;
class CreateReportResult;
class StoragePartitionImpl;
class StoreSourceResult;
struct GlobalRenderFrameHostId;
struct OsRegistration;
struct ProcessAggregatableDebugReportResult;
struct SendAggregatableDebugReportResult;
struct SendResult;
// UI thread class that manages the lifetime of the underlying attribution
// storage and coordinates sending attribution reports. Owned by the storage
// partition.
class CONTENT_EXPORT AttributionManagerImpl : public AttributionManager {
public:
// Configures underlying storage to be setup in memory, rather than on
// disk. This speeds up initialization to avoid timeouts in test environments.
class CONTENT_EXPORT ScopedUseInMemoryStorageForTesting {
public:
ScopedUseInMemoryStorageForTesting();
~ScopedUseInMemoryStorageForTesting();
ScopedUseInMemoryStorageForTesting(
const ScopedUseInMemoryStorageForTesting&) = delete;
ScopedUseInMemoryStorageForTesting& operator=(
const ScopedUseInMemoryStorageForTesting&) = delete;
ScopedUseInMemoryStorageForTesting(ScopedUseInMemoryStorageForTesting&&) =
delete;
ScopedUseInMemoryStorageForTesting& operator=(
ScopedUseInMemoryStorageForTesting&&) = delete;
private:
const bool previous_;
};
static std::unique_ptr<AttributionManagerImpl> CreateForTesting(
const base::FilePath& user_data_directory,
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
std::unique_ptr<AttributionResolverDelegate> resolver_delegate,
std::unique_ptr<AttributionReportSender> report_sender,
std::unique_ptr<AttributionOsLevelManager> os_level_manager,
StoragePartitionImpl* storage_partition,
scoped_refptr<base::UpdateableSequencedTaskRunner> resolver_task_runner);
AttributionManagerImpl(
StoragePartitionImpl* storage_partition,
const base::FilePath& user_data_directory,
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy);
AttributionManagerImpl(const AttributionManagerImpl&) = delete;
AttributionManagerImpl& operator=(const AttributionManagerImpl&) = delete;
AttributionManagerImpl(AttributionManagerImpl&&) = delete;
AttributionManagerImpl& operator=(AttributionManagerImpl&&) = delete;
~AttributionManagerImpl() override;
// AttributionManager:
void AddObserver(AttributionObserver* observer) override;
void RemoveObserver(AttributionObserver* observer) override;
AttributionDataHostManager* GetDataHostManager() override;
void HandleSource(StorableSource source,
GlobalRenderFrameHostId render_frame_id) override;
void HandleTrigger(AttributionTrigger trigger,
GlobalRenderFrameHostId render_frame_id) override;
void GetActiveSourcesForWebUI(
base::OnceCallback<void(std::vector<StoredSource>)> callback) override;
void GetPendingReportsForInternalUse(
int limit,
base::OnceCallback<void(std::vector<AttributionReport>)> callback)
override;
void SendReportForWebUI(AttributionReport::Id,
base::OnceClosure done) override;
void ClearData(base::Time delete_begin,
base::Time delete_end,
StoragePartition::StorageKeyMatcherFunction filter,
BrowsingDataFilterBuilder* filter_builder,
bool delete_rate_limit_data,
base::OnceClosure done) override;
void SetDebugMode(std::optional<bool> enabled,
base::OnceClosure done) override;
void ReportRegistrationHeaderError(
attribution_reporting::SuitableOrigin reporting_origin,
attribution_reporting::RegistrationHeaderError,
const attribution_reporting::SuitableOrigin& context_origin,
bool is_within_fenced_frame,
GlobalRenderFrameHostId render_frame_id) override;
void GetAllDataKeys(
base::OnceCallback<void(std::set<DataKey>)> callback) override;
void RemoveAttributionDataByDataKey(const DataKey& data_key,
base::OnceClosure callback) override;
void HandleOsRegistration(OsRegistration) override;
void UpdateLastNavigationTime(base::Time navigation_time) override;
private:
friend class AttributionManagerImplTest;
class ReportScheduler;
using ReportSentCallback =
base::OnceCallback<void(const AttributionReport&, SendResult)>;
AttributionManagerImpl(
StoragePartitionImpl* storage_partition,
const base::FilePath& user_data_directory,
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
std::unique_ptr<AttributionResolverDelegate> resolver_delegate,
std::unique_ptr<AttributionReportSender> report_sender,
std::unique_ptr<AttributionOsLevelManager> os_level_manager,
scoped_refptr<base::UpdateableSequencedTaskRunner> resolver_task_runner,
bool debug_mode);
void GetReportsToSend();
void OnGetReportToSendFromWebUI(base::OnceClosure done,
std::optional<AttributionReport>);
void SendReports(std::vector<AttributionReport>);
void SendReport(base::OnceClosure web_ui_callback,
base::Time now,
AttributionReport);
void PrepareToSendReport(AttributionReport report,
bool is_debug_report,
ReportSentCallback callback);
void SendReport(AttributionReport report,
bool is_debug_report,
ReportSentCallback callback);
void OnReportSent(base::OnceClosure done,
const AttributionReport&,
SendResult info);
void AssembleAggregatableReport(AttributionReport report,
bool is_debug_report,
ReportSentCallback callback);
void OnAggregatableReportAssembled(
AttributionReport report,
bool is_debug_report,
ReportSentCallback callback,
AggregatableReportRequest,
std::optional<AggregatableReport> assembled_report,
AggregationService::AssemblyStatus);
void MarkReportCompleted(AttributionReport::Id report_id);
void OnSourceStored(std::optional<uint64_t> cleared_debug_key,
StoreSourceResult result);
void OnReportStored(std::optional<uint64_t> cleared_debug_key,
bool cookie_based_debug_allowed,
CreateReportResult result);
void MaybeSendDebugReport(AttributionReport&&);
void NotifySourcesChanged();
void NotifyReportsChanged();
void NotifyReportSent(bool is_debug_report,
const AttributionReport&,
SendResult);
void NotifyDebugReportSent(const AttributionDebugReport&, int status);
void NotifyOsRegistration(base::Time time,
const attribution_reporting::OsRegistrationItem&,
const url::Origin& top_level_origin,
bool is_debug_key_allowed,
attribution_reporting::mojom::RegistrationType,
attribution_reporting::mojom::OsRegistrationResult);
bool IsReportAllowed(const AttributionReport&) const;
void MaybeSendVerboseDebugReport(const StoreSourceResult& result);
void MaybeSendVerboseDebugReport(bool cookie_based_debug_allowed,
const CreateReportResult& result);
void MaybeSendVerboseDebugReports(const OsRegistration&);
void MaybeSendAggregatableDebugReport(const StoreSourceResult& result);
void MaybeSendAggregatableDebugReport(const CreateReportResult& result);
void OnAggregatableDebugReportProcessed(ProcessAggregatableDebugReportResult);
void OnAggregatableDebugReportAssembled(ProcessAggregatableDebugReportResult,
AggregatableReportRequest,
std::optional<AggregatableReport>,
AggregationService::AssemblyStatus);
void NotifyAggregatableDebugReportSent(
const AggregatableDebugReport&,
base::ValueView report_body,
attribution_reporting::mojom::ProcessAggregatableDebugReportResult,
SendAggregatableDebugReportResult);
void OnUserVisibleTaskStarted();
void OnUserVisibleTaskComplete();
void OnClearDataComplete(bool was_user_visible);
void OnOsRegistration(const std::vector<bool>& is_debug_key_allowed,
const OsRegistration&,
const std::vector<bool>& success);
const raw_ref<StoragePartitionImpl> storage_partition_;
// The task runner for all operations on the resolver.
// Updateable to allow for priority to be temporarily increased to
// `USER_VISIBLE` when a user-visible storage task is queued or running.
// Otherwise `BEST_EFFORT` is used.
scoped_refptr<base::UpdateableSequencedTaskRunner> resolver_task_runner_;
// How many user-visible storage tasks are queued or running currently,
// i.e. have been posted but the reply has not been run.
int num_pending_user_visible_tasks_ = 0;
base::SequenceBound<AttributionResolver> attribution_resolver_;
std::unique_ptr<ReportSchedulerTimer> scheduler_timer_;
std::unique_ptr<AttributionDataHostManager> data_host_manager_;
// Storage policy for the browser context |this| is in. May be nullptr.
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
std::unique_ptr<AttributionReportSender> report_sender_;
// Set of all conversion IDs that are currently being sent, deleted, or
// updated. The number of concurrent conversion reports being sent at any time
// is expected to be small, so a `flat_set` is used.
base::flat_set<AttributionReport::Id> reports_being_sent_;
base::ObserverList<AttributionObserver> observers_;
const std::unique_ptr<AttributionOsLevelManager> os_level_manager_;
// Technically redundant with fields in the `AttributionResolverDelegate` but
// duplicated here to avoid an async call to retrieve them.
bool debug_mode_ = false;
std::optional<base::Time> last_navigation_time_;
base::WeakPtrFactory<AttributionManagerImpl> weak_factory_{this};
};
// Gets the new delayed report time for a report that has failed to be sent
// `failed_send_attempts` times.
// Returns `std::nullopt` to indicate that no more attempts should be made.
// Otherwise, the return value must be later than current time.
// `failed_send_attempts` is guaranteed to be positive.
//
// If the `kAttributionReportNavigationBasedRetry` feature is enabled, at the
// `kAttributionReportNavigationRetryAttempt` send attempt, the report's expiry
// time will be returned for the navigation-based retry to occur with no issues.
//
// Exposed here for testing.
CONTENT_EXPORT
std::optional<base::Time> GetReportTimeForRetry(int failed_send_attempts,
base::Time report_expiry_time);
} // namespace content
#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_MANAGER_IMPL_H_