blob: fc0f163148ccac21e4f42a8897748f730d9982df [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.adselection;
import android.adservices.adselection.AdSelectionConfig;
import android.adservices.adselection.AdWithBid;
import android.adservices.adselection.SignedContextualAds;
import android.adservices.common.AdTechIdentifier;
import android.annotation.NonNull;
import android.net.Uri;
import com.android.adservices.LoggerFactory;
import com.android.adservices.service.common.AdDataValidator;
import com.android.adservices.service.common.AdRenderIdValidator;
import com.android.adservices.service.common.AdTechIdentifierValidator;
import com.android.adservices.service.common.AdTechUriValidator;
import com.android.adservices.service.common.FrequencyCapAdDataValidator;
import com.android.adservices.service.common.Validator;
import com.android.adservices.service.common.ValidatorUtil;
import com.android.internal.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import java.util.Map;
import java.util.Objects;
/** This class runs the validation of the {@link AdSelectionConfig} subfields. */
public class AdSelectionConfigValidator implements Validator<AdSelectionConfig> {
private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger();
private static final String AD_SELECTION_CONFIG_CLASS_NAME = "AdSelectionConfig";
@VisibleForTesting
static final String TRUSTED_SCORING_SIGNALS_URI_TYPE = "Trusted Scoring Signals URI";
@VisibleForTesting static final String DECISION_LOGIC_URI_TYPE = "Decision Logic URI";
@VisibleForTesting
static final String CONTEXTUAL_ADS_DECISION_LOGIC_FIELD_NAME =
"Contextual ads decision logic URI";
@NonNull private final PrebuiltLogicGenerator mPrebuiltLogicGenerator;
@NonNull private final FrequencyCapAdDataValidator mFrequencyCapAdDataValidator;
@NonNull private final AdTechIdentifierValidator mAdTechIdentifierValidator;
// AdRenderId is ignored in contextual ads
@NonNull private final AdRenderIdValidator mAdRenderIdValidator;
public AdSelectionConfigValidator(
@NonNull PrebuiltLogicGenerator prebuiltLogicGenerator,
@NonNull FrequencyCapAdDataValidator frequencyCapAdDataValidator) {
Objects.requireNonNull(prebuiltLogicGenerator);
Objects.requireNonNull(frequencyCapAdDataValidator);
mPrebuiltLogicGenerator = prebuiltLogicGenerator;
mFrequencyCapAdDataValidator = frequencyCapAdDataValidator;
mAdTechIdentifierValidator =
new AdTechIdentifierValidator(
AD_SELECTION_CONFIG_CLASS_NAME, ValidatorUtil.AD_TECH_ROLE_SELLER);
mAdRenderIdValidator = AdRenderIdValidator.AD_RENDER_ID_VALIDATOR_NO_OP;
}
@Override
public void addValidation(
@NonNull AdSelectionConfig adSelectionConfig,
@NonNull ImmutableCollection.Builder<String> violations) {
if (Objects.isNull(adSelectionConfig)) {
violations.add("The AdSelectionConfig should not be null.");
}
String sellerString = adSelectionConfig.getSeller().toString();
mAdTechIdentifierValidator.addValidation(sellerString, violations);
if (mPrebuiltLogicGenerator.isPrebuiltUri(adSelectionConfig.getDecisionLogicUri())) {
sLogger.v("Decision logic URI validation is skipped because prebuilt URI is detected!");
} else {
sLogger.v("Validating decision logic URI");
AdTechUriValidator sellerDecisionLogicUriValidator =
new AdTechUriValidator(
ValidatorUtil.AD_TECH_ROLE_SELLER,
sellerString,
AD_SELECTION_CONFIG_CLASS_NAME,
DECISION_LOGIC_URI_TYPE);
sellerDecisionLogicUriValidator.addValidation(
adSelectionConfig.getDecisionLogicUri(), violations);
}
if (!adSelectionConfig.getTrustedScoringSignalsUri().equals(Uri.EMPTY)) {
AdTechUriValidator trustedScoringSignalsUriValidator =
new AdTechUriValidator(
ValidatorUtil.AD_TECH_ROLE_SELLER,
sellerString,
AD_SELECTION_CONFIG_CLASS_NAME,
TRUSTED_SCORING_SIGNALS_URI_TYPE);
trustedScoringSignalsUriValidator.addValidation(
adSelectionConfig.getTrustedScoringSignalsUri(), violations);
}
violations.addAll(
validateSignedContextualAds(adSelectionConfig.getBuyerSignedContextualAds()));
}
private ImmutableList<String> validateSignedContextualAds(
Map<AdTechIdentifier, SignedContextualAds> signedContextualAdsMap) {
ImmutableList.Builder<String> violations = new ImmutableList.Builder<>();
for (Map.Entry<AdTechIdentifier, SignedContextualAds> entry :
signedContextualAdsMap.entrySet()) {
// Validate that the buyer decision logic for Contextual Ads satisfies buyer eTLD+1
AdTechUriValidator buyerUriValidator =
new AdTechUriValidator(
ValidatorUtil.AD_TECH_ROLE_BUYER,
entry.getValue().getBuyer().toString(),
SignedContextualAds.class.getName(),
CONTEXTUAL_ADS_DECISION_LOGIC_FIELD_NAME);
buyerUriValidator.addValidation(entry.getValue().getDecisionLogicUri(), violations);
// Validate that the ad render URI for Contextual Ads satisfies buyer eTLD+1
AdDataValidator adDataValidator =
new AdDataValidator(
ValidatorUtil.AD_TECH_ROLE_BUYER,
entry.getValue().getBuyer().toString(),
mFrequencyCapAdDataValidator,
mAdRenderIdValidator);
for (AdWithBid ad : entry.getValue().getAdsWithBid()) {
adDataValidator.addValidation(ad.getAdData(), violations);
}
}
return violations.build();
}
}