Clickiness: Add viewAndClickCountsProviders IG field
Bug: 394108643 Change-Id: I4e7b3c66c03935d62f1f320552935683323754a7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6248184 Commit-Queue: Caleb Raitto <caraitto@chromium.org> Reviewed-by: Yao Xiao <yaoxia@chromium.org> Reviewed-by: Jeremy Roman <jbroman@chromium.org> Reviewed-by: Ayu Ishii <ayui@chromium.org> Reviewed-by: Maks Orlovich <morlovich@chromium.org> Reviewed-by: Giovanni Ortuno Urquidi <ortuno@chromium.org> Cr-Commit-Position: refs/heads/main@{#1422203}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
f28f5e714c
commit
6bb1cf26eb
content
browser
interest_group
test
third_party/blink
common
interest_group
public
common
mojom
interest_group
renderer
modules
ad_auction
auction_ad_interest_group.idlnavigator_auction.ccvalidate_blink_interest_group.ccvalidate_blink_interest_group_test.cc
shared_storage
platform
tools
blinkpy
presubmit
tools/metrics/histograms/metadata/storage
@ -1592,6 +1592,7 @@ TEST_F(AdAuctionServiceImplTest, UpdateAllUpdatableFields) {
|
||||
"trustedBiddingSignalsSlotSizeMode": "slot-size",
|
||||
"maxTrustedBiddingSignalsURLLength": 8000,
|
||||
"trustedBiddingSignalsCoordinator": "https://trusted-bidding-signals.coordinator-b.test",
|
||||
"viewAndClickCountsProviders": ["https://view-and-click-counts-provider-b.test"],
|
||||
"userBiddingSignals": {"test":10},
|
||||
"updateURL": "%s/interest_group/new_daily_update_partial.json",
|
||||
"ads": [{"renderURL": "%s/new_ad_render_url",
|
||||
@ -1651,6 +1652,8 @@ TEST_F(AdAuctionServiceImplTest, UpdateAllUpdatableFields) {
|
||||
interest_group.max_trusted_bidding_signals_url_length = 10000;
|
||||
interest_group.trusted_bidding_signals_coordinator = url::Origin::Create(
|
||||
GURL("https://trusted-bidding-signals.coordinator-a.test"));
|
||||
interest_group.view_and_click_counts_providers = {{url::Origin::Create(
|
||||
GURL("https://view-and-click-counts-provider-a.test"))}};
|
||||
interest_group.ads.emplace();
|
||||
std::vector<url::Origin> allowed_reporting_origins = {kOriginF};
|
||||
blink::InterestGroup::Ad ad(
|
||||
@ -1738,6 +1741,10 @@ TEST_F(AdAuctionServiceImplTest, UpdateAllUpdatableFields) {
|
||||
EXPECT_EQ(group.max_trusted_bidding_signals_url_length, 8000);
|
||||
EXPECT_EQ(group.trusted_bidding_signals_coordinator->Serialize(),
|
||||
"https://trusted-bidding-signals.coordinator-b.test");
|
||||
ASSERT_TRUE(group.view_and_click_counts_providers.has_value());
|
||||
ASSERT_EQ(group.view_and_click_counts_providers->size(), 1u);
|
||||
EXPECT_EQ(group.view_and_click_counts_providers.value()[0].Serialize(),
|
||||
"https://view-and-click-counts-provider-b.test");
|
||||
ASSERT_TRUE(group.user_bidding_signals.has_value());
|
||||
EXPECT_EQ(group.user_bidding_signals.value(), "{\"test\":10}");
|
||||
|
||||
|
@ -5337,6 +5337,46 @@ IN_PROC_BROWSER_TEST_F(
|
||||
EvalJs(shell(), JsReplace(kScriptTemplate, origin_string.c_str())));
|
||||
}
|
||||
|
||||
class InterestGroupClickinessBrowserTest : public InterestGroupBrowserTest {
|
||||
public:
|
||||
InterestGroupClickinessBrowserTest() {
|
||||
feature_list_.InitWithFeatures({blink::features::kFledgeClickiness},
|
||||
/*disabled_features=*/{});
|
||||
}
|
||||
|
||||
protected:
|
||||
base::test::ScopedFeatureList feature_list_;
|
||||
};
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(InterestGroupClickinessBrowserTest,
|
||||
JoinInterestGroupNonOriginViewAndClickCountsProviders) {
|
||||
const char kScriptTemplate[] = R"(
|
||||
(async function() {
|
||||
try {
|
||||
await navigator.joinAdInterestGroup(
|
||||
{
|
||||
name: 'cars',
|
||||
owner: $1,
|
||||
viewAndClickCountsProviders: ['hi'],
|
||||
},
|
||||
/*joinDurationSec=*/10000);
|
||||
} catch (e) {
|
||||
return e.toString();
|
||||
}
|
||||
return 'done';
|
||||
})())";
|
||||
|
||||
GURL url = embedded_https_test_server().GetURL("a.test", "/echo");
|
||||
std::string origin_string = url::Origin::Create(url).Serialize();
|
||||
ASSERT_TRUE(NavigateToURL(shell(), url));
|
||||
|
||||
EXPECT_EQ(
|
||||
"TypeError: Failed to execute 'joinAdInterestGroup' on 'Navigator': "
|
||||
"viewAndClickCountsProviders 'hi' for AuctionAdInterestGroup with name "
|
||||
"'cars' must be a valid https origin.",
|
||||
EvalJs(shell(), JsReplace(kScriptTemplate, origin_string.c_str())));
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionInvalidSeller) {
|
||||
ASSERT_TRUE(NavigateToURL(
|
||||
shell(), embedded_https_test_server().GetURL("a.test", "/echo")));
|
||||
|
@ -202,6 +202,7 @@ const base::FilePath::CharType kDatabasePath[] =
|
||||
// Version 30 - 2024/08 - crrev.com/c/5707491
|
||||
// Version 31 - 2025/01 - crrev.com/c/6084483
|
||||
// Version 32 - 2025/02 - crrev.com/c/6239846
|
||||
// Version 33 - 2025/02 - crrev.com/c/6248184
|
||||
//
|
||||
// Version 1 adds a table for interest groups.
|
||||
// Version 2 adds a column for rate limiting interest group updates.
|
||||
@ -243,14 +244,15 @@ const base::FilePath::CharType kDatabasePath[] =
|
||||
// Version 30 compresses the AdsProto field using Snappy compression and runs a
|
||||
// VACUUM command.
|
||||
// Version 31 adds creative_scanning_metadata field to ad object.
|
||||
// Version 32 adds duration column to the debug report lockout table, and rename
|
||||
// its last_report_sent_time column to starting_time.
|
||||
// Version 32 adds duration column to the debug report lockout table, and
|
||||
// renames its last_report_sent_time column to starting_time.
|
||||
// Version 33 adds view_and_click_counts_providers interest_groups field.
|
||||
|
||||
const int kCurrentVersionNumber = 32;
|
||||
const int kCurrentVersionNumber = 33;
|
||||
|
||||
// Earliest version of the code which can use a |kCurrentVersionNumber| database
|
||||
// without failing.
|
||||
const int kCompatibleVersionNumber = 32;
|
||||
const int kCompatibleVersionNumber = 33;
|
||||
|
||||
// Latest version of the database that cannot be upgraded to
|
||||
// |kCurrentVersionNumber| without razing the database.
|
||||
@ -718,6 +720,56 @@ std::optional<std::vector<std::string>> DeserializeStringVector(
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Serialize(const std::optional<std::vector<url::Origin>>& origins) {
|
||||
std::string serialized;
|
||||
ListOfOrigins list_of_origins;
|
||||
|
||||
if (origins) {
|
||||
for (const url::Origin& o : origins.value()) {
|
||||
list_of_origins.add_origins(o.Serialize());
|
||||
}
|
||||
}
|
||||
if (list_of_origins.SerializeToString(&serialized)) {
|
||||
base::UmaHistogramEnumeration(
|
||||
"Storage.InterestGroup.ProtoSerializationResult.ListOfOrigins",
|
||||
InterestGroupStorageProtoSerializationResult::kSucceeded);
|
||||
} else {
|
||||
base::UmaHistogramEnumeration(
|
||||
"Storage.InterestGroup.ProtoSerializationResult.ListOfOrigins",
|
||||
InterestGroupStorageProtoSerializationResult::kFailed);
|
||||
// TODO(crbug.com/355010821): Consider bubbling out the failure.
|
||||
}
|
||||
return serialized;
|
||||
}
|
||||
|
||||
std::optional<std::vector<url::Origin>> DeserializeOriginVector(
|
||||
const std::string& serialized_vector) {
|
||||
ListOfOrigins list_of_origins;
|
||||
|
||||
bool success = list_of_origins.ParseFromString(serialized_vector);
|
||||
|
||||
if (success) {
|
||||
UMA_HISTOGRAM_ENUMERATION(
|
||||
"Storage.InterestGroup.ProtoDeserializationResult.ListOfOrigins",
|
||||
InterestGroupStorageProtoDeserializationResult::kSucceeded);
|
||||
} else {
|
||||
UMA_HISTOGRAM_ENUMERATION(
|
||||
"Storage.InterestGroup.ProtoDeserializationResult.ListOfOrigins",
|
||||
InterestGroupStorageProtoDeserializationResult::kFailed);
|
||||
// TODO(crbug.com/355010821): Consider bubbling out the failure.
|
||||
}
|
||||
|
||||
if (!success || list_of_origins.origins().empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::vector<url::Origin> result;
|
||||
result.reserve(list_of_origins.origins_size());
|
||||
for (const std::string& origin_string : list_of_origins.origins()) {
|
||||
result.emplace_back(DeserializeOrigin(origin_string));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t Serialize(SellerCapabilitiesType capabilities) {
|
||||
uint64_t result = capabilities.ToEnumBitmask();
|
||||
// Supporting 64 or more seller capabilities will require a different
|
||||
@ -886,7 +938,7 @@ std::set<std::string> GetAllKanonKeys(
|
||||
|
||||
// Adds indices to the `interest_group` table.
|
||||
// Call this function after the table has been created,
|
||||
// both when creating a new database in CreateVxxSchema
|
||||
// both when creating a new database in CreateCurrentSchema
|
||||
// and after dropping/recreating the `interest_groups` table
|
||||
// in the *latest* UpgradeVxxSchemaToVxx function to do so.
|
||||
bool CreateInterestGroupIndices(sql::Database& db) {
|
||||
@ -953,7 +1005,7 @@ bool CreateInterestGroupIndices(sql::Database& db) {
|
||||
|
||||
// Adds indices to the `kanon` table.
|
||||
// Call this function after the table has been created,
|
||||
// both when creating a new database in CreateVxxSchema
|
||||
// both when creating a new database in CreateCurrentSchema
|
||||
// and after dropping/recreating the `kanon` table
|
||||
// in the *latest* UpgradeVxxSchemaToVxx function to do so.
|
||||
bool CreateKAnonIndices(sql::Database& db) {
|
||||
@ -1063,6 +1115,7 @@ bool CreateCurrentSchema(sql::Database& db) {
|
||||
"trusted_bidding_signals_slot_size_mode INTEGER NOT NULL,"
|
||||
"max_trusted_bidding_signals_url_length INTEGER NOT NULL,"
|
||||
"trusted_bidding_signals_coordinator TEXT,"
|
||||
"view_and_click_counts_providers TEXT,"
|
||||
"user_bidding_signals TEXT,"
|
||||
"ads_pb BLOB NOT NULL,"
|
||||
"ad_components_pb BLOB NOT NULL,"
|
||||
@ -1204,6 +1257,115 @@ bool VacuumDB(sql::Database& db) {
|
||||
return db.Execute(kVacuum);
|
||||
}
|
||||
|
||||
bool UpgradeV32SchemaToV33(sql::Database& db, sql::MetaTable& meta_table) {
|
||||
// Make a table with new column `view_and_click_counts_providers`.
|
||||
static const char kInterestGroupTableSql[] =
|
||||
// clang-format off
|
||||
"CREATE TABLE new_interest_groups("
|
||||
"expiration INTEGER NOT NULL,"
|
||||
"last_updated INTEGER NOT NULL,"
|
||||
"next_update_after INTEGER NOT NULL,"
|
||||
"owner TEXT NOT NULL,"
|
||||
"joining_origin TEXT NOT NULL,"
|
||||
"exact_join_time INTEGER NOT NULL,"
|
||||
"name TEXT NOT NULL,"
|
||||
"priority DOUBLE NOT NULL,"
|
||||
"enable_bidding_signals_prioritization INTEGER NOT NULL,"
|
||||
"priority_vector TEXT NOT NULL,"
|
||||
"priority_signals_overrides TEXT NOT NULL,"
|
||||
"seller_capabilities TEXT NOT NULL,"
|
||||
"all_sellers_capabilities INTEGER NOT NULL,"
|
||||
"execution_mode INTEGER NOT NULL,"
|
||||
"joining_url TEXT NOT NULL,"
|
||||
"bidding_url TEXT NOT NULL,"
|
||||
"bidding_wasm_helper_url TEXT NOT NULL,"
|
||||
"update_url TEXT NOT NULL,"
|
||||
"trusted_bidding_signals_url TEXT NOT NULL,"
|
||||
"trusted_bidding_signals_keys TEXT NOT NULL,"
|
||||
"trusted_bidding_signals_slot_size_mode INTEGER NOT NULL,"
|
||||
"max_trusted_bidding_signals_url_length INTEGER NOT NULL,"
|
||||
"trusted_bidding_signals_coordinator TEXT,"
|
||||
"view_and_click_counts_providers TEXT,"
|
||||
"user_bidding_signals TEXT,"
|
||||
"ads_pb BLOB NOT NULL,"
|
||||
"ad_components_pb BLOB NOT NULL,"
|
||||
"ad_sizes TEXT NOT NULL,"
|
||||
"size_groups TEXT NOT NULL,"
|
||||
"auction_server_request_flags INTEGER NOT NULL,"
|
||||
"additional_bid_key BLOB NOT NULL,"
|
||||
"aggregation_coordinator_origin TEXT,"
|
||||
"storage_size INTEGER NOT NULL,"
|
||||
"last_k_anon_updated_time INTEGER NOT NULL, "
|
||||
"kanon_keys BLOB NOT NULL,"
|
||||
"PRIMARY KEY(owner,name))";
|
||||
|
||||
// clang-format on
|
||||
if (!db.Execute(kInterestGroupTableSql)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char kCopyInterestGroupTableSql[] =
|
||||
// clang-format off
|
||||
"INSERT INTO new_interest_groups "
|
||||
"SELECT expiration,"
|
||||
"last_updated,"
|
||||
"next_update_after,"
|
||||
"owner,"
|
||||
"joining_origin,"
|
||||
"exact_join_time,"
|
||||
"name,"
|
||||
"priority,"
|
||||
"enable_bidding_signals_prioritization,"
|
||||
"priority_vector,"
|
||||
"priority_signals_overrides,"
|
||||
"seller_capabilities,"
|
||||
"all_sellers_capabilities,"
|
||||
"execution_mode,"
|
||||
"joining_url,"
|
||||
"bidding_url,"
|
||||
"bidding_wasm_helper_url,"
|
||||
"update_url,"
|
||||
"trusted_bidding_signals_url,"
|
||||
"trusted_bidding_signals_keys,"
|
||||
"trusted_bidding_signals_slot_size_mode,"
|
||||
"max_trusted_bidding_signals_url_length,"
|
||||
"trusted_bidding_signals_coordinator,"
|
||||
"NULL," // view_and_click_counts_providers
|
||||
"user_bidding_signals,"
|
||||
"ads_pb,"
|
||||
"ad_components_pb,"
|
||||
"ad_sizes,"
|
||||
"size_groups,"
|
||||
"auction_server_request_flags,"
|
||||
"additional_bid_key,"
|
||||
"aggregation_coordinator_origin,"
|
||||
"storage_size,"
|
||||
"last_k_anon_updated_time,"
|
||||
"kanon_keys "
|
||||
"FROM interest_groups";
|
||||
// clang-format on
|
||||
|
||||
if (!db.Execute(kCopyInterestGroupTableSql)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char kDropInterestGroupTableSql[] = "DROP TABLE interest_groups";
|
||||
if (!db.Execute(kDropInterestGroupTableSql)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char kRenameInterestGroupTableSql[] =
|
||||
// clang-format off
|
||||
"ALTER TABLE new_interest_groups "
|
||||
"RENAME TO interest_groups";
|
||||
// clang-format on
|
||||
if (!db.Execute(kRenameInterestGroupTableSql)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return CreateInterestGroupIndices(db);
|
||||
}
|
||||
|
||||
bool UpgradeV31SchemaToV32(sql::Database& db, sql::MetaTable& meta_table) {
|
||||
// Adds duration column to the debug report lockout table, and rename its
|
||||
// last_report_sent_time column to starting_time.
|
||||
@ -3114,6 +3276,11 @@ bool UpgradeDB(sql::Database& db,
|
||||
if (!UpgradeV31SchemaToV32(db, meta_table)) {
|
||||
return false;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case 32:
|
||||
if (!UpgradeV32SchemaToV33(db, meta_table)) {
|
||||
return false;
|
||||
}
|
||||
if (!meta_table.SetVersionNumber(kCurrentVersionNumber)) {
|
||||
return false;
|
||||
}
|
||||
@ -3333,6 +3500,7 @@ std::optional<std::vector<std::string>> DoClearOriginJoinedInterestGroups(
|
||||
"trusted_bidding_signals_slot_size_mode," \
|
||||
"max_trusted_bidding_signals_url_length," \
|
||||
"trusted_bidding_signals_coordinator," \
|
||||
"view_and_click_counts_providers," \
|
||||
"user_bidding_signals," /* opaque data */ \
|
||||
"ads_pb," \
|
||||
"ad_components_pb," \
|
||||
@ -3387,28 +3555,32 @@ void PopulateInterestGroupFromQueryResult(sql::Statement& load,
|
||||
DeserializeOrigin(load.ColumnString(19));
|
||||
}
|
||||
if (load.GetColumnType(20) != sql::ColumnType::kNull) {
|
||||
group.interest_group.user_bidding_signals = load.ColumnString(20);
|
||||
group.interest_group.view_and_click_counts_providers =
|
||||
DeserializeOriginVector(load.ColumnString(20));
|
||||
}
|
||||
if (load.GetColumnType(21) != sql::ColumnType::kNull) {
|
||||
group.interest_group.user_bidding_signals = load.ColumnString(21);
|
||||
}
|
||||
group.interest_group.ads = DecompressAndDeserializeInterestGroupAdVectorProto(
|
||||
passkey, load.ColumnString(21));
|
||||
passkey, load.ColumnString(22));
|
||||
group.interest_group.ad_components =
|
||||
DecompressAndDeserializeInterestGroupAdVectorProto(passkey,
|
||||
load.ColumnString(22));
|
||||
load.ColumnString(23));
|
||||
group.interest_group.ad_sizes =
|
||||
DeserializeStringSizeMap(load.ColumnString(23));
|
||||
DeserializeStringSizeMap(load.ColumnString(24));
|
||||
group.interest_group.size_groups =
|
||||
DeserializeStringStringVectorMap(load.ColumnString(24));
|
||||
DeserializeStringStringVectorMap(load.ColumnString(25));
|
||||
group.interest_group.auction_server_request_flags =
|
||||
DeserializeAuctionServerRequestFlags(load.ColumnInt64(25));
|
||||
DeserializeAuctionServerRequestFlags(load.ColumnInt64(26));
|
||||
group.interest_group.additional_bid_key =
|
||||
DeserializeAdditionalBidKey(load.ColumnBlob(26));
|
||||
if (load.GetColumnType(27) != sql::ColumnType::kNull) {
|
||||
DeserializeAdditionalBidKey(load.ColumnBlob(27));
|
||||
if (load.GetColumnType(28) != sql::ColumnType::kNull) {
|
||||
group.interest_group.aggregation_coordinator_origin =
|
||||
DeserializeOrigin(load.ColumnString(27));
|
||||
DeserializeOrigin(load.ColumnString(28));
|
||||
}
|
||||
group.last_k_anon_updated = load.ColumnTime(28);
|
||||
group.last_k_anon_updated = load.ColumnTime(29);
|
||||
KAnonKeyProtos keys_proto;
|
||||
if (keys_proto.ParseFromString(load.ColumnString(29))) {
|
||||
if (keys_proto.ParseFromString(load.ColumnString(30))) {
|
||||
base::UmaHistogramEnumeration(
|
||||
"Storage.InterestGroup.ProtoDeserializationResult.KAnonKeyProtos",
|
||||
InterestGroupStorageProtoDeserializationResult::kSucceeded);
|
||||
@ -3602,6 +3774,7 @@ std::optional<InterestGroupKanonUpdateParameter> DoJoinInterestGroup(
|
||||
"trusted_bidding_signals_slot_size_mode,"
|
||||
"max_trusted_bidding_signals_url_length,"
|
||||
"trusted_bidding_signals_coordinator,"
|
||||
"view_and_click_counts_providers,"
|
||||
"user_bidding_signals," // opaque data
|
||||
"ads_pb,"
|
||||
"ad_components_pb,"
|
||||
@ -3614,7 +3787,7 @@ std::optional<InterestGroupKanonUpdateParameter> DoJoinInterestGroup(
|
||||
"last_k_anon_updated_time,"
|
||||
"kanon_keys) "
|
||||
"VALUES("
|
||||
"?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
|
||||
"?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
|
||||
));
|
||||
|
||||
// clang-format on
|
||||
@ -3651,24 +3824,29 @@ std::optional<InterestGroupKanonUpdateParameter> DoJoinInterestGroup(
|
||||
} else {
|
||||
join_group.BindNull(22);
|
||||
}
|
||||
if (data.user_bidding_signals) {
|
||||
join_group.BindString(23, data.user_bidding_signals.value());
|
||||
if (data.view_and_click_counts_providers) {
|
||||
join_group.BindString(23, Serialize(*data.view_and_click_counts_providers));
|
||||
} else {
|
||||
join_group.BindNull(23);
|
||||
}
|
||||
join_group.BindBlob(24, Serialize(data.ads));
|
||||
join_group.BindBlob(25, Serialize(data.ad_components));
|
||||
join_group.BindString(26, Serialize(data.ad_sizes));
|
||||
join_group.BindString(27, Serialize(data.size_groups));
|
||||
join_group.BindInt64(28, Serialize(data.auction_server_request_flags));
|
||||
join_group.BindBlob(29, Serialize(data.additional_bid_key));
|
||||
if (data.aggregation_coordinator_origin) {
|
||||
join_group.BindString(30, Serialize(*data.aggregation_coordinator_origin));
|
||||
if (data.user_bidding_signals) {
|
||||
join_group.BindString(24, data.user_bidding_signals.value());
|
||||
} else {
|
||||
join_group.BindNull(30);
|
||||
join_group.BindNull(24);
|
||||
}
|
||||
join_group.BindInt64(31, data.EstimateSize());
|
||||
join_group.BindTime(32, last_k_anon_updated);
|
||||
join_group.BindBlob(25, Serialize(data.ads));
|
||||
join_group.BindBlob(26, Serialize(data.ad_components));
|
||||
join_group.BindString(27, Serialize(data.ad_sizes));
|
||||
join_group.BindString(28, Serialize(data.size_groups));
|
||||
join_group.BindInt64(29, Serialize(data.auction_server_request_flags));
|
||||
join_group.BindBlob(30, Serialize(data.additional_bid_key));
|
||||
if (data.aggregation_coordinator_origin) {
|
||||
join_group.BindString(31, Serialize(*data.aggregation_coordinator_origin));
|
||||
} else {
|
||||
join_group.BindNull(31);
|
||||
}
|
||||
join_group.BindInt64(32, data.EstimateSize());
|
||||
join_group.BindTime(33, last_k_anon_updated);
|
||||
KAnonKeyProtos key_proto;
|
||||
*key_proto.mutable_keys() = {positive_kanon_keys.begin(),
|
||||
positive_kanon_keys.end()};
|
||||
@ -3683,7 +3861,7 @@ std::optional<InterestGroupKanonUpdateParameter> DoJoinInterestGroup(
|
||||
InterestGroupStorageProtoSerializationResult::kFailed);
|
||||
// TODO(crbug.com/355010821): Consider bubbling out the failure.
|
||||
}
|
||||
join_group.BindBlob(33, key_proto_str);
|
||||
join_group.BindBlob(34, key_proto_str);
|
||||
|
||||
if (!join_group.Run()) {
|
||||
return std::nullopt;
|
||||
@ -3745,6 +3923,7 @@ bool DoStoreInterestGroupUpdate(
|
||||
"trusted_bidding_signals_slot_size_mode=?,"
|
||||
"max_trusted_bidding_signals_url_length=?,"
|
||||
"trusted_bidding_signals_coordinator=?,"
|
||||
"view_and_click_counts_providers=?,"
|
||||
"user_bidding_signals=?,"
|
||||
"ads_pb=?,"
|
||||
"ad_components_pb=?,"
|
||||
@ -3787,24 +3966,30 @@ bool DoStoreInterestGroupUpdate(
|
||||
} else {
|
||||
store_group.BindNull(16);
|
||||
}
|
||||
if (group.user_bidding_signals) {
|
||||
store_group.BindString(17, group.user_bidding_signals.value());
|
||||
if (group.view_and_click_counts_providers) {
|
||||
store_group.BindString(17,
|
||||
Serialize(*group.view_and_click_counts_providers));
|
||||
} else {
|
||||
store_group.BindNull(17);
|
||||
}
|
||||
store_group.BindBlob(18, Serialize(group.ads));
|
||||
store_group.BindBlob(19, Serialize(group.ad_components));
|
||||
store_group.BindString(20, Serialize(group.ad_sizes));
|
||||
store_group.BindString(21, Serialize(group.size_groups));
|
||||
store_group.BindInt64(22, Serialize(group.auction_server_request_flags));
|
||||
store_group.BindBlob(23, Serialize(group.additional_bid_key));
|
||||
if (group.user_bidding_signals) {
|
||||
store_group.BindString(18, group.user_bidding_signals.value());
|
||||
} else {
|
||||
store_group.BindNull(18);
|
||||
}
|
||||
store_group.BindBlob(19, Serialize(group.ads));
|
||||
store_group.BindBlob(20, Serialize(group.ad_components));
|
||||
store_group.BindString(21, Serialize(group.ad_sizes));
|
||||
store_group.BindString(22, Serialize(group.size_groups));
|
||||
store_group.BindInt64(23, Serialize(group.auction_server_request_flags));
|
||||
store_group.BindBlob(24, Serialize(group.additional_bid_key));
|
||||
if (group.aggregation_coordinator_origin) {
|
||||
store_group.BindString(24,
|
||||
store_group.BindString(25,
|
||||
Serialize(*group.aggregation_coordinator_origin));
|
||||
} else {
|
||||
store_group.BindNull(24);
|
||||
store_group.BindNull(25);
|
||||
}
|
||||
store_group.BindInt64(25, group.EstimateSize());
|
||||
store_group.BindInt64(26, group.EstimateSize());
|
||||
|
||||
KAnonKeyProtos key_proto;
|
||||
*key_proto.mutable_keys() = {positive_kanon_keys.begin(),
|
||||
@ -3820,10 +4005,10 @@ bool DoStoreInterestGroupUpdate(
|
||||
InterestGroupStorageProtoSerializationResult::kFailed);
|
||||
// TODO(crbug.com/355010821): Consider bubbling out the failure.
|
||||
}
|
||||
store_group.BindBlob(26, key_proto_str);
|
||||
store_group.BindBlob(27, key_proto_str);
|
||||
|
||||
store_group.BindString(27, Serialize(group.owner));
|
||||
store_group.BindString(28, group.name);
|
||||
store_group.BindString(28, Serialize(group.owner));
|
||||
store_group.BindString(29, group.name);
|
||||
|
||||
return store_group.Run();
|
||||
}
|
||||
@ -3919,6 +4104,10 @@ std::optional<InterestGroupKanonUpdateParameter> DoUpdateInterestGroup(
|
||||
updated_group.trusted_bidding_signals_coordinator =
|
||||
std::move(update.trusted_bidding_signals_coordinator.value());
|
||||
}
|
||||
if (update.view_and_click_counts_providers.has_value()) {
|
||||
updated_group.view_and_click_counts_providers =
|
||||
std::move(update.view_and_click_counts_providers.value());
|
||||
}
|
||||
if (update.user_bidding_signals) {
|
||||
updated_group.user_bidding_signals = std::move(update.user_bidding_signals);
|
||||
}
|
||||
@ -4864,7 +5053,7 @@ std::optional<std::vector<StorageInterestGroup>> DoGetInterestGroupsForOwner(
|
||||
load.BindTime(1, now);
|
||||
|
||||
while (load.Step()) {
|
||||
std::string name = load.ColumnString(30);
|
||||
std::string name = load.ColumnString(31);
|
||||
StorageInterestGroup& db_interest_group = interest_group_by_name[name];
|
||||
db_interest_group.bidding_browser_signals =
|
||||
blink::mojom::BiddingBrowserSignals::New();
|
||||
|
@ -34,3 +34,7 @@ message BiddingAndAuctionServerKeyProtos {
|
||||
message KAnonKeyProtos {
|
||||
repeated bytes keys = 1;
|
||||
}
|
||||
|
||||
message ListOfOrigins {
|
||||
repeated string origins = 1;
|
||||
}
|
||||
|
@ -212,12 +212,16 @@ class InterestGroupStorageTest : public testing::Test {
|
||||
// instance.
|
||||
|
||||
switch (version_number) {
|
||||
case 33:
|
||||
result.view_and_click_counts_providers = {{url::Origin::Create(
|
||||
GURL("https://view-and-click-counts-provider.test"))}};
|
||||
[[fallthrough]];
|
||||
case 32:
|
||||
[[fallthrough]];
|
||||
case 31:
|
||||
result.ads.value()[0].creative_scanning_metadata = "scan 1";
|
||||
result.ad_components.value()[1].creative_scanning_metadata = "scan 2";
|
||||
ABSL_FALLTHROUGH_INTENDED;
|
||||
[[fallthrough]];
|
||||
case 30:
|
||||
// Compressed AdsProto, but introduced no new fields.
|
||||
[[fallthrough]];
|
||||
@ -3583,6 +3587,16 @@ TEST_F(InterestGroupStorageTest, MultiVersionUpgradeTest) {
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the metadata table got upgraded correctly.
|
||||
{
|
||||
sql::Database raw_db(sql::test::kTestTag);
|
||||
EXPECT_TRUE(raw_db.Open(db_path()));
|
||||
sql::MetaTable meta;
|
||||
ASSERT_TRUE(meta.Init(&raw_db, 1, 1));
|
||||
EXPECT_EQ(InterestGroupStorage::GetCurrentVersionNumberForTesting(),
|
||||
meta.GetVersionNumber());
|
||||
}
|
||||
|
||||
// Delete the database in case we loop again, creating the database from
|
||||
// another .sql file.
|
||||
base::DeleteFile(db_path());
|
||||
@ -3597,6 +3611,26 @@ TEST_F(InterestGroupStorageTest, MultiVersionUpgradeTest) {
|
||||
InterestGroupStorage::GetCurrentVersionNumberForTesting()));
|
||||
ASSERT_TRUE(base::PathExists(file_path))
|
||||
<< "Missing " << file_path << " -- " << kMisssingFileError;
|
||||
|
||||
// Also, make sure that the current version matches ProduceAllFields() -- they
|
||||
// might not match if the storage format changed after the initial DB dump for
|
||||
// the current version (that is, it changed before the CL introducing the new
|
||||
// version landed).
|
||||
{
|
||||
ASSERT_TRUE(sql::test::CreateDatabaseFromSQL(db_path(), file_path));
|
||||
blink::InterestGroup expected = ProduceAllFields();
|
||||
std::unique_ptr<InterestGroupStorage> storage = CreateStorage();
|
||||
std::vector<StorageInterestGroup> interest_groups =
|
||||
storage->GetAllInterestGroupsUnfilteredForTesting();
|
||||
|
||||
ASSERT_EQ(1u, interest_groups.size());
|
||||
const blink::InterestGroup& actual = interest_groups[0].interest_group;
|
||||
// Don't compare `expiry` as it changes every test run.
|
||||
expected.expiry = actual.expiry;
|
||||
IgExpectEqualsForTesting(actual, expected);
|
||||
// Delete the database before the next testcase.
|
||||
base::DeleteFile(db_path());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(InterestGroupStorageTest,
|
||||
|
@ -57,6 +57,7 @@ struct CONTENT_EXPORT InterestGroupUpdate {
|
||||
// when the value is `null` in JSON, allowing for a downgrade from KVv2 to
|
||||
// KVv1.
|
||||
std::optional<std::optional<url::Origin>> trusted_bidding_signals_coordinator;
|
||||
std::optional<std::vector<url::Origin>> view_and_click_counts_providers;
|
||||
std::optional<std::string> user_bidding_signals;
|
||||
std::optional<std::vector<blink::InterestGroup::Ad>> ads, ad_components;
|
||||
std::optional<base::flat_map<std::string, blink::AdSize>> ad_sizes;
|
||||
|
@ -424,6 +424,48 @@ constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
|
||||
return true;
|
||||
}
|
||||
|
||||
// Copies the viewAndClickCountsProviders JSON field into
|
||||
// `view_and_click_counts_providers`.
|
||||
[[nodiscard]] bool TryToCopyViewAndClickCountsProviders(
|
||||
const base::Value::Dict& dict,
|
||||
InterestGroupUpdate& interest_group_update) {
|
||||
const base::Value* maybe_view_and_click_counts_providers =
|
||||
dict.Find("viewAndClickCountsProviders");
|
||||
|
||||
// No `viewAndClickCountsProviders` field in the update JSON.
|
||||
if (!maybe_view_and_click_counts_providers) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// `viewAndClickCountsProviders` field is `null` in the update JSON.
|
||||
if (maybe_view_and_click_counts_providers->is_none()) {
|
||||
interest_group_update.view_and_click_counts_providers = std::nullopt;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If `view_and_click_counts_providers` is present and not null, it must
|
||||
// be a valid list of URL origin strings.
|
||||
if (!maybe_view_and_click_counts_providers->is_list()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const base::Value::List& view_and_click_counts_providers =
|
||||
maybe_view_and_click_counts_providers->GetList();
|
||||
|
||||
interest_group_update.view_and_click_counts_providers.emplace();
|
||||
interest_group_update.view_and_click_counts_providers->reserve(
|
||||
view_and_click_counts_providers.size());
|
||||
for (const base::Value& provider : view_and_click_counts_providers) {
|
||||
if (!provider.is_string()) {
|
||||
return false;
|
||||
}
|
||||
interest_group_update.view_and_click_counts_providers->emplace_back(
|
||||
url::Origin::Create(GURL(provider.GetString())));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper for TryToCopyAds() and TryToCopyAdComponents().
|
||||
[[nodiscard]] std::optional<std::vector<blink::InterestGroup::Ad>> ExtractAds(
|
||||
const base::Value::List& ads_list,
|
||||
@ -782,6 +824,9 @@ std::optional<InterestGroupUpdate> ParseUpdateJson(
|
||||
interest_group_update)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!TryToCopyViewAndClickCountsProviders(*dict, interest_group_update)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
if (!TryToCopyUserBiddingSignals(*dict, interest_group_update)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -7331,6 +7331,7 @@ data/interest_group/autogenSchemaV29.sql
|
||||
data/interest_group/autogenSchemaV30.sql
|
||||
data/interest_group/autogenSchemaV31.sql
|
||||
data/interest_group/autogenSchemaV32.sql
|
||||
data/interest_group/autogenSchemaV33.sql
|
||||
data/interest_group/bidding_argument_validator.js
|
||||
data/interest_group/bidding_argument_validator.js.mock-http-headers
|
||||
data/interest_group/bidding_logic.js
|
||||
|
24
content/test/data/interest_group/autogenSchemaV33.sql
Normal file
24
content/test/data/interest_group/autogenSchemaV33.sql
Normal file
@ -0,0 +1,24 @@
|
||||
PRAGMA foreign_keys=OFF;
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
|
||||
INSERT INTO meta VALUES('mmap_status','-1');
|
||||
INSERT INTO meta VALUES('version','33');
|
||||
INSERT INTO meta VALUES('last_compatible_version','33');
|
||||
CREATE TABLE interest_groups(expiration INTEGER NOT NULL,last_updated INTEGER NOT NULL,next_update_after INTEGER NOT NULL,owner TEXT NOT NULL,joining_origin TEXT NOT NULL,exact_join_time INTEGER NOT NULL,name TEXT NOT NULL,priority DOUBLE NOT NULL,enable_bidding_signals_prioritization INTEGER NOT NULL,priority_vector TEXT NOT NULL,priority_signals_overrides TEXT NOT NULL,seller_capabilities TEXT NOT NULL,all_sellers_capabilities INTEGER NOT NULL,execution_mode INTEGER NOT NULL,joining_url TEXT NOT NULL,bidding_url TEXT NOT NULL,bidding_wasm_helper_url TEXT NOT NULL,update_url TEXT NOT NULL,trusted_bidding_signals_url TEXT NOT NULL,trusted_bidding_signals_keys TEXT NOT NULL,trusted_bidding_signals_slot_size_mode INTEGER NOT NULL,max_trusted_bidding_signals_url_length INTEGER NOT NULL,trusted_bidding_signals_coordinator TEXT,view_and_click_counts_providers TEXT,user_bidding_signals TEXT,ads_pb BLOB NOT NULL,ad_components_pb BLOB NOT NULL,ad_sizes TEXT NOT NULL,size_groups TEXT NOT NULL,auction_server_request_flags INTEGER NOT NULL,additional_bid_key BLOB NOT NULL,aggregation_coordinator_origin TEXT,storage_size INTEGER NOT NULL,last_k_anon_updated_time INTEGER NOT NULL,kanon_keys BLOB NOT NULL,PRIMARY KEY(owner,name));
|
||||
INSERT INTO interest_groups VALUES(11648709739634000,11646117739634000,-9223372036854775808,'https://full.example.com','https://full.example.com',11646117739634000,'full',1.0,1,'{"a":2.0,"b":-2.2}','{"a":-2.0,"c":10.0,"d":1.2}','{"https://full.example.com":"1","https://partial.example.com":"2"}',3,2,'https://full.example.com/','https://full.example.com/bid','https://full.example.com/bid_wasm','https://full.example.com/update','https://full.example.com/signals','["a","b","c","d"]',2,8000,'https://coordinator.test',replace('\n+https://view-and-click-counts-provider.test','\n',char(10)),'foo',X'd401f0580a92010a1c68747470733a2f2f66756c6c2e6578616d706c652e636f6d2f616431120767726f75705f311a096d6574616461746131220862757965725f69642a097368617265645f6964320a616452656e64657249643a15680d53207265706f7274696e6701503c420e73656c65637461626c655f6964313a100034324a067363616e20310a3d0a1c680d410066469400003211940c321a096d0d942c32220962757965725f696432',X'9101f04c0a490a2568747470733a2f2f66756c6c2e6578616d706c652e636f6d2f6164636f6d706f6e656e7431120767726f75705f311a0a6d657461646174613163320b616452656e6465724964320a44964b000032114b04321a154b2432634a067363616e2032','{"size_1":"{\"height\":150.0,\"height_units\":1,\"width\":300.0,\"width_units\":1}","size_2":"{\"height\":480.0,\"height_units\":1,\"width\":640.0,\"width_units\":1}","size_3":"{\"height\":100.0,\"height_units\":2,\"width\":100.0,\"width_units\":2}"}','{"group_1":"[\"size_1\"]","group_2":"[\"size_1\",\"size_2\"]","group_3":"[\"size_3\"]"}',3,X'','https://coordinator.test',822,-9223372036854775808,X'');
|
||||
CREATE TABLE joined_k_anon(hashed_key BLOB NOT NULL,last_reported_to_anon_server_time INTEGER NOT NULL,PRIMARY KEY(hashed_key));
|
||||
CREATE TABLE join_history(owner TEXT NOT NULL,name TEXT NOT NULL,join_time INTEGER NOT NULL,count INTEGER NOT NULL,PRIMARY KEY(owner, name, join_time) FOREIGN KEY(owner,name) REFERENCES interest_groups);
|
||||
INSERT INTO join_history VALUES('https://full.example.com','full',11646115200000000,1);
|
||||
CREATE TABLE bid_history(owner TEXT NOT NULL,name TEXT NOT NULL,bid_time INTEGER NOT NULL,count INTEGER NOT NULL,PRIMARY KEY(owner, name, bid_time) FOREIGN KEY(owner,name) REFERENCES interest_groups);
|
||||
CREATE TABLE win_history(owner TEXT NOT NULL,name TEXT NOT NULL,win_time INTEGER NOT NULL,ad TEXT NOT NULL,FOREIGN KEY(owner,name) REFERENCES interest_groups);
|
||||
CREATE TABLE lockout_debugging_only_report(id INTEGER NOT NULL,starting_time INTEGER NOT NULL,duration INTEGER NOT NULL,PRIMARY KEY(id));
|
||||
CREATE TABLE cooldown_debugging_only_report(origin TEXT NOT NULL,starting_time INTEGER NOT NULL,type INTEGER NOT NULL,PRIMARY KEY(origin));
|
||||
CREATE TABLE bidding_and_auction_server_keys(coordinator TEXT NOT NULL,keys BLOB NOT NULL,expiration INTEGER NOT NULL,PRIMARY KEY(coordinator));
|
||||
CREATE INDEX interest_group_expiration ON interest_groups(expiration DESC, owner, name);
|
||||
CREATE INDEX interest_group_owner ON interest_groups(owner,expiration DESC,next_update_after ASC,name);
|
||||
CREATE INDEX interest_group_owner_and_type ON interest_groups(LENGTH(additional_bid_key) == 0,owner,expiration DESC,name);
|
||||
CREATE INDEX interest_group_owner_size ON interest_groups(owner,expiration DESC,storage_size);
|
||||
CREATE INDEX interest_group_joining_origin ON interest_groups(joining_origin, expiration DESC, owner, name);
|
||||
CREATE INDEX k_anon_last_server_time_idx ON joined_k_anon(last_reported_to_anon_server_time DESC);
|
||||
CREATE INDEX win_history_index ON win_history(owner,name,win_time DESC);
|
||||
COMMIT;
|
@ -504,6 +504,8 @@ base::Value::Dict SerializeInterestGroupForDevtools(const InterestGroup& ig) {
|
||||
ig.max_trusted_bidding_signals_url_length, result);
|
||||
SerializeIntoDict("trustedBiddingSignalsCoordinator",
|
||||
ig.trusted_bidding_signals_coordinator, result);
|
||||
SerializeIntoDict("viewAndClickCountsProviders",
|
||||
ig.view_and_click_counts_providers, result);
|
||||
SerializeIntoDict("userBiddingSignals", ig.user_bidding_signals, result);
|
||||
SerializeIntoDict("ads", ig.ads, result);
|
||||
SerializeIntoDict("adComponents", ig.ad_components, result);
|
||||
|
@ -265,6 +265,8 @@ TEST(SerializeInterestGroupTest, Basic) {
|
||||
ig.max_trusted_bidding_signals_url_length = 100;
|
||||
ig.trusted_bidding_signals_coordinator =
|
||||
url::Origin::Create(GURL("https://example.test"));
|
||||
ig.view_and_click_counts_providers = {
|
||||
{url::Origin::Create(GURL("https://example.test"))}};
|
||||
ig.user_bidding_signals = "hello";
|
||||
ig.ads = {
|
||||
{blink::InterestGroup::Ad(
|
||||
@ -309,6 +311,7 @@ TEST(SerializeInterestGroupTest, Basic) {
|
||||
"trustedBiddingSignalsSlotSizeMode": "all-slots-requested-sizes",
|
||||
"maxTrustedBiddingSignalsURLLength": 100,
|
||||
"trustedBiddingSignalsCoordinator": "https://example.test",
|
||||
"viewAndClickCountsProviders": ["https://example.test"],
|
||||
"userBiddingSignals": "hello",
|
||||
"ads": [ {
|
||||
"adRenderId": "ad_render_id",
|
||||
|
@ -316,6 +316,14 @@ bool InterestGroup::IsValid() const {
|
||||
}
|
||||
}
|
||||
|
||||
if (view_and_click_counts_providers) {
|
||||
for (const url::Origin& provider : *view_and_click_counts_providers) {
|
||||
if (provider.scheme() != url::kHttpsScheme) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ads) {
|
||||
std::optional<size_t> selectable_buyer_and_seller_reporting_ids_hard_limit;
|
||||
if (base::FeatureList::IsEnabled(
|
||||
@ -504,6 +512,11 @@ size_t InterestGroup::EstimateSize() const {
|
||||
if (trusted_bidding_signals_coordinator) {
|
||||
size += trusted_bidding_signals_coordinator->Serialize().size();
|
||||
}
|
||||
if (view_and_click_counts_providers) {
|
||||
for (const url::Origin& provider : *view_and_click_counts_providers) {
|
||||
size += provider.Serialize().size();
|
||||
}
|
||||
}
|
||||
if (user_bidding_signals) {
|
||||
size += user_bidding_signals->size();
|
||||
}
|
||||
|
@ -81,6 +81,8 @@ bool StructTraits<blink::mojom::InterestGroupDataView, blink::InterestGroup>::
|
||||
!data.ReadTrustedBiddingSignalsKeys(&out->trusted_bidding_signals_keys) ||
|
||||
!data.ReadTrustedBiddingSignalsCoordinator(
|
||||
&out->trusted_bidding_signals_coordinator) ||
|
||||
!data.ReadViewAndClickCountsProviders(
|
||||
&out->view_and_click_counts_providers) ||
|
||||
!data.ReadUserBiddingSignals(&out->user_bidding_signals) ||
|
||||
!data.ReadAds(&out->ads) || !data.ReadAdComponents(&out->ad_components) ||
|
||||
!data.ReadAdSizes(&out->ad_sizes) ||
|
||||
|
@ -290,6 +290,23 @@ TEST(InterestGroupMojomTraitsTest,
|
||||
"trustedBiddingSignalsCoordinator");
|
||||
}
|
||||
|
||||
TEST(InterestGroupMojomTraitsTest,
|
||||
SerializeAndDeserializeViewAndClickCountsProviders) {
|
||||
InterestGroup interest_group = CreateInterestGroup();
|
||||
interest_group.view_and_click_counts_providers = {
|
||||
{url::Origin::Create(GURL("https://example.test"))}};
|
||||
SerializeAndDeserializeAndCompare(interest_group);
|
||||
}
|
||||
|
||||
TEST(InterestGroupMojomTraitsTest,
|
||||
SerializeAndDeserializeInvalidViewAndClickCountsProviders) {
|
||||
InterestGroup interest_group = CreateInterestGroup();
|
||||
interest_group.view_and_click_counts_providers = {
|
||||
{url::Origin::Create(GURL("http://example.test"))}};
|
||||
SerializeAndDeserializeExpectFailure(interest_group,
|
||||
"viewAndClickCountsProviders");
|
||||
}
|
||||
|
||||
TEST(InterestGroupMojomTraitsTest, SerializeAndDeserializeUserBiddingSignals) {
|
||||
InterestGroup interest_group = CreateInterestGroup();
|
||||
interest_group.user_bidding_signals = "[]";
|
||||
|
@ -204,6 +204,12 @@ void InterestGroupCompare(const blink::InterestGroup& actual,
|
||||
expected.max_trusted_bidding_signals_url_length);
|
||||
IG_COMPARE(actual.trusted_bidding_signals_coordinator,
|
||||
expected.trusted_bidding_signals_coordinator);
|
||||
auto compare_origins = [&](const url::Origin& actual,
|
||||
const url::Origin& expected) {
|
||||
IG_COMPARE(actual, expected);
|
||||
};
|
||||
IG_COMPARE_VEC(actual.view_and_click_counts_providers,
|
||||
expected.view_and_click_counts_providers, compare_origins);
|
||||
IG_COMPARE(actual.user_bidding_signals, expected.user_bidding_signals);
|
||||
auto compare_ads = [&](const blink::InterestGroup::Ad& actual,
|
||||
const blink::InterestGroup::Ad& expected) {
|
||||
@ -218,10 +224,6 @@ void InterestGroupCompare(const blink::InterestGroup& actual,
|
||||
compare_strings);
|
||||
IG_COMPARE(actual.ad_render_id, expected.ad_render_id);
|
||||
|
||||
auto compare_origins = [&](const url::Origin& actual,
|
||||
const url::Origin& expected) {
|
||||
IG_COMPARE(actual, expected);
|
||||
};
|
||||
IG_COMPARE_VEC(actual.allowed_reporting_origins,
|
||||
expected.allowed_reporting_origins, compare_origins);
|
||||
IG_COMPARE(actual.creative_scanning_metadata,
|
||||
|
@ -143,7 +143,15 @@ TestInterestGroupBuilder&
|
||||
TestInterestGroupBuilder::SetTrustedBiddingSignalsCoordinator(
|
||||
std::optional<url::Origin> trusted_bidding_signals_coordinator) {
|
||||
interest_group_.trusted_bidding_signals_coordinator =
|
||||
trusted_bidding_signals_coordinator;
|
||||
std::move(trusted_bidding_signals_coordinator);
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestInterestGroupBuilder&
|
||||
TestInterestGroupBuilder::SetViewAndClickCountsProviders(
|
||||
std::optional<std::vector<url::Origin>> view_and_click_counts_providers) {
|
||||
interest_group_.view_and_click_counts_providers =
|
||||
std::move(view_and_click_counts_providers);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -194,7 +202,8 @@ TestInterestGroupBuilder& TestInterestGroupBuilder::SetAdditionalBidKey(
|
||||
TestInterestGroupBuilder&
|
||||
TestInterestGroupBuilder::SetAggregationCoordinatorOrigin(
|
||||
std::optional<url::Origin> agg_coordinator_origin) {
|
||||
interest_group_.aggregation_coordinator_origin = agg_coordinator_origin;
|
||||
interest_group_.aggregation_coordinator_origin =
|
||||
std::move(agg_coordinator_origin);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -170,6 +170,7 @@ struct BLINK_COMMON_EXPORT InterestGroup {
|
||||
TrustedBiddingSignalsSlotSizeMode::kNone;
|
||||
int32_t max_trusted_bidding_signals_url_length = 0;
|
||||
std::optional<url::Origin> trusted_bidding_signals_coordinator;
|
||||
std::optional<std::vector<url::Origin>> view_and_click_counts_providers;
|
||||
std::optional<std::string> user_bidding_signals;
|
||||
std::optional<std::vector<InterestGroup::Ad>> ads, ad_components;
|
||||
std::optional<base::flat_map<std::string, blink::AdSize>> ad_sizes;
|
||||
@ -181,7 +182,7 @@ struct BLINK_COMMON_EXPORT InterestGroup {
|
||||
std::optional<AdditionalBidKey> additional_bid_key;
|
||||
std::optional<url::Origin> aggregation_coordinator_origin;
|
||||
|
||||
static_assert(__LINE__ == 184, R"(
|
||||
static_assert(__LINE__ == 185, R"(
|
||||
If modifying InterestGroup fields, make sure to also modify:
|
||||
|
||||
* IsValid(), EstimateSize(), and in this class
|
||||
@ -189,13 +190,13 @@ If modifying InterestGroup fields, make sure to also modify:
|
||||
* SerializeInterestGroupForDevtools()
|
||||
(in devtools_serialization.cc; test in devtools_serialization_unittest.cc)
|
||||
* auction_ad_interest_group.idl
|
||||
* navigator_auction.cc
|
||||
* navigator_auction.cc (test logic in interest_group_browsertest.cc)
|
||||
* interest_group_types.mojom
|
||||
* validate_blink_interest_group.cc (includes blink version of EstimateSize)
|
||||
* validate_blink_interest_group_test.cc
|
||||
(at least CreateFullyPopulatedInterestGroup)
|
||||
* test_interest_group_builder[.h/.cc]
|
||||
* interest_group_mojom_traits[.h/.cc/.test]
|
||||
* interest_group_mojom_traits[.h/.cc/_test.cc]
|
||||
* bidder_lazy_filler.cc (to pass the InterestGroup to generateBid())
|
||||
* shared_storage_worklet_global_scope.cc (interestGroups())
|
||||
* shared_storage_worklet_unittest.cc (SharedStorageWorkletTest.InterestGroups)
|
||||
|
@ -206,6 +206,11 @@ struct BLINK_COMMON_EXPORT
|
||||
return interest_group.trusted_bidding_signals_coordinator;
|
||||
}
|
||||
|
||||
static const std::optional<std::vector<url::Origin>>&
|
||||
view_and_click_counts_providers(const blink::InterestGroup& interest_group) {
|
||||
return interest_group.view_and_click_counts_providers;
|
||||
}
|
||||
|
||||
static const std::optional<std::string>& user_bidding_signals(
|
||||
const blink::InterestGroup& interest_group) {
|
||||
return interest_group.user_bidding_signals;
|
||||
|
@ -63,6 +63,8 @@ class TestInterestGroupBuilder {
|
||||
int32_t max_trusted_bidding_signals_url_length);
|
||||
TestInterestGroupBuilder& SetTrustedBiddingSignalsCoordinator(
|
||||
std::optional<url::Origin> trusted_bidding_signals_coordinator);
|
||||
TestInterestGroupBuilder& SetViewAndClickCountsProviders(
|
||||
std::optional<std::vector<url::Origin>> view_and_click_counts_providers);
|
||||
TestInterestGroupBuilder& SetUserBiddingSignals(
|
||||
std::optional<std::string> user_bidding_signals);
|
||||
TestInterestGroupBuilder& SetAds(
|
||||
|
@ -179,6 +179,9 @@ struct InterestGroup {
|
||||
// An optional field for matching the encryption key, and indicating which
|
||||
// version of the key-value server this interest group uses.
|
||||
url.mojom.Origin? trusted_bidding_signals_coordinator;
|
||||
// Stores the set of origins that are allowed to provide view and click
|
||||
// counts to this interest group's generateBid() function.
|
||||
array<url.mojom.Origin>? view_and_click_counts_providers;
|
||||
// Opaque JSON data, persisted, then passed as object to auction worklet.
|
||||
string? user_bidding_signals;
|
||||
array<InterestGroupAd>? ads;
|
||||
|
@ -67,6 +67,8 @@ dictionary AuctionAdInterestGroup {
|
||||
long maxTrustedBiddingSignalsURLLength;
|
||||
[RuntimeEnabled=FledgeTrustedSignalsKVv2Support]
|
||||
USVString trustedBiddingSignalsCoordinator;
|
||||
[RuntimeEnabled=FledgeClickiness]
|
||||
sequence<USVString> viewAndClickCountsProviders;
|
||||
any userBiddingSignals;
|
||||
sequence<AuctionAd> ads;
|
||||
sequence<AuctionAd> adComponents;
|
||||
|
@ -942,6 +942,31 @@ bool CopyTrustedBiddingSignalsCoordinatorFromIdlToMojo(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CopyViewAndClickCountsProvidersFromIdlToMojo(
|
||||
ExceptionState& exception_state,
|
||||
const AuctionAdInterestGroup& input,
|
||||
mojom::blink::InterestGroup& output) {
|
||||
if (!input.hasViewAndClickCountsProviders()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector<scoped_refptr<const SecurityOrigin>> view_and_click_counts_providers;
|
||||
for (const String& provider : input.viewAndClickCountsProviders()) {
|
||||
scoped_refptr<const SecurityOrigin> parsed_provider = ParseOrigin(provider);
|
||||
if (!parsed_provider) {
|
||||
exception_state.ThrowTypeError(String::Format(
|
||||
"viewAndClickCountsProviders '%s' for AuctionAdInterestGroup "
|
||||
"with name '%s' must be a valid https origin.",
|
||||
provider.Utf8().c_str(), input.name().Utf8().c_str()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
output.view_and_click_counts_providers =
|
||||
std::move(view_and_click_counts_providers);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CopyUserBiddingSignalsFromIdlToMojo(const ScriptState& script_state,
|
||||
ExceptionState& exception_state,
|
||||
const AuctionAdInterestGroup& input,
|
||||
@ -3464,6 +3489,8 @@ ScriptPromise<IDLUndefined> NavigatorAuction::joinAdInterestGroup(
|
||||
exception_state, *group, *mojo_group) ||
|
||||
!CopyTrustedBiddingSignalsCoordinatorFromIdlToMojo(exception_state,
|
||||
*group, *mojo_group) ||
|
||||
!CopyViewAndClickCountsProvidersFromIdlToMojo(exception_state, *group,
|
||||
*mojo_group) ||
|
||||
!CopyUserBiddingSignalsFromIdlToMojo(*script_state, exception_state,
|
||||
*group, *mojo_group) ||
|
||||
!CopyAdsFromIdlToMojo(*context, *script_state, exception_state, *group,
|
||||
|
@ -123,6 +123,12 @@ size_t EstimateBlinkInterestGroupSize(
|
||||
if (group.trusted_bidding_signals_coordinator) {
|
||||
size += group.trusted_bidding_signals_coordinator->ToString().length();
|
||||
}
|
||||
if (group.view_and_click_counts_providers) {
|
||||
for (const scoped_refptr<const SecurityOrigin>& provider :
|
||||
*group.view_and_click_counts_providers) {
|
||||
size += provider->ToString().length();
|
||||
}
|
||||
}
|
||||
size += group.user_bidding_signals.length();
|
||||
|
||||
if (group.ads) {
|
||||
@ -317,6 +323,18 @@ bool ValidateBlinkInterestGroup(const mojom::blink::InterestGroup& group,
|
||||
}
|
||||
}
|
||||
|
||||
if (group.view_and_click_counts_providers) {
|
||||
for (const scoped_refptr<const SecurityOrigin>& provider :
|
||||
*group.view_and_click_counts_providers) {
|
||||
if (provider->Protocol() != url::kHttpsScheme) {
|
||||
error_field_name = "viewAndClickCountsProviders";
|
||||
error_field_value = provider->ToString();
|
||||
error = "viewAndClickCountsProviders origin must be HTTPS.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (group.ads) {
|
||||
std::optional<WTF::wtf_size_t>
|
||||
selectable_buyer_and_seller_reporting_ids_hard_limit;
|
||||
|
@ -179,6 +179,9 @@ class ValidateBlinkInterestGroupTest : public testing::Test {
|
||||
blink_interest_group->max_trusted_bidding_signals_url_length = 8000;
|
||||
blink_interest_group->trusted_bidding_signals_coordinator =
|
||||
kCoordinatorOrigin;
|
||||
blink_interest_group->view_and_click_counts_providers.emplace();
|
||||
blink_interest_group->view_and_click_counts_providers->emplace_back(
|
||||
kOrigin);
|
||||
blink_interest_group->user_bidding_signals =
|
||||
String::FromUTF8("\"This field isn't actually validated\"");
|
||||
|
||||
@ -1549,4 +1552,32 @@ TEST_F(ValidateBlinkInterestGroupTest,
|
||||
"trustedBiddingSignalsCoordinator origin must be HTTPS."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateBlinkInterestGroupTest, InvalidViewAndClickCountsProviders) {
|
||||
mojom::blink::InterestGroupPtr blink_interest_group =
|
||||
CreateMinimalInterestGroup();
|
||||
blink_interest_group->view_and_click_counts_providers.emplace();
|
||||
blink_interest_group->view_and_click_counts_providers->emplace_back(
|
||||
SecurityOrigin::CreateFromString(
|
||||
String::FromUTF8("http://origin.test/")));
|
||||
ExpectInterestGroupIsNotValid(
|
||||
blink_interest_group,
|
||||
/*expected_error_field_name=*/
|
||||
String::FromUTF8("viewAndClickCountsProviders"),
|
||||
/*expected_error_field_value=*/String::FromUTF8("http://origin.test"),
|
||||
/*expected_error=*/
|
||||
String::FromUTF8("viewAndClickCountsProviders origin must be HTTPS."));
|
||||
|
||||
blink_interest_group->view_and_click_counts_providers.emplace();
|
||||
blink_interest_group->view_and_click_counts_providers->emplace_back(
|
||||
SecurityOrigin::CreateFromString(String::FromUTF8("data:,foo")));
|
||||
// Data URLs have opaque origins, which are mapped to the string "null".
|
||||
ExpectInterestGroupIsNotValid(
|
||||
blink_interest_group,
|
||||
/*expected_error_field_name=*/
|
||||
String::FromUTF8("viewAndClickCountsProviders"),
|
||||
/*expected_error_field_value=*/String::FromUTF8("null"),
|
||||
/*expected_error=*/
|
||||
String::FromUTF8("viewAndClickCountsProviders origin must be HTTPS."));
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
|
16
third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.cc
vendored
16
third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_global_scope.cc
vendored
@ -876,6 +876,22 @@ SharedStorageWorkletGlobalScope::interestGroups(
|
||||
->trusted_bidding_signals_coordinator->ToString());
|
||||
}
|
||||
|
||||
if (mojom_group->interest_group
|
||||
->view_and_click_counts_providers) {
|
||||
Vector<String> view_and_click_counts_providers;
|
||||
view_and_click_counts_providers.reserve(
|
||||
mojom_group->interest_group->view_and_click_counts_providers
|
||||
->size());
|
||||
for (const scoped_refptr<const blink::SecurityOrigin>& origin :
|
||||
*mojom_group->interest_group
|
||||
->view_and_click_counts_providers) {
|
||||
view_and_click_counts_providers.emplace_back(
|
||||
origin->ToString());
|
||||
}
|
||||
group->setViewAndClickCountsProviders(
|
||||
std::move(view_and_click_counts_providers));
|
||||
}
|
||||
|
||||
if (mojom_group->interest_group->user_bidding_signals) {
|
||||
group->setUserBiddingSignals(JsonStringToScriptValue(
|
||||
resolver->GetScriptState(),
|
||||
|
@ -1942,6 +1942,8 @@ TEST_F(SharedStorageWorkletTest, InterestGroups) {
|
||||
ig.max_trusted_bidding_signals_url_length = 100;
|
||||
ig.trusted_bidding_signals_coordinator =
|
||||
url::Origin::Create(GURL("https://example.test"));
|
||||
ig.view_and_click_counts_providers = {
|
||||
{url::Origin::Create(GURL("https://example.test"))}};
|
||||
ig.user_bidding_signals = "\"hello\"";
|
||||
ig.ads = {
|
||||
{blink::InterestGroup::Ad(
|
||||
@ -2193,7 +2195,8 @@ TEST_F(SharedStorageWorkletTest, InterestGroups) {
|
||||
"trustedBiddingSignalsUrl": "https://example.org/trust.json",
|
||||
"updateURL": "https://example.org/ig_update.json",
|
||||
"updateUrl": "https://example.org/ig_update.json",
|
||||
"userBiddingSignals": "hello"
|
||||
"userBiddingSignals": "hello",
|
||||
"viewAndClickCountsProviders": ["https://example.test"]
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -2099,6 +2099,10 @@
|
||||
{
|
||||
name: "FledgeBiddingAndAuctionServerAPIMultiSeller",
|
||||
},
|
||||
{
|
||||
name: "FledgeClickiness",
|
||||
status: "test",
|
||||
},
|
||||
{
|
||||
name: "FledgeCustomMaxAuctionAdComponents",
|
||||
status: "stable",
|
||||
|
@ -380,16 +380,20 @@ _CONFIG = [
|
||||
},
|
||||
{
|
||||
'paths': [
|
||||
'third_party/blink/common/interest_group/interest_group.cc',
|
||||
'third_party/blink/public/common/interest_group/interest_group.h'
|
||||
'third_party/blink/common/interest_group/',
|
||||
'third_party/blink/public/common/interest_group/',
|
||||
],
|
||||
'allowed': [
|
||||
# For hashing of k-anonymity keys
|
||||
'crypto::SHA256HashString',
|
||||
|
||||
# Types used to compute k-anonymity keys.
|
||||
# Types used to compute k-anonymity keys, also many IG fields are
|
||||
# origins and URLs.
|
||||
"url::Origin",
|
||||
"GURL",
|
||||
|
||||
# For checking if origins in interest group are https.
|
||||
"url::kHttpsScheme",
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -27,6 +27,7 @@ chromium-metrics-reviews@google.com.
|
||||
<variant name="BiddingAndAuctionServerKeyProtos"
|
||||
summary="BiddingAndAuctionServerKeyProtos"/>
|
||||
<variant name="KAnonKeyProtos" summary="KAnonKeyProtos"/>
|
||||
<variant name="ListOfOrigins" summary="ListOfOrigins"/>
|
||||
</variants>
|
||||
|
||||
<histogram name="API.EffectiveStorageAccess.AllowedByStorageAccessType"
|
||||
|
Reference in New Issue
Block a user