Skip to content

Commit

Permalink
[Browsing Data Model] Attribution Data Model Implementation
Browse files Browse the repository at this point in the history
This implements the getter and remover function for the Browsing Data Model. This operates solely on reporting origin, but there are plans to incorporate context origin in the future.

(cherry picked from commit 02ed9db)

Bug: 1407369
Change-Id: I9fd76e6813f78040ab88b065711bd4a49e33afef
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4189258
Reviewed-by: Andrew Paseltiner <apaseltiner@chromium.org>
Commit-Queue: Thomas Quintanilla <tquintanilla@chromium.org>
Reviewed-by: Nan Lin <linnan@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1099326}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4214891
Cr-Commit-Position: refs/branch-heads/5563@{#96}
Cr-Branched-From: 3ac59a6-refs/heads/main@{#1097615}
  • Loading branch information
ThomasQuesadilla authored and Chromium LUCI CQ committed Feb 1, 2023
1 parent c1e7c21 commit 0b26ee1
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -802,18 +802,19 @@ void AttributionManagerImpl::OnClearDataComplete() {
NotifyReportsChanged(AttributionReport::Type::kAggregatableAttribution);
}

// TODO(crbug.com/1407369): Propagate calls to storage
void AttributionManagerImpl::GetAllDataKeys(
base::OnceCallback<void(std::vector<AttributionManager::DataKey>)>
callback) {
std::move(callback).Run({});
attribution_storage_.AsyncCall(&AttributionStorage::GetAllDataKeys)
.Then(std::move(callback));
}

// TODO(crbug.com/1407369): Propagate calls to storage
void AttributionManagerImpl::RemoveAttributionDataByDataKey(
const AttributionManager::DataKey& data_key,
base::OnceClosure callback) {
std::move(callback).Run();
attribution_storage_.AsyncCall(&AttributionStorage::DeleteByDataKey)
.WithArgs(data_key)
.Then(std::move(callback));
}

void AttributionManagerImpl::GetReportsToSend() {
Expand Down
10 changes: 10 additions & 0 deletions content/browser/attribution_reporting/attribution_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "content/browser/attribution_reporting/attribution_report.h"
#include "content/browser/attribution_reporting/storable_source.h"
#include "content/common/content_export.h"
#include "content/public/browser/attribution_data_model.h"
#include "content/public/browser/storage_partition.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

Expand Down Expand Up @@ -103,6 +104,15 @@ class AttributionStorage {
// a negative number for no limit.
virtual std::vector<StoredSource> GetActiveSources(int limit = -1) = 0;

// Returns all distinct reporting_origins as DataKeys for the
// Browsing Data Model. Partial data will still be returned
// in the event of an error.
virtual std::vector<AttributionDataModel::DataKey> GetAllDataKeys() = 0;

// Deletes all data in storage for storage keys matching the provided
// reporting origin in the data key.
virtual void DeleteByDataKey(const AttributionDataModel::DataKey&) = 0;

// Deletes the report with the given |report_id|. Returns
// false if an error occurred.
[[nodiscard]] virtual bool DeleteReport(AttributionReport::Id report_id) = 0;
Expand Down
36 changes: 36 additions & 0 deletions content/browser/attribution_reporting/attribution_storage_sql.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <stdint.h>

#include <functional>
#include <iterator>
#include <limits>
#include <string>
Expand Down Expand Up @@ -50,6 +51,7 @@
#include "content/browser/attribution_reporting/sql_utils.h"
#include "content/browser/attribution_reporting/storable_source.h"
#include "content/browser/attribution_reporting/stored_source.h"
#include "content/public/browser/attribution_data_model.h"
#include "net/base/schemeful_site.h"
#include "sql/database.h"
#include "sql/meta_table.h"
Expand Down Expand Up @@ -2928,4 +2930,38 @@ absl::optional<AttributionReport> AttributionStorageSql::GetReport(
return ReadAggregatableAttributionReportFromStatement(statement);
}

std::vector<AttributionDataModel::DataKey>
AttributionStorageSql::GetAllDataKeys() {
// We don't bother creating the DB here if it doesn't exist, because it's not
// possible for there to be any data to return if there's no DB
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) {
return {};
}

std::vector<AttributionDataModel::DataKey> keys;
sql::Statement statement(db_->GetCachedStatement(
SQL_FROM_HERE, attribution_queries::kGetSourcesDataKeysSql));

while (statement.Step()) {
url::Origin reporting_origin = DeserializeOrigin(statement.ColumnString(0));
if (reporting_origin.opaque()) {
continue;
}
keys.emplace_back(std::move(reporting_origin));
}

rate_limit_table_.AppendRateLimitDataKeys(db_.get(), keys);
return base::flat_set<AttributionDataModel::DataKey>(std::move(keys))
.extract();
}

void AttributionStorageSql::DeleteByDataKey(
const AttributionDataModel::DataKey& key) {
ClearData(base::Time::Min(), base::Time::Max(),
base::BindRepeating(std::equal_to<blink::StorageKey>(),
blink::StorageKey(key.reporting_origin())),
/*delete_rate_limit_data=*/true);
}

} // namespace content
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "content/browser/attribution_reporting/rate_limit_table.h"
#include "content/browser/attribution_reporting/stored_source.h"
#include "content/common/content_export.h"
#include "content/public/browser/attribution_data_model.h"
#include "content/public/browser/storage_partition.h"

namespace base {
Expand Down Expand Up @@ -112,6 +113,8 @@ class CONTENT_EXPORT AttributionStorageSql : public AttributionStorage {
std::vector<AttributionReport> GetReports(
const std::vector<AttributionReport::Id>& ids) override;
std::vector<StoredSource> GetActiveSources(int limit = -1) override;
std::vector<AttributionDataModel::DataKey> GetAllDataKeys() override;
void DeleteByDataKey(const AttributionDataModel::DataKey& datakey) override;
bool DeleteReport(AttributionReport::Id report_id) override;
bool UpdateReportForSendFailure(AttributionReport::Id report_id,
base::Time new_report_time) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,19 @@ TEST_F(AttributionSqlQueryPlanTest, kGetContributionsSql) {
UsesPrimaryKey());
}

TEST_F(AttributionSqlQueryPlanTest, kGetSourcesDataKeysSql) {
EXPECT_THAT(
GetPlan(attribution_queries::kGetSourcesDataKeysSql,
SqlFullScanReason::kIntentional),
UsesCoveringIndex("sources_by_active_destination_site_reporting_origin"));
}

TEST_F(AttributionSqlQueryPlanTest, kGetRateLimitDataKeysSql) {
EXPECT_THAT(GetPlan(attribution_queries::kGetRateLimitDataKeysSql,
SqlFullScanReason::kIntentional),
UsesCoveringIndex("rate_limit_source_site_reporting_origin_idx"));
}

TEST_F(AttributionSqlQueryPlanTest, kCountEventLevelReportsSql) {
EXPECT_THAT(GetPlan(attribution_queries::kCountEventLevelReportsSql),
AllOf(UsesCoveringIndex(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,25 @@ TEST_F(AttributionStorageSqlTest, ClearData_KeepRateLimitData) {
}
}

TEST_F(AttributionStorageSqlTest, DeleteAttributionDataByDataKey) {
OpenDatabase();
storage()->StoreSource(SourceBuilder().Build());

std::vector keys = storage()->GetAllDataKeys();
ASSERT_THAT(keys, SizeIs(1));

storage()->DeleteByDataKey(keys[0]);

CloseDatabase();

sql::Database raw_db;
ASSERT_TRUE(raw_db.Open(db_path()));
{
sql::Statement s(raw_db.GetUniqueStatement("SELECT * FROM sources"));
ASSERT_FALSE(s.Step());
}
}

TEST_F(AttributionStorageSqlTest, MaxSourcesPerOrigin) {
OpenDatabase();
delegate()->set_max_sources_per_origin(2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "content/browser/attribution_reporting/rate_limit_result.h"
#include "content/browser/attribution_reporting/storable_source.h"
#include "content/browser/attribution_reporting/stored_source.h"
#include "content/public/browser/attribution_data_model.h"
#include "content/public/browser/storage_partition.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/numeric/int128.h"
Expand Down Expand Up @@ -2343,6 +2344,37 @@ TEST_F(AttributionStorageTest, GetAttributionReportsExceedLimit_Shuffles) {
EventLevelDataIs(TriggerDataIs(3))));
}

TEST_F(AttributionStorageTest, GetAttributionDataKeysSet) {
auto expected_1 = AttributionDataModel::DataKey(
url::Origin::Create(GURL("https://a.r.test")));
auto expected_2 = AttributionDataModel::DataKey(
url::Origin::Create(GURL("https://b.r.test")));

auto s1 =
SourceBuilder()
.SetReportingOrigin(*SuitableOrigin::Deserialize("https://a.r.test"))
.Build();
auto s2 =
SourceBuilder()
.SetReportingOrigin(*SuitableOrigin::Deserialize("https://b.r.test"))
.SetSourceOrigin(*SuitableOrigin::Deserialize("https://s1.test"))
.SetDestinationOrigin(*SuitableOrigin::Deserialize("https://d1.test"))
.Build();
auto s3 =
SourceBuilder()
.SetReportingOrigin(*SuitableOrigin::Deserialize("https://b.r.test"))
.SetSourceOrigin(*SuitableOrigin::Deserialize("https://s2.test"))
.SetDestinationOrigin(*SuitableOrigin::Deserialize("https://d2.test"))
.Build();

storage()->StoreSource(s1);
storage()->StoreSource(s1);
storage()->StoreSource(s2);
storage()->StoreSource(s3);

EXPECT_THAT(storage()->GetAllDataKeys(), ElementsAre(expected_1, expected_2));
}

TEST_F(AttributionStorageTest, SourceDebugKey_RoundTrips) {
storage()->StoreSource(
SourceBuilder(base::Time::Now()).SetDebugKey(33).Build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "content/browser/attribution_reporting/attribution_trigger.h"
#include "content/browser/attribution_reporting/rate_limit_result.h"
#include "content/public/browser/attribution_config.h"
#include "content/public/browser/attribution_data_model.h"
#include "content/public/browser/navigation_handle.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "net/base/net_errors.h"
Expand Down Expand Up @@ -1282,6 +1283,11 @@ std::ostream& operator<<(std::ostream& out, StorableSource::Result status) {
}
}

std::ostream& operator<<(std::ostream& out,
const AttributionDataModel::DataKey& key) {
return out << "{reporting_origin=" << key.reporting_origin() << "}";
}

EventTriggerDataMatcherConfig::EventTriggerDataMatcherConfig(
::testing::Matcher<uint64_t> data,
::testing::Matcher<int64_t> priority,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "content/browser/attribution_reporting/storable_source.h"
#include "content/browser/attribution_reporting/stored_source.h"
#include "content/public/browser/attribution_config.h"
#include "content/public/browser/attribution_data_model.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/test/test_content_browser_client.h"
#include "mojo/public/cpp/bindings/receiver.h"
Expand Down Expand Up @@ -724,6 +725,11 @@ std::ostream& operator<<(std::ostream& out,

std::ostream& operator<<(std::ostream& out, StorableSource::Result status);

// TODO: Move to test-only public header to be reused by other test code
// that rely on DataKey
std::ostream& operator<<(std::ostream& out,
const AttributionDataModel::DataKey& key);

std::vector<AttributionReport> GetAttributionReportsForTesting(
AttributionManager* manager);

Expand Down
15 changes: 15 additions & 0 deletions content/browser/attribution_reporting/rate_limit_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -428,4 +428,19 @@ bool RateLimitTable::ClearDataForSourceIds(
return transaction.Commit();
}

void RateLimitTable::AppendRateLimitDataKeys(
sql::Database* db,
std::vector<AttributionDataModel::DataKey>& keys) {
sql::Statement statement(db->GetCachedStatement(
SQL_FROM_HERE, attribution_queries::kGetRateLimitDataKeysSql));

while (statement.Step()) {
url::Origin reporting_origin = DeserializeOrigin(statement.ColumnString(0));
if (reporting_origin.opaque()) {
continue;
}
keys.emplace_back(std::move(reporting_origin));
}
}

} // namespace content
5 changes: 5 additions & 0 deletions content/browser/attribution_reporting/rate_limit_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "base/time/time.h"
#include "content/browser/attribution_reporting/stored_source.h"
#include "content/common/content_export.h"
#include "content/public/browser/attribution_data_model.h"
#include "content/public/browser/storage_partition.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

Expand Down Expand Up @@ -97,6 +98,10 @@ class CONTENT_EXPORT RateLimitTable {
sql::Database* db,
const std::vector<StoredSource::Id>& source_ids);

void AppendRateLimitDataKeys(
sql::Database* db,
std::vector<AttributionDataModel::DataKey>& keys);

private:
[[nodiscard]] bool AddRateLimit(sql::Database* db,
const StoredSource& source,
Expand Down
27 changes: 27 additions & 0 deletions content/browser/attribution_reporting/rate_limit_table_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "content/browser/attribution_reporting/attribution_test_utils.h"
#include "content/browser/attribution_reporting/rate_limit_result.h"
#include "content/browser/attribution_reporting/stored_source.h"
#include "content/public/browser/attribution_data_model.h"
#include "content/public/browser/storage_partition.h"
#include "sql/database.h"
#include "sql/statement.h"
Expand Down Expand Up @@ -916,4 +917,30 @@ TEST_F(RateLimitTableTest, SourceAllowedForDestinationLimit) {
EXPECT_EQ(RateLimitResult::kAllowed, SourceAllowedForDestinationLimit(input));
}

TEST_F(RateLimitTableTest, GetAttributionDataKeyList) {
auto expected_1 = AttributionDataModel::DataKey(
url::Origin::Create(GURL("https://a.r.test")));
auto expected_2 = AttributionDataModel::DataKey(
url::Origin::Create(GURL("https://b.r.test")));

ASSERT_TRUE(table_.AddRateLimitForSource(
&db_,
SourceBuilder()
.SetReportingOrigin(*SuitableOrigin::Deserialize("https://a.r.test"))
.BuildStored()));

ASSERT_TRUE(table_.AddRateLimitForAttribution(
&db_, AttributionInfoBuilder(
SourceBuilder()
.SetReportingOrigin(
*SuitableOrigin::Deserialize("https://b.r.test"))
.BuildStored())
.Build()));

std::vector<AttributionDataModel::DataKey> keys;
table_.AppendRateLimitDataKeys(&db_, keys);

EXPECT_THAT(keys, ElementsAre(expected_1, expected_2));
}

} // namespace content
6 changes: 6 additions & 0 deletions content/browser/attribution_reporting/sql_queries.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ inline constexpr const char kGetContributionsSql[] =
"FROM aggregatable_contributions "
"WHERE aggregation_id=?";

inline constexpr const char kGetSourcesDataKeysSql[] =
"SELECT DISTINCT reporting_origin FROM sources";

inline constexpr const char kGetRateLimitDataKeysSql[] =
"SELECT DISTINCT reporting_origin FROM rate_limits";

// We need to hint to the query planner that/ `event_level_active` and
// `aggregatable_active` are booleans, so include them in the conditional.
#define ATTRIBUTION_COUNT_REPORTS_SQL(table) \
Expand Down

0 comments on commit 0b26ee1

Please sign in to comment.