[go: nahoru, domu]

blob: ca5d1808abe0a96890a6eea4b372681151932e17 [file] [log] [blame]
// Copyright 2022 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_PRIVATE_AGGREGATION_PRIVATE_AGGREGATION_HOST_H_
#define CONTENT_BROWSER_PRIVATE_AGGREGATION_PRIVATE_AGGREGATION_HOST_H_
#include <map>
#include <optional>
#include <string>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/raw_ref.h"
#include "base/time/time.h"
#include "content/browser/private_aggregation/private_aggregation_budget_key.h"
#include "content/browser/private_aggregation/private_aggregation_budgeter.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "third_party/blink/public/common/shared_storage/shared_storage_utils.h"
#include "third_party/blink/public/mojom/private_aggregation/private_aggregation_host.mojom.h"
namespace base {
class ElapsedTimer;
class Uuid;
} // namespace base
namespace url {
class Origin;
} // namespace url
namespace content {
class AggregatableReportRequest;
class BrowserContext;
// UI thread class responsible for implementing the mojo interface used by
// worklets and renderers to request reports be sent and maintaining the
// receiver set for this interface. It is responsible for validating the
// messages received and then passing them on for budget approval.
class CONTENT_EXPORT PrivateAggregationHost
: public blink::mojom::PrivateAggregationHost {
public:
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class PipeResult {
kReportSuccess = 0,
kReportSuccessButTruncatedDueToTooManyContributions = 1,
kNoReportButNoError = 2,
kApiDisabledInSettings = 3,
kEnableDebugModeCalledMultipleTimes = 4,
kNegativeValue = 5,
kMaxValue = kNegativeValue,
};
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class TimeoutResult {
kOccurredBeforeRemoteDisconnection = 0,
kOccurredAfterRemoteDisconnection = 1,
kCanceledDueToError = 2,
kStillScheduledOnShutdown = 3,
kMaxValue = kStillScheduledOnShutdown,
};
using ReportRequestGenerator = base::OnceCallback<AggregatableReportRequest(
std::vector<blink::mojom::AggregatableReportHistogramContribution>)>;
// Version string for the reports generated by this API.
static constexpr char kApiReportVersion[] = "0.1";
// The maximum number of contributions that can go in an `AggregatableReport`.
// Aligns with `attribution_reporting::kMaxAggregationKeysPerSource`.
static constexpr int kMaxNumberOfContributions = 20;
// The maximum allowed context_id string length.
static constexpr int kMaxContextIdLength = 64;
static_assert(kMaxContextIdLength ==
blink::kPrivateAggregationApiContextIdMaxLength,
"Maximum length of context_id should be aligned between Shared "
"Storage and Private Aggregation.");
// `on_report_request_details_received` and `browser_context` must be
// non-null.
PrivateAggregationHost(
base::RepeatingCallback<void(
ReportRequestGenerator,
std::vector<blink::mojom::AggregatableReportHistogramContribution>,
PrivateAggregationBudgetKey,
PrivateAggregationBudgeter::BudgetDeniedBehavior)>
on_report_request_details_received,
BrowserContext* browser_context);
PrivateAggregationHost(const PrivateAggregationHost&) = delete;
PrivateAggregationHost& operator=(const PrivateAggregationHost&) = delete;
~PrivateAggregationHost() override;
// Binds a new pending receiver for a worklet, allowing messages to be sent
// and processed. However, the receiver is not bound if the `worklet_origin`
// is not potentially trustworthy or if `context_id` is too long. If
// `timeout` is set, the report will be sent as if the pipe closed after the
// timeout, regardless of when the disconnection actually happens. `timeout`
// must be positive if set. If `timeout` is set, `context_id` must be set too.
// If `aggregation_coordinator_origin` is set, the origin must be on the
// allowlist. But if the `kPrivateAggregationApiMultipleCloudProviders`
// feature is disabled, this function will act as if
// `aggregation_coordinator_origin` was not set. The return value indicates
// whether the receiver was accepted. Virtual for testing.
[[nodiscard]] virtual bool BindNewReceiver(
url::Origin worklet_origin,
url::Origin top_frame_origin,
PrivateAggregationBudgetKey::Api api_for_budgeting,
std::optional<std::string> context_id,
std::optional<base::TimeDelta> timeout,
std::optional<url::Origin> aggregation_coordinator_origin,
mojo::PendingReceiver<blink::mojom::PrivateAggregationHost>
pending_receiver);
bool IsDebugModeAllowed(const url::Origin& top_frame_origin,
const url::Origin& reporting_origin);
// blink::mojom::PrivateAggregationHost:
void ContributeToHistogram(
std::vector<blink::mojom::AggregatableReportHistogramContributionPtr>
contribution_ptrs) override;
void EnableDebugMode(blink::mojom::DebugKeyPtr debug_key) override;
void FlushReceiverSetForTesting() { receiver_set_.FlushForTesting(); }
private:
friend class PrivateAggregationReportGoldenLatestVersionTest;
struct ReceiverContext;
static AggregatableReportRequest GenerateReportRequest(
blink::mojom::DebugModeDetailsPtr debug_mode_details,
base::Time scheduled_report_time,
base::Uuid report_id,
const url::Origin& reporting_origin,
PrivateAggregationBudgetKey::Api api_for_budgeting,
std::optional<std::string> context_id,
std::optional<url::Origin> aggregation_coordinator_origin,
std::vector<blink::mojom::AggregatableReportHistogramContribution>
contributions);
void CloseCurrentPipe(PipeResult pipe_result);
void OnTimeoutBeforeDisconnect(mojo::ReceiverId id,
ReceiverContext* receiver_context);
void OnReceiverDisconnected();
void SendReportOnTimeoutOrDisconnect(ReceiverContext& current_context,
base::TimeDelta remaining_timeout);
// Set iff the private aggregation developer mode is set.
bool should_not_delay_reports_;
base::RepeatingCallback<void(
ReportRequestGenerator,
std::vector<blink::mojom::AggregatableReportHistogramContribution>,
PrivateAggregationBudgetKey,
PrivateAggregationBudgeter::BudgetDeniedBehavior)>
on_report_request_details_received_;
mojo::ReceiverSet<blink::mojom::PrivateAggregationHost,
std::unique_ptr<ReceiverContext>>
receiver_set_;
// A map containing a timer tracking the duration of time that each mojo pipe
// has been open. Used for duration measurement to ensure they are being
// closed appropriately.
std::map<mojo::ReceiverId, base::ElapsedTimer> pipe_duration_timers_;
// The number of open pipes where a timeout was specified.
int pipes_with_timeout_count_ = 0;
// `this` is indirectly owned by the StoragePartitionImpl, which itself is
// owned by `browser_context_`.
raw_ref<BrowserContext> browser_context_;
};
} // namespace content
#endif // CONTENT_BROWSER_PRIVATE_AGGREGATION_PRIVATE_AGGREGATION_HOST_H_