blob: 4d921233f073525a1f4b3aa6baa26a0e8f6069aa [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.adservices.service.customaudience;
import android.adservices.common.AdData;
import android.adservices.customaudience.CustomAudience;
import android.annotation.NonNull;
import android.content.Context;
import com.android.adservices.service.Flags;
import com.android.adservices.service.FlagsFactory;
import com.android.adservices.service.common.AdDataValidator;
import com.android.adservices.service.common.AdTechIdentifierValidator;
import com.android.adservices.service.common.AdTechUriValidator;
import com.android.adservices.service.common.JsonValidator;
import com.android.adservices.service.common.Validator;
import com.android.adservices.service.common.ValidatorUtil;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableCollection;
import java.time.Clock;
import java.util.Objects;
/** Validator for Custom Audience. */
public class CustomAudienceValidator implements Validator<CustomAudience> {
@VisibleForTesting
static final String CUSTOM_AUDIENCE_CLASS_NAME = CustomAudience.class.getName();
@VisibleForTesting static final String DAILY_UPDATE_URI_FIELD_NAME = "daily update uri";
@VisibleForTesting static final String BIDDING_LOGIC_URI_FIELD_NAME = "bidding logic uri";
@VisibleForTesting static final String USER_BIDDING_SIGNALS_FIELD_NAME = "user bidding signals";
private static final Object SINGLETON_LOCK = new Object();
@GuardedBy("SINGLETON_LOCK")
private static CustomAudienceValidator sSingleton;
@NonNull private final CustomAudienceTimestampValidator mCustomAudienceTimestampValidator;
@NonNull private final AdTechIdentifierValidator mBuyerValidator;
@NonNull private final JsonValidator mUserBiddingSignalsValidator;
@VisibleForTesting
public CustomAudienceValidator(
@NonNull CustomAudienceTimestampValidator customAudienceTimestampValidator,
@NonNull AdTechIdentifierValidator buyerValidator,
@NonNull JsonValidator userBiddingSignalsValidator) {
Objects.requireNonNull(customAudienceTimestampValidator);
Objects.requireNonNull(buyerValidator);
Objects.requireNonNull(userBiddingSignalsValidator);
mCustomAudienceTimestampValidator = customAudienceTimestampValidator;
mBuyerValidator = buyerValidator;
mUserBiddingSignalsValidator = userBiddingSignalsValidator;
}
@VisibleForTesting
public CustomAudienceValidator(@NonNull Clock clock, @NonNull Flags flags) {
this(
new CustomAudienceTimestampValidator(clock, flags),
new AdTechIdentifierValidator(
CUSTOM_AUDIENCE_CLASS_NAME, ValidatorUtil.AD_TECH_ROLE_BUYER),
new JsonValidator(CUSTOM_AUDIENCE_CLASS_NAME, USER_BIDDING_SIGNALS_FIELD_NAME));
}
/**
* Gets an instance of {@link CustomAudienceValidator} to be used.
*
* <p>If no instance has been initialized yet, a new one will be created. Otherwise, the
* existing instance will be returned.
*/
@NonNull
public static CustomAudienceValidator getInstance(@NonNull Context context) {
Objects.requireNonNull(context, "Context must be provided.");
synchronized (SINGLETON_LOCK) {
if (sSingleton == null) {
Flags flags = FlagsFactory.getFlags();
sSingleton = new CustomAudienceValidator(Clock.systemUTC(), flags);
}
return sSingleton;
}
}
/**
* Validates the custom audience.
*
* @param customAudience the instance to be validated.
*/
@Override
public void addValidation(
@NonNull CustomAudience customAudience,
@NonNull ImmutableCollection.Builder<String> violations) {
Objects.requireNonNull(customAudience);
Objects.requireNonNull(violations);
validateFieldFormat(customAudience, violations);
mCustomAudienceTimestampValidator.addValidation(customAudience, violations);
}
private void validateFieldFormat(
CustomAudience customAudience, ImmutableCollection.Builder<String> violations) {
String buyer = customAudience.getBuyer();
mBuyerValidator.addValidation(buyer, violations);
new AdTechUriValidator(
ValidatorUtil.AD_TECH_ROLE_BUYER,
buyer,
CUSTOM_AUDIENCE_CLASS_NAME,
DAILY_UPDATE_URI_FIELD_NAME)
.addValidation(customAudience.getDailyUpdateUrl(), violations);
new AdTechUriValidator(
ValidatorUtil.AD_TECH_ROLE_BUYER,
buyer,
CUSTOM_AUDIENCE_CLASS_NAME,
BIDDING_LOGIC_URI_FIELD_NAME)
.addValidation(customAudience.getBiddingLogicUrl(), violations);
if (customAudience.getUserBiddingSignals() != null) {
mUserBiddingSignalsValidator.addValidation(
customAudience.getUserBiddingSignals(), violations);
}
if (customAudience.getTrustedBiddingData() != null) {
new TrustedBiddingDataValidator(buyer)
.addValidation(customAudience.getTrustedBiddingData(), violations);
}
AdDataValidator adDataValidator =
new AdDataValidator(ValidatorUtil.AD_TECH_ROLE_BUYER, buyer);
for (AdData adData : customAudience.getAds()) {
adDataValidator.addValidation(adData, violations);
}
}
}