[go: nahoru, domu]

blob: f94593de94cc2bdaee8811976100e568613385f7 [file] [log] [blame]
// Copyright 2022 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/test/attribution_simulator_impl.h"
#include <memory>
#include <utility>
#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/test/test_timeouts.h"
#include "base/values.h"
#include "content/browser/attribution_reporting/attribution_manager_impl.h"
#include "content/browser/attribution_reporting/attribution_storage_delegate_impl.h"
#include "content/browser/attribution_reporting/common_source_info.h"
#include "content/browser/attribution_reporting/send_result.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/test/attribution_simulator.h"
#include "content/public/test/browser_task_environment.h"
#include "services/network/test/test_network_connection_tracker.h"
#include "url/gurl.h"
namespace content {
namespace {
base::Time GetEventTime(const AttributionSimulationEvent& event) {
struct Visitor {
base::Time operator()(const StorableSource& source) {
return source.common_info().impression_time();
}
base::Time operator()(const AttributionTriggerAndTime& trigger) {
return trigger.time;
}
};
return absl::visit(Visitor{}, event);
}
class SentReportAccumulator : public AttributionManagerImpl::NetworkSender {
public:
SentReportAccumulator(base::Value::ListStorage& reports,
bool remove_report_ids)
: time_origin_(base::Time::Now()),
remove_report_ids_(remove_report_ids),
reports_(reports) {}
~SentReportAccumulator() override = default;
SentReportAccumulator(const SentReportAccumulator&) = delete;
SentReportAccumulator(SentReportAccumulator&&) = delete;
SentReportAccumulator& operator=(const SentReportAccumulator&) = delete;
SentReportAccumulator& operator=(SentReportAccumulator&&) = delete;
private:
// AttributionManagerImpl::NetworkSender:
void SendReport(GURL report_url,
base::Value report_body,
ReportSentCallback sent_callback) override {
if (remove_report_ids_)
report_body.RemoveKey("report_id");
base::DictionaryValue value;
value.SetKey("report", std::move(report_body));
value.SetStringKey("report_url", report_url.spec());
value.SetIntKey("report_time",
(base::Time::Now() - time_origin_).InSeconds());
reports_.push_back(std::move(value));
std::move(sent_callback)
.Run(SendResult(SendResult::Status::kSent,
/*http_response_code=*/200));
}
const base::Time time_origin_;
const bool remove_report_ids_;
base::Value::ListStorage& reports_;
};
struct EventHandler {
base::raw_ptr<AttributionManagerImpl> manager;
void operator()(StorableSource source) {
manager->HandleSourceInternalForTesting(std::move(source));
}
void operator()(AttributionTriggerAndTime trigger) {
manager->HandleTriggerInternalForTesting(std::move(trigger.trigger));
}
};
} // namespace
base::Value RunAttributionSimulation(
std::vector<AttributionSimulationEvent> events,
const AttributionSimulationOptions& options) {
base::ranges::stable_sort(events, /*comp=*/{}, &GetEventTime);
// Prerequisites for using an environment with mock time.
TestTimeouts::Initialize();
content::BrowserTaskEnvironment task_environment(
base::test::TaskEnvironment::TimeSource::MOCK_TIME);
// Avoid creating an on-disk sqlite DB.
content::AttributionManagerImpl::RunInMemoryForTesting();
// Ensure that the manager always thinks the browser is online.
auto network_connection_tracker =
network::TestNetworkConnectionTracker::CreateInstance();
content::SetNetworkConnectionTrackerForTesting(
network_connection_tracker.get());
auto always_allow_reports_callback =
base::BindRepeating([](const AttributionReport&) { return true; });
// This isn't needed because the DB is completely in memory for testing.
const base::FilePath user_data_directory;
base::Value::ListStorage reports;
auto manager = AttributionManagerImpl::CreateForTesting(
std::move(always_allow_reports_callback), user_data_directory,
/*special_storage_policy=*/nullptr,
std::make_unique<AttributionStorageDelegateImpl>(),
/*network_sender=*/
std::make_unique<SentReportAccumulator>(reports,
options.remove_report_ids));
// TODO(apaseltiner): Add an `AttributionManager::Observer` to `manager` so we
// can record dropped reports in the output.
EventHandler handler{.manager = manager.get()};
for (auto& event : events) {
task_environment.FastForwardBy(GetEventTime(event) - base::Time::Now());
absl::visit(handler, std::move(event));
}
absl::optional<base::Time> last_report_time;
base::RunLoop loop;
manager->GetPendingReportsForInternalUse(
base::BindLambdaForTesting([&](std::vector<AttributionReport> reports) {
if (!reports.empty()) {
last_report_time = base::ranges::max(reports, /*comp=*/{},
&AttributionReport::report_time)
.report_time();
}
loop.Quit();
}));
loop.Run();
if (last_report_time.has_value())
task_environment.FastForwardBy(*last_report_time - base::Time::Now());
base::DictionaryValue output;
output.SetKey("reports", base::Value(std::move(reports)));
return output;
}
} // namespace content