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.tests.permissions; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertThrows; 22 23 import android.adservices.adselection.AdSelectionConfig; 24 import android.adservices.adselection.AdSelectionConfigFixture; 25 import android.adservices.adselection.AddAdSelectionOverrideRequest; 26 import android.adservices.adselection.RemoveAdSelectionOverrideRequest; 27 import android.adservices.adselection.ReportImpressionRequest; 28 import android.adservices.clients.adselection.AdSelectionClient; 29 import android.adservices.clients.adselection.TestAdSelectionClient; 30 import android.adservices.clients.customaudience.AdvertisingCustomAudienceClient; 31 import android.adservices.clients.customaudience.TestAdvertisingCustomAudienceClient; 32 import android.adservices.clients.topics.AdvertisingTopicsClient; 33 import android.adservices.common.AdSelectionSignals; 34 import android.adservices.common.AdTechIdentifier; 35 import android.adservices.customaudience.AddCustomAudienceOverrideRequest; 36 import android.adservices.customaudience.CustomAudience; 37 import android.adservices.customaudience.RemoveCustomAudienceOverrideRequest; 38 import android.content.Context; 39 import android.net.Uri; 40 41 import androidx.test.core.app.ApplicationProvider; 42 import androidx.test.ext.junit.runners.AndroidJUnit4; 43 44 import com.android.adservices.common.CompatAdServicesTestUtils; 45 import com.android.compatibility.common.util.ShellUtils; 46 import com.android.modules.utils.build.SdkLevel; 47 48 import org.junit.After; 49 import org.junit.Before; 50 import org.junit.Test; 51 import org.junit.runner.RunWith; 52 53 import java.util.concurrent.ExecutionException; 54 import java.util.concurrent.Executor; 55 import java.util.concurrent.Executors; 56 57 /** In the manifest file, no API permissions are declared for this test. */ 58 @RunWith(AndroidJUnit4.class) 59 // TODO: Add tests for measurement (b/238194122). 60 public class PermissionsNoPermTest { 61 private static final Executor CALLBACK_EXECUTOR = Executors.newCachedThreadPool(); 62 private static final Context sContext = ApplicationProvider.getApplicationContext(); 63 private static final String CALLER_NOT_AUTHORIZED = 64 "java.lang.SecurityException: Caller is not authorized to call this API. " 65 + "Permission was not requested."; 66 67 private String mPreviousAppAllowList; 68 69 @Before setup()70 public void setup() { 71 if (!SdkLevel.isAtLeastT()) { 72 overridePpapiAppAllowList(); 73 CompatAdServicesTestUtils.setFlags(); 74 } 75 } 76 77 @After tearDown()78 public void tearDown() throws Exception { 79 if (!SdkLevel.isAtLeastT()) { 80 setPpapiAppAllowList(mPreviousAppAllowList); 81 CompatAdServicesTestUtils.resetFlagsToDefault(); 82 } 83 } 84 setPpapiAppAllowList(String allowList)85 private void setPpapiAppAllowList(String allowList) { 86 ShellUtils.runShellCommand( 87 "device_config put adservices ppapi_app_allow_list " + allowList); 88 } 89 overridePpapiAppAllowList()90 private void overridePpapiAppAllowList() { 91 mPreviousAppAllowList = 92 ShellUtils.runShellCommand("device_config get adservices ppapi_app_allow_list"); 93 setPpapiAppAllowList(mPreviousAppAllowList + "," + sContext.getPackageName()); 94 } 95 96 @Test testNoPerm_topics()97 public void testNoPerm_topics() { 98 AdvertisingTopicsClient advertisingTopicsClient1 = 99 new AdvertisingTopicsClient.Builder() 100 .setContext(sContext) 101 .setSdkName("sdk1") 102 .setExecutor(CALLBACK_EXECUTOR) 103 .build(); 104 105 ExecutionException exception = 106 assertThrows( 107 ExecutionException.class, () -> advertisingTopicsClient1.getTopics().get()); 108 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 109 } 110 111 @Test testPermissionNotRequested_fledgeJoinCustomAudience()112 public void testPermissionNotRequested_fledgeJoinCustomAudience() { 113 AdvertisingCustomAudienceClient customAudienceClient = 114 new AdvertisingCustomAudienceClient.Builder() 115 .setContext(sContext) 116 .setExecutor(CALLBACK_EXECUTOR) 117 .build(); 118 119 CustomAudience customAudience = 120 new CustomAudience.Builder() 121 .setBuyer(AdTechIdentifier.fromString("buyer.example.com")) 122 .setName("exampleCustomAudience") 123 .setDailyUpdateUri(Uri.parse("https://buyer.example.com/daily-update")) 124 .setBiddingLogicUri(Uri.parse("https://buyer.example.com/bidding-logic")) 125 .build(); 126 127 ExecutionException exception = 128 assertThrows( 129 ExecutionException.class, 130 () -> customAudienceClient.joinCustomAudience(customAudience).get()); 131 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 132 } 133 134 @Test testPermissionNotRequested_fledgeLeaveCustomAudience()135 public void testPermissionNotRequested_fledgeLeaveCustomAudience() { 136 AdvertisingCustomAudienceClient customAudienceClient = 137 new AdvertisingCustomAudienceClient.Builder() 138 .setContext(sContext) 139 .setExecutor(CALLBACK_EXECUTOR) 140 .build(); 141 142 ExecutionException exception = 143 assertThrows( 144 ExecutionException.class, 145 () -> 146 customAudienceClient 147 .leaveCustomAudience( 148 AdTechIdentifier.fromString("buyer.example.com"), 149 "exampleCustomAudience") 150 .get()); 151 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 152 } 153 154 @Test testPermissionNotRequested_fledgeOverrideCustomAudienceRemoteInfo()155 public void testPermissionNotRequested_fledgeOverrideCustomAudienceRemoteInfo() { 156 TestAdvertisingCustomAudienceClient testCustomAudienceClient = 157 new TestAdvertisingCustomAudienceClient.Builder() 158 .setContext(sContext) 159 .setExecutor(CALLBACK_EXECUTOR) 160 .build(); 161 162 AddCustomAudienceOverrideRequest request = 163 new AddCustomAudienceOverrideRequest.Builder() 164 .setBuyer(AdTechIdentifier.fromString("buyer.example.com")) 165 .setName("exampleCustomAudience") 166 .setBiddingLogicJs("function test() { return \"hello, world!\"; }") 167 .setTrustedBiddingSignals(AdSelectionSignals.fromString("{\"test\":1}")) 168 .build(); 169 170 ExecutionException exception = 171 assertThrows( 172 ExecutionException.class, 173 () -> 174 testCustomAudienceClient 175 .overrideCustomAudienceRemoteInfo(request) 176 .get()); 177 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 178 } 179 180 @Test testPermissionNotRequested_fledgeRemoveCustomAudienceRemoteInfoOverride()181 public void testPermissionNotRequested_fledgeRemoveCustomAudienceRemoteInfoOverride() { 182 TestAdvertisingCustomAudienceClient testCustomAudienceClient = 183 new TestAdvertisingCustomAudienceClient.Builder() 184 .setContext(sContext) 185 .setExecutor(CALLBACK_EXECUTOR) 186 .build(); 187 188 RemoveCustomAudienceOverrideRequest request = 189 new RemoveCustomAudienceOverrideRequest.Builder() 190 .setBuyer(AdTechIdentifier.fromString("buyer.example.com")) 191 .setName("exampleCustomAudience") 192 .build(); 193 194 ExecutionException exception = 195 assertThrows( 196 ExecutionException.class, 197 () -> 198 testCustomAudienceClient 199 .removeCustomAudienceRemoteInfoOverride(request) 200 .get()); 201 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 202 } 203 204 @Test testPermissionNotRequested_fledgeResetAllCustomAudienceOverrides()205 public void testPermissionNotRequested_fledgeResetAllCustomAudienceOverrides() { 206 TestAdvertisingCustomAudienceClient testCustomAudienceClient = 207 new TestAdvertisingCustomAudienceClient.Builder() 208 .setContext(sContext) 209 .setExecutor(CALLBACK_EXECUTOR) 210 .build(); 211 212 ExecutionException exception = 213 assertThrows( 214 ExecutionException.class, 215 () -> testCustomAudienceClient.resetAllCustomAudienceOverrides().get()); 216 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 217 } 218 219 @Test testPermissionNotRequested_selectAds_adSelectionConfig()220 public void testPermissionNotRequested_selectAds_adSelectionConfig() { 221 AdSelectionConfig adSelectionConfig = AdSelectionConfigFixture.anAdSelectionConfig(); 222 223 AdSelectionClient mAdSelectionClient = 224 new AdSelectionClient.Builder() 225 .setContext(sContext) 226 .setExecutor(CALLBACK_EXECUTOR) 227 .build(); 228 229 ExecutionException exception = 230 assertThrows( 231 ExecutionException.class, 232 () -> mAdSelectionClient.selectAds(adSelectionConfig).get()); 233 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 234 } 235 236 @Test testPermissionNotRequested_reportImpression()237 public void testPermissionNotRequested_reportImpression() { 238 AdSelectionConfig adSelectionConfig = AdSelectionConfigFixture.anAdSelectionConfig(); 239 240 long adSelectionId = 1; 241 242 AdSelectionClient mAdSelectionClient = 243 new AdSelectionClient.Builder() 244 .setContext(sContext) 245 .setExecutor(CALLBACK_EXECUTOR) 246 .build(); 247 248 ReportImpressionRequest request = 249 new ReportImpressionRequest(adSelectionId, adSelectionConfig); 250 251 ExecutionException exception = 252 assertThrows( 253 ExecutionException.class, 254 () -> mAdSelectionClient.reportImpression(request).get()); 255 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 256 } 257 258 // TODO(b/274723533): Uncomment after un-hiding the API 259 /* 260 @Test 261 public void testPermissionNotRequested_reportInteraction() { 262 long adSelectionId = 1; 263 String interactionKey = "click"; 264 String interactionData = "{\"key\":\"value\"}"; 265 266 AdSelectionClient mAdSelectionClient = 267 new AdSelectionClient.Builder() 268 .setContext(sContext) 269 .setExecutor(CALLBACK_EXECUTOR) 270 .build(); 271 272 ReportInteractionRequest request = 273 new ReportInteractionRequest( 274 adSelectionId, 275 interactionKey, 276 interactionData, 277 ReportInteractionRequest.FLAG_REPORTING_DESTINATION_BUYER 278 | ReportInteractionRequest.FLAG_REPORTING_DESTINATION_SELLER); 279 280 ExecutionException exception = 281 assertThrows( 282 ExecutionException.class, 283 () -> mAdSelectionClient.reportInteraction(request).get()); 284 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 285 } 286 */ 287 288 @Test testPermissionNotRequested_fledgeOverrideAdSelectionConfigRemoteInfo()289 public void testPermissionNotRequested_fledgeOverrideAdSelectionConfigRemoteInfo() { 290 TestAdSelectionClient testAdSelectionClient = 291 new TestAdSelectionClient.Builder() 292 .setContext(sContext) 293 .setExecutor(CALLBACK_EXECUTOR) 294 .build(); 295 296 String decisionLogicJs = "function test() { return \"hello world\"; }"; 297 AdSelectionSignals trustedScoringSignals = 298 AdSelectionSignals.fromString( 299 "{\n" 300 + "\t\"render_uri_1\": \"signals_for_1\",\n" 301 + "\t\"render_uri_2\": \"signals_for_2\"\n" 302 + "}"); 303 304 AdSelectionConfig adSelectionConfig = AdSelectionConfigFixture.anAdSelectionConfig(); 305 306 AddAdSelectionOverrideRequest request = 307 new AddAdSelectionOverrideRequest( 308 adSelectionConfig, decisionLogicJs, trustedScoringSignals); 309 310 Exception exception = 311 assertThrows( 312 ExecutionException.class, 313 () -> { 314 testAdSelectionClient 315 .overrideAdSelectionConfigRemoteInfo(request) 316 .get(); 317 }); 318 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 319 } 320 321 @Test testPermissionNotRequested_fledgeRemoveAdSelectionConfigRemoteInfo()322 public void testPermissionNotRequested_fledgeRemoveAdSelectionConfigRemoteInfo() { 323 TestAdSelectionClient testAdSelectionClient = 324 new TestAdSelectionClient.Builder() 325 .setContext(sContext) 326 .setExecutor(CALLBACK_EXECUTOR) 327 .build(); 328 329 AdSelectionConfig adSelectionConfig = AdSelectionConfigFixture.anAdSelectionConfig(); 330 331 RemoveAdSelectionOverrideRequest request = 332 new RemoveAdSelectionOverrideRequest(adSelectionConfig); 333 334 Exception exception = 335 assertThrows( 336 ExecutionException.class, 337 () -> { 338 testAdSelectionClient 339 .removeAdSelectionConfigRemoteInfoOverride(request) 340 .get(); 341 }); 342 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 343 } 344 345 @Test testPermissionNotRequested_fledgeResetAllAdSelectionConfigRemoteOverrides()346 public void testPermissionNotRequested_fledgeResetAllAdSelectionConfigRemoteOverrides() { 347 TestAdSelectionClient testAdSelectionClient = 348 new TestAdSelectionClient.Builder() 349 .setContext(sContext) 350 .setExecutor(CALLBACK_EXECUTOR) 351 .build(); 352 353 Exception exception = 354 assertThrows( 355 ExecutionException.class, 356 () -> { 357 testAdSelectionClient.resetAllAdSelectionConfigRemoteOverrides().get(); 358 }); 359 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 360 } 361 362 // TODO(b/221876775): Unhide for frequency cap mainline promotion 363 /* 364 @Test 365 public void testPermissionNotRequested_updateAdCounterHistogram() { 366 long adSelectionId = 1; 367 368 AdSelectionClient mAdSelectionClient = 369 new AdSelectionClient.Builder() 370 .setContext(sContext) 371 .setExecutor(CALLBACK_EXECUTOR) 372 .build(); 373 374 UpdateAdCounterHistogramRequest request = 375 new UpdateAdCounterHistogramRequest.Builder() 376 .setAdSelectionId(adSelectionId) 377 .setAdEventType(FrequencyCapFilters.AD_EVENT_TYPE_IMPRESSION) 378 .setCallerAdTech(AdTechIdentifier.fromString("test.com")) 379 .build(); 380 ExecutionException exception = 381 assertThrows( 382 ExecutionException.class, 383 () -> mAdSelectionClient.updateAdCounterHistogram(request).get()); 384 385 assertThat(exception.getMessage()).isEqualTo(CALLER_NOT_AUTHORIZED); 386 } 387 */ 388 } 389