blob: d1ba6c77acb8eb02e07f9b5c89d245251d65abc8 [file] [log] [blame]
// Copyright 2020 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.
#ifndef CONTENT_BROWSER_CONVERSIONS_CONVERSION_REPORTER_IMPL_H_
#define CONTENT_BROWSER_CONVERSIONS_CONVERSION_REPORTER_IMPL_H_
#include <stdint.h>
#include <memory>
#include <queue>
#include <vector>
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/browser/conversions/conversion_manager_impl.h"
#include "content/browser/conversions/conversion_report.h"
#include "content/common/content_export.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace base {
class Clock;
} // namespace base
namespace content {
class StoragePartition;
class StoragePartitionImpl;
// This class is responsible for managing the dispatch of conversion reports to
// a ConversionReporterImpl::NetworkSender. It maintains a queue of reports and
// a timer to ensure all reports are sent at the correct time, since the time in
// which a conversion report is sent is potentially sensitive information.
// Created and owned by ConversionManager.
class CONTENT_EXPORT ConversionReporterImpl
: public ConversionManagerImpl::ConversionReporter {
public:
// This class is responsible for sending conversion reports to their
// configured endpoints over the network.
class NetworkSender {
public:
virtual ~NetworkSender() = default;
// Callback used to notify caller that the requested report has been sent.
using ReportSentCallback = base::OnceCallback<void()>;
// Generates and sends a conversion report matching |report|. This should
// generate a secure POST quest with no-credentials. Does not persist the
// raw pointer.
virtual void SendReport(ConversionReport* report,
ReportSentCallback sent_callback) = 0;
};
ConversionReporterImpl(StoragePartition* storage_partition,
const base::Clock* clock);
ConversionReporterImpl(const ConversionReporterImpl&) = delete;
ConversionReporterImpl& operator=(const ConversionReporterImpl&) = delete;
~ConversionReporterImpl() override;
// ConversionManagerImpl::ConversionReporter:
void AddReportsToQueue(
std::vector<ConversionReport> reports,
base::RepeatingCallback<void(int64_t)> report_sent_callback) override;
void SetNetworkSenderForTesting(
std::unique_ptr<NetworkSender> network_sender);
private:
void MaybeScheduleNextReport();
void SendNextReport();
// Called when a conversion report sent via NetworkSender::SendReport() has
// completed loading.
void OnReportSent(int64_t conversion_id);
// Comparator used to order ConversionReports by their report time, with the
// smallest time at the top of |report_queue_|.
struct ReportComparator {
bool operator()(const std::unique_ptr<ConversionReport>& a,
const std::unique_ptr<ConversionReport>& b) const;
};
// Priority queue which holds reports that are yet to be sent. Reports are
// removed from the queue when they are delivered to the NetworkSender.
std::priority_queue<std::unique_ptr<ConversionReport>,
std::vector<std::unique_ptr<ConversionReport>>,
ReportComparator>
report_queue_;
// Map of all conversion ids that are currently in |report_queue| or are being
// sent by |network_sender_|, and their associated report sent callbacks. The
// number of concurrent conversion reports being sent at any time is expected
// to be small, so a flat_map is used.
base::flat_map<int64_t, base::OnceCallback<void(int64_t)>>
conversion_report_callbacks_;
const base::Clock* clock_;
// Should never be nullptr, since StoragePartition owns the ConversionManager
// which owns |this|.
StoragePartitionImpl* partition_;
// Timer which signals the next report in |report_queue_| should be sent.
base::OneShotTimer send_report_timer_;
// Responsible for issuing requests to network for report that need to be
// sent. Calls OnReportSent() when a report has finished sending.
//
// Should never be nullptr.
std::unique_ptr<NetworkSender> network_sender_;
};
} // namespace content
#endif // CONTENT_BROWSER_CONVERSIONS_CONVERSION_REPORTER_IMPL_H_