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