1 /* 2 * Copyright (C) 2022 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.measurement.registration; 18 19 import android.adservices.measurement.RegistrationRequest; 20 import android.adservices.measurement.SourceRegistrationRequestInternal; 21 import android.adservices.measurement.WebSourceParams; 22 import android.adservices.measurement.WebSourceRegistrationRequest; 23 import android.adservices.measurement.WebTriggerParams; 24 import android.adservices.measurement.WebTriggerRegistrationRequest; 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.content.ContentProviderClient; 28 import android.content.ContentResolver; 29 import android.net.Uri; 30 import android.os.RemoteException; 31 32 import com.android.adservices.LoggerFactory; 33 import com.android.adservices.data.measurement.DatastoreException; 34 import com.android.adservices.data.measurement.DatastoreManager; 35 import com.android.adservices.data.measurement.IMeasurementDao; 36 import com.android.adservices.service.measurement.Source; 37 38 import java.util.Objects; 39 import java.util.UUID; 40 41 /** Class containing static functions for enqueueing AsyncRegistrations */ 42 public class EnqueueAsyncRegistration { 43 44 /** 45 * Inserts an App Source or Trigger Registration request into the Async Registration Queue 46 * table. 47 * 48 * @param registrationRequest a {@link RegistrationRequest} to be queued. 49 */ appSourceOrTriggerRegistrationRequest( RegistrationRequest registrationRequest, boolean adIdPermission, @NonNull Uri registrant, long requestTime, @NonNull Source.SourceType sourceType, @Nullable String postBody, @NonNull DatastoreManager datastoreManager, @NonNull ContentResolver contentResolver)50 public static boolean appSourceOrTriggerRegistrationRequest( 51 RegistrationRequest registrationRequest, 52 boolean adIdPermission, 53 @NonNull Uri registrant, 54 long requestTime, 55 @NonNull Source.SourceType sourceType, 56 @Nullable String postBody, 57 @NonNull DatastoreManager datastoreManager, 58 @NonNull ContentResolver contentResolver) { 59 Objects.requireNonNull(contentResolver); 60 Objects.requireNonNull(datastoreManager); 61 return datastoreManager.runInTransaction( 62 (dao) -> { 63 if (hasValidScheme(registrationRequest.getRegistrationUri())) { 64 insertAsyncRegistration( 65 UUID.randomUUID().toString(), 66 registrationRequest.getRegistrationUri(), 67 /* mWebDestination */ null, 68 /* mOsDestination */ null, 69 registrant, 70 /* verifiedDestination */ null, 71 registrant, 72 registrationRequest.getRegistrationType() 73 == RegistrationRequest.REGISTER_SOURCE 74 ? AsyncRegistration.RegistrationType.APP_SOURCE 75 : AsyncRegistration.RegistrationType.APP_TRIGGER, 76 sourceType, 77 requestTime, 78 false, 79 adIdPermission, 80 registrationRequest.getAdIdValue(), 81 postBody, 82 UUID.randomUUID().toString(), 83 dao, 84 contentResolver); 85 } 86 }); 87 } 88 89 /** 90 * Inserts a Web Source Registration request into the Async Registration Queue table. 91 * 92 * @param webSourceRegistrationRequest a {@link WebSourceRegistrationRequest} to be queued. 93 */ 94 public static boolean webSourceRegistrationRequest( 95 WebSourceRegistrationRequest webSourceRegistrationRequest, 96 boolean adIdPermission, 97 @NonNull Uri registrant, 98 long requestTime, 99 @Nullable Source.SourceType sourceType, 100 @NonNull DatastoreManager datastoreManager, 101 @NonNull ContentResolver contentResolver) { 102 Objects.requireNonNull(contentResolver); 103 Objects.requireNonNull(datastoreManager); 104 String registrationId = UUID.randomUUID().toString(); 105 return datastoreManager.runInTransaction( 106 (dao) -> { 107 for (WebSourceParams webSourceParams : 108 webSourceRegistrationRequest.getSourceParams()) { 109 if (hasValidScheme(webSourceParams.getRegistrationUri())) { 110 insertAsyncRegistration( 111 UUID.randomUUID().toString(), 112 webSourceParams.getRegistrationUri(), 113 webSourceRegistrationRequest.getWebDestination(), 114 webSourceRegistrationRequest.getAppDestination(), 115 registrant, 116 webSourceRegistrationRequest.getVerifiedDestination(), 117 webSourceRegistrationRequest.getTopOriginUri(), 118 AsyncRegistration.RegistrationType.WEB_SOURCE, 119 sourceType, 120 requestTime, 121 webSourceParams.isDebugKeyAllowed(), 122 adIdPermission, 123 /* adIdValue */ null, // null for web 124 /* postBody */ null, 125 registrationId, 126 dao, 127 contentResolver); 128 } 129 } 130 }); 131 } 132 133 /** 134 * Inserts a Web Trigger Registration request into the Async Registration Queue table. 135 * 136 * @param webTriggerRegistrationRequest a {@link WebTriggerRegistrationRequest} to be queued. 137 */ 138 public static boolean webTriggerRegistrationRequest( 139 WebTriggerRegistrationRequest webTriggerRegistrationRequest, 140 boolean adIdPermission, 141 @NonNull Uri registrant, 142 long requestTime, 143 @NonNull DatastoreManager datastoreManager, 144 @NonNull ContentResolver contentResolver) { 145 Objects.requireNonNull(contentResolver); 146 Objects.requireNonNull(datastoreManager); 147 String registrationId = UUID.randomUUID().toString(); 148 return datastoreManager.runInTransaction( 149 (dao) -> { 150 for (WebTriggerParams webTriggerParams : 151 webTriggerRegistrationRequest.getTriggerParams()) { 152 if (hasValidScheme(webTriggerParams.getRegistrationUri())) { 153 insertAsyncRegistration( 154 UUID.randomUUID().toString(), 155 webTriggerParams.getRegistrationUri(), 156 /* mWebDestination */ null, 157 /* mOsDestination */ null, 158 registrant, 159 /* mVerifiedDestination */ null, 160 webTriggerRegistrationRequest.getDestination(), 161 AsyncRegistration.RegistrationType.WEB_TRIGGER, 162 /* mSourceType */ null, 163 requestTime, 164 webTriggerParams.isDebugKeyAllowed(), 165 adIdPermission, 166 /* adIdValue */ null, // null for web 167 /* postBody */ null, 168 registrationId, 169 dao, 170 contentResolver); 171 } 172 } 173 }); 174 } 175 176 /** 177 * Inserts an App Sources Registration request into the Async Registration Queue table. 178 * 179 * @param requestInternal a {@link RegistrationRequest} to be queued. 180 */ 181 public static boolean appSourcesRegistrationRequest( 182 @NonNull SourceRegistrationRequestInternal requestInternal, 183 boolean adIdPermission, 184 @NonNull Uri registrant, 185 long requestTime, 186 @NonNull Source.SourceType sourceType, 187 @Nullable String postBody, 188 @NonNull DatastoreManager datastoreManager, 189 @NonNull ContentResolver contentResolver) { 190 Objects.requireNonNull(contentResolver); 191 Objects.requireNonNull(datastoreManager); 192 String registrationId = UUID.randomUUID().toString(); 193 return datastoreManager.runInTransaction( 194 (dao) -> { 195 for (Uri registrationUri : 196 requestInternal.getSourceRegistrationRequest().getRegistrationUris()) { 197 if (hasValidScheme(registrationUri)) { 198 insertAsyncRegistration( 199 UUID.randomUUID().toString(), 200 registrationUri, 201 /* mWebDestination */ null, 202 /* mOsDestination */ null, 203 registrant, 204 /* verifiedDestination */ null, 205 registrant, 206 AsyncRegistration.RegistrationType.APP_SOURCES, 207 sourceType, 208 requestTime, 209 false, 210 adIdPermission, 211 requestInternal.getAdIdValue(), 212 postBody, 213 registrationId, 214 dao, 215 contentResolver); 216 } 217 } 218 }); 219 } 220 221 private static void insertAsyncRegistration( 222 String id, 223 Uri registrationUri, 224 Uri webDestination, 225 Uri osDestination, 226 Uri registrant, 227 Uri verifiedDestination, 228 Uri topOrigin, 229 AsyncRegistration.RegistrationType registrationType, 230 Source.SourceType sourceType, 231 long mRequestTime, 232 boolean debugKeyAllowed, 233 boolean adIdPermission, 234 String platformAdIdValue, 235 String postBody, 236 String registrationId, 237 IMeasurementDao dao, 238 ContentResolver contentResolver) 239 throws DatastoreException { 240 AsyncRegistration asyncRegistration = 241 new AsyncRegistration.Builder() 242 .setId(id) 243 .setRegistrationUri(registrationUri) 244 .setWebDestination(webDestination) 245 .setOsDestination(osDestination) 246 .setRegistrant(registrant) 247 .setVerifiedDestination(verifiedDestination) 248 .setTopOrigin(topOrigin) 249 .setType(registrationType) 250 .setSourceType(sourceType) 251 .setRequestTime(mRequestTime) 252 .setRetryCount(0) 253 .setDebugKeyAllowed(debugKeyAllowed) 254 .setAdIdPermission(adIdPermission) 255 .setPlatformAdId(platformAdIdValue) 256 .setPostBody(postBody) 257 .setRegistrationId(registrationId) 258 .setRedirectBehavior(AsyncRedirect.RedirectBehavior.AS_IS) 259 .build(); 260 261 dao.insertAsyncRegistration(asyncRegistration); 262 notifyContentProvider(contentResolver); 263 } 264 265 private static void notifyContentProvider(ContentResolver contentResolver) { 266 try (ContentProviderClient contentProviderClient = 267 contentResolver.acquireContentProviderClient( 268 AsyncRegistrationContentProvider.TRIGGER_URI)) { 269 if (contentProviderClient != null) { 270 contentProviderClient.insert(AsyncRegistrationContentProvider.TRIGGER_URI, null); 271 } 272 } catch (RemoteException e) { 273 LoggerFactory.getMeasurementLogger() 274 .e(e, "AsyncRegistration Content Provider invocation failed."); 275 } 276 } 277 278 private static boolean hasValidScheme(Uri registrationUri) { 279 return registrationUri.getScheme().equalsIgnoreCase("https"); 280 } 281 } 282