1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.adservices.service.customaudience; 18 19 import static com.android.adservices.service.customaudience.CustomAudienceBlob.AUCTION_SERVER_REQUEST_FLAGS_KEY; 20 import static com.android.adservices.service.customaudience.CustomAudienceBlob.BUYER_KEY; 21 import static com.android.adservices.service.customaudience.CustomAudienceBlob.OWNER_KEY; 22 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.ADS_KEY; 23 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.AD_COUNTERS_KEY; 24 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.AD_FILTERS_KEY; 25 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.AD_RENDER_ID_KEY; 26 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.METADATA_KEY; 27 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.RENDER_URI_KEY; 28 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.TRUSTED_BIDDING_DATA_KEY; 29 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.TRUSTED_BIDDING_KEYS_KEY; 30 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.TRUSTED_BIDDING_URI_KEY; 31 import static com.android.adservices.service.customaudience.CustomAudienceUpdatableDataReader.USER_BIDDING_SIGNALS_KEY; 32 import static com.android.adservices.service.customaudience.FetchCustomAudienceReader.ACTIVATION_TIME_KEY; 33 import static com.android.adservices.service.customaudience.FetchCustomAudienceReader.BIDDING_LOGIC_URI_KEY; 34 import static com.android.adservices.service.customaudience.FetchCustomAudienceReader.DAILY_UPDATE_URI_KEY; 35 import static com.android.adservices.service.customaudience.FetchCustomAudienceReader.EXPIRATION_TIME_KEY; 36 import static com.android.adservices.service.customaudience.FetchCustomAudienceReader.NAME_KEY; 37 38 import android.adservices.common.AdTechIdentifier; 39 import android.net.Uri; 40 41 import com.android.adservices.LoggerFactory; 42 import com.android.adservices.common.JsonFixture; 43 import com.android.adservices.data.common.DBAdData; 44 import com.android.adservices.data.customaudience.DBTrustedBiddingData; 45 46 import org.json.JSONArray; 47 import org.json.JSONException; 48 import org.json.JSONObject; 49 50 import java.time.Instant; 51 import java.util.List; 52 53 public class CustomAudienceBlobFixture { 54 private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger(); 55 56 /** Converts the input to a valid JSON object and returns it as a serialized string. */ asJSONObjectString( String owner, AdTechIdentifier buyer, String name, Instant activationTime, Instant expirationTime, Uri dailyUpdateUri, Uri biddingLogicUri, String userBiddingSignals, DBTrustedBiddingData trustedBiddingData, List<DBAdData> ads)57 public static String asJSONObjectString( 58 String owner, 59 AdTechIdentifier buyer, 60 String name, 61 Instant activationTime, 62 Instant expirationTime, 63 Uri dailyUpdateUri, 64 Uri biddingLogicUri, 65 String userBiddingSignals, 66 DBTrustedBiddingData trustedBiddingData, 67 List<DBAdData> ads) 68 throws JSONException { 69 return asJSONObject( 70 owner, 71 buyer, 72 name, 73 activationTime, 74 expirationTime, 75 dailyUpdateUri, 76 biddingLogicUri, 77 userBiddingSignals, 78 trustedBiddingData, 79 ads, 80 false) 81 .toString(); 82 } 83 84 /** 85 * Converts the inputs to a valid JSON object and returns it as a serialized string. 86 * 87 * <p>Optionally adds harmless junk to the response by adding unexpected fields. 88 */ asJSONObject( String owner, AdTechIdentifier buyer, String name, Instant activationTime, Instant expirationTime, Uri dailyUpdateUri, Uri biddingLogicUri, String userBiddingSignals, DBTrustedBiddingData trustedBiddingData, List<DBAdData> ads, boolean shouldAddHarmlessJunk)89 public static JSONObject asJSONObject( 90 String owner, 91 AdTechIdentifier buyer, 92 String name, 93 Instant activationTime, 94 Instant expirationTime, 95 Uri dailyUpdateUri, 96 Uri biddingLogicUri, 97 String userBiddingSignals, 98 DBTrustedBiddingData trustedBiddingData, 99 List<DBAdData> ads, 100 boolean shouldAddHarmlessJunk) 101 throws JSONException { 102 JSONObject json = new JSONObject(); 103 104 json = addOwner(json, owner, shouldAddHarmlessJunk); 105 json = addBuyer(json, buyer, shouldAddHarmlessJunk); 106 json = addName(json, name, shouldAddHarmlessJunk); 107 json = addActivationTime(json, activationTime, shouldAddHarmlessJunk); 108 json = addExpirationTime(json, expirationTime, shouldAddHarmlessJunk); 109 json = addDailyUpdateUri(json, dailyUpdateUri, shouldAddHarmlessJunk); 110 json = addBiddingLogicUri(json, biddingLogicUri, shouldAddHarmlessJunk); 111 json = addUserBiddingSignals(json, userBiddingSignals, shouldAddHarmlessJunk); 112 json = addTrustedBiddingData(json, trustedBiddingData, shouldAddHarmlessJunk); 113 json = addAds(json, ads, shouldAddHarmlessJunk); 114 115 return json; 116 } 117 118 /** 119 * Converts a string representation of a JSON object into a JSONObject with a keyed field for 120 * owner. 121 * 122 * <p>Optionally adds harmless junk to the object by adding unexpected fields. 123 */ addOwner(JSONObject json, String owner, boolean shouldAddHarmlessJunk)124 public static JSONObject addOwner(JSONObject json, String owner, boolean shouldAddHarmlessJunk) 125 throws JSONException { 126 if (owner != null) { 127 return addToJSONObject(json, OWNER_KEY, owner, shouldAddHarmlessJunk); 128 } 129 return json; 130 } 131 132 /** 133 * Converts a string representation of a JSON object into a JSONObject with a keyed field for 134 * buyer. 135 * 136 * <p>Optionally adds harmless junk to the object by adding unexpected fields. 137 */ addBuyer( JSONObject json, AdTechIdentifier adTechIdentifier, boolean shouldAddHarmlessJunk)138 public static JSONObject addBuyer( 139 JSONObject json, AdTechIdentifier adTechIdentifier, boolean shouldAddHarmlessJunk) 140 throws JSONException { 141 if (adTechIdentifier != null) { 142 return addToJSONObject( 143 json, BUYER_KEY, adTechIdentifier.toString(), shouldAddHarmlessJunk); 144 } 145 return json; 146 } 147 148 /** 149 * Converts a string representation of a JSON object into a JSONObject with a keyed field for 150 * name. 151 * 152 * <p>Optionally adds harmless junk to the object by adding unexpected fields. 153 */ addName(JSONObject json, String name, boolean shouldAddHarmlessJunk)154 public static JSONObject addName(JSONObject json, String name, boolean shouldAddHarmlessJunk) 155 throws JSONException { 156 if (name != null) { 157 return addToJSONObject(json, NAME_KEY, name, shouldAddHarmlessJunk); 158 } 159 return json; 160 } 161 162 /** 163 * Converts a string representation of a JSON object into a JSONObject with a keyed field for 164 * activation time. 165 * 166 * <p>Optionally adds harmless junk to the object by adding unexpected fields. 167 */ addActivationTime( JSONObject json, Instant activationTime, boolean shouldAddHarmlessJunk)168 public static JSONObject addActivationTime( 169 JSONObject json, Instant activationTime, boolean shouldAddHarmlessJunk) 170 throws JSONException { 171 if (activationTime != null) { 172 return addToJSONObject( 173 json, 174 ACTIVATION_TIME_KEY, 175 activationTime.toEpochMilli(), 176 shouldAddHarmlessJunk); 177 } 178 return json; 179 } 180 181 /** 182 * Converts a string representation of a JSON object into a JSONObject with a keyed field for 183 * expiration time. 184 * 185 * <p>Optionally adds harmless junk to the object by adding unexpected fields. 186 */ addExpirationTime( JSONObject json, Instant expirationTime, boolean shouldAddHarmlessJunk)187 public static JSONObject addExpirationTime( 188 JSONObject json, Instant expirationTime, boolean shouldAddHarmlessJunk) 189 throws JSONException { 190 if (expirationTime != null) { 191 return addToJSONObject( 192 json, 193 EXPIRATION_TIME_KEY, 194 expirationTime.toEpochMilli(), 195 shouldAddHarmlessJunk); 196 } 197 return json; 198 } 199 200 /** 201 * Converts a string representation of a JSON object into a JSONObject with a keyed field for 202 * daily update uri. 203 * 204 * <p>Optionally adds harmless junk to the object by adding unexpected fields. 205 */ addDailyUpdateUri( JSONObject json, Uri dailyUpdateUri, boolean shouldAddHarmlessJunk)206 public static JSONObject addDailyUpdateUri( 207 JSONObject json, Uri dailyUpdateUri, boolean shouldAddHarmlessJunk) 208 throws JSONException { 209 if (dailyUpdateUri != null) { 210 return addToJSONObject( 211 json, DAILY_UPDATE_URI_KEY, dailyUpdateUri.toString(), shouldAddHarmlessJunk); 212 } 213 return json; 214 } 215 216 /** 217 * Converts a string representation of a JSON object into a JSONObject with a keyed field for 218 * bidding logic uri. 219 * 220 * <p>Optionally adds harmless junk to the object by adding unexpected fields. 221 */ addBiddingLogicUri( JSONObject json, Uri biddingLogicUri, boolean shouldAddHarmlessJunk)222 public static JSONObject addBiddingLogicUri( 223 JSONObject json, Uri biddingLogicUri, boolean shouldAddHarmlessJunk) 224 throws JSONException { 225 if (biddingLogicUri != null) { 226 return addToJSONObject( 227 json, BIDDING_LOGIC_URI_KEY, biddingLogicUri.toString(), shouldAddHarmlessJunk); 228 } 229 return json; 230 } 231 232 /** 233 * Converts a string representation of a JSON object into a JSONObject with a keyed field for 234 * user bidding signals. 235 * 236 * <p>Optionally adds harmless junk to the object by adding unexpected fields. 237 */ addUserBiddingSignals( JSONObject json, String userBiddingSignals, boolean shouldAddHarmlessJunk)238 public static JSONObject addUserBiddingSignals( 239 JSONObject json, String userBiddingSignals, boolean shouldAddHarmlessJunk) 240 throws JSONException { 241 if (userBiddingSignals != null) { 242 JSONObject userBiddingSignalsJson = new JSONObject(userBiddingSignals); 243 return addToJSONObject( 244 json, USER_BIDDING_SIGNALS_KEY, userBiddingSignalsJson, shouldAddHarmlessJunk); 245 } 246 return json; 247 } 248 249 /** 250 * Converts {@link DBTrustedBiddingData} into a JSONObject with a keyed field for trusted 251 * bidding data. 252 * 253 * <p>Optionally adds harmless junk to the object by adding unexpected fields. 254 */ addTrustedBiddingData( JSONObject json, DBTrustedBiddingData trustedBiddingData, boolean shouldAddHarmlessJunk)255 public static JSONObject addTrustedBiddingData( 256 JSONObject json, DBTrustedBiddingData trustedBiddingData, boolean shouldAddHarmlessJunk) 257 throws JSONException { 258 if (trustedBiddingData != null) { 259 JSONObject trustedBiddingDataJson = new JSONObject(); 260 261 if (shouldAddHarmlessJunk) { 262 JsonFixture.addHarmlessJunkValues(trustedBiddingDataJson); 263 } 264 265 trustedBiddingDataJson.put( 266 TRUSTED_BIDDING_URI_KEY, trustedBiddingData.getUri().toString()); 267 JSONArray trustedBiddingKeysJson = new JSONArray(trustedBiddingData.getKeys()); 268 if (shouldAddHarmlessJunk) { 269 JsonFixture.addHarmlessJunkValues(trustedBiddingKeysJson); 270 } 271 trustedBiddingDataJson.put(TRUSTED_BIDDING_KEYS_KEY, trustedBiddingKeysJson); 272 273 return addToJSONObject(json, TRUSTED_BIDDING_DATA_KEY, trustedBiddingDataJson, false); 274 } 275 276 return json; 277 } 278 279 /** 280 * Converts a list of {@link DBAdData} into a JSONObject with a keyed field for ads. 281 * 282 * <p>Optionally adds harmless junk to the object by adding unexpected fields. 283 */ addAds( JSONObject json, List<DBAdData> ads, boolean shouldAddHarmlessJunk)284 public static JSONObject addAds( 285 JSONObject json, List<DBAdData> ads, boolean shouldAddHarmlessJunk) 286 throws JSONException { 287 if (ads != null) { 288 JSONArray adsJson = new JSONArray(); 289 290 if (shouldAddHarmlessJunk) { 291 JsonFixture.addHarmlessJunkValues(adsJson); 292 } 293 294 for (DBAdData ad : ads) { 295 JSONObject adJson = new JSONObject(); 296 if (shouldAddHarmlessJunk) { 297 JsonFixture.addHarmlessJunkValues(adJson); 298 } 299 300 adJson.put(RENDER_URI_KEY, ad.getRenderUri().toString()); 301 try { 302 adJson.put(METADATA_KEY, new JSONObject(ad.getMetadata())); 303 } catch (JSONException exception) { 304 sLogger.v( 305 "Trying to add invalid JSON to test object (%s); inserting as String" 306 + " instead", 307 exception.getMessage()); 308 adJson.put(METADATA_KEY, ad.getMetadata()); 309 } 310 if (!ad.getAdCounterKeys().isEmpty()) { 311 adJson.put(AD_COUNTERS_KEY, new JSONArray(ad.getAdCounterKeys())); 312 } 313 if (ad.getAdFilters() != null) { 314 adJson.put(AD_FILTERS_KEY, ad.getAdFilters().toJson()); 315 } 316 if (ad.getAdRenderId() != null) { 317 adJson.put(AD_RENDER_ID_KEY, ad.getAdRenderId()); 318 } 319 adsJson.put(adJson); 320 } 321 322 return addToJSONObject(json, ADS_KEY, adsJson, false); 323 } 324 325 return json; 326 } 327 328 /** 329 * Converts a list of {@link String} into a JSONObject with a keyed field for auction server 330 * request flags. 331 * 332 * <p>Optionally adds harmless junk to the object by adding unexpected fields. 333 */ addAuctionServerRequestFlags( JSONObject json, List<String> auctionServerRequestFlags, boolean shouldAddHarmlessJunk)334 public static JSONObject addAuctionServerRequestFlags( 335 JSONObject json, List<String> auctionServerRequestFlags, boolean shouldAddHarmlessJunk) 336 throws JSONException { 337 if (auctionServerRequestFlags != null) { 338 JSONArray auctionServerRequestFlagsArray = new JSONArray(); 339 for (String s : auctionServerRequestFlags) { 340 auctionServerRequestFlagsArray.put(s); 341 } 342 if (shouldAddHarmlessJunk) { 343 JsonFixture.addHarmlessJunkValues(auctionServerRequestFlagsArray); 344 } 345 return addToJSONObject( 346 json, AUCTION_SERVER_REQUEST_FLAGS_KEY, auctionServerRequestFlagsArray, false); 347 } 348 return json; 349 } 350 addToJSONObject( JSONObject json, String key, Object value, boolean shouldAddHarmlessJunk)351 private static JSONObject addToJSONObject( 352 JSONObject json, String key, Object value, boolean shouldAddHarmlessJunk) 353 throws JSONException { 354 if (json == null) { 355 json = new JSONObject(); 356 } 357 358 if (shouldAddHarmlessJunk) { 359 JsonFixture.addHarmlessJunkValues(json); 360 } 361 362 json.put(key, value); 363 return json; 364 } 365 } 366