1 /* 2 * Copyright (C) 2019 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 android.autofillservice.cts.augmented; 18 19 import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE; 20 import static android.autofillservice.cts.Helper.ID_PASSWORD; 21 import static android.autofillservice.cts.Helper.ID_USERNAME; 22 import static android.autofillservice.cts.Helper.assertHasFlags; 23 import static android.autofillservice.cts.Helper.assertTextAndValue; 24 import static android.autofillservice.cts.Helper.assertViewAutofillState; 25 import static android.autofillservice.cts.Helper.findNodeByResourceId; 26 import static android.autofillservice.cts.LoginActivity.getWelcomeMessage; 27 import static android.autofillservice.cts.UiBot.LANDSCAPE; 28 import static android.autofillservice.cts.UiBot.PORTRAIT; 29 import static android.autofillservice.cts.augmented.AugmentedHelper.assertBasicRequestInfo; 30 import static android.autofillservice.cts.augmented.AugmentedTimeouts.AUGMENTED_FILL_TIMEOUT; 31 import static android.autofillservice.cts.augmented.CannedAugmentedFillResponse.DO_NOT_REPLY_AUGMENTED_RESPONSE; 32 import static android.autofillservice.cts.augmented.CannedAugmentedFillResponse.NO_AUGMENTED_RESPONSE; 33 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; 34 import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_PASSWORD; 35 36 import static com.google.common.truth.Truth.assertThat; 37 import static com.google.common.truth.Truth.assertWithMessage; 38 39 import static org.junit.Assume.assumeTrue; 40 import static org.testng.Assert.assertThrows; 41 42 import android.app.assist.AssistStructure.ViewNode; 43 import android.autofillservice.cts.AutofillActivityTestRule; 44 import android.autofillservice.cts.CannedFillResponse; 45 import android.autofillservice.cts.CannedFillResponse.CannedDataset; 46 import android.autofillservice.cts.Helper; 47 import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest; 48 import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest; 49 import android.autofillservice.cts.LoginActivity; 50 import android.autofillservice.cts.MyAutofillCallback; 51 import android.autofillservice.cts.OneTimeCancellationSignalListener; 52 import android.autofillservice.cts.augmented.CtsAugmentedAutofillService.AugmentedFillRequest; 53 import android.content.ComponentName; 54 import android.os.CancellationSignal; 55 import android.platform.test.annotations.AppModeFull; 56 import android.support.test.uiautomator.UiObject2; 57 import android.util.ArraySet; 58 import android.view.View; 59 import android.view.autofill.AutofillId; 60 import android.view.autofill.AutofillManager; 61 import android.view.autofill.AutofillValue; 62 import android.widget.EditText; 63 64 import org.junit.Test; 65 66 import java.util.Set; 67 68 public class AugmentedLoginActivityTest 69 extends AugmentedAutofillAutoActivityLaunchTestCase<AugmentedLoginActivity> { 70 71 protected AugmentedLoginActivity mActivity; 72 73 @Override getActivityRule()74 protected AutofillActivityTestRule<AugmentedLoginActivity> getActivityRule() { 75 return new AutofillActivityTestRule<AugmentedLoginActivity>( 76 AugmentedLoginActivity.class) { 77 @Override 78 protected void afterActivityLaunched() { 79 mActivity = getActivity(); 80 } 81 }; 82 } 83 84 @Test 85 public void testServiceLifecycle() throws Exception { 86 enableService(); 87 CtsAugmentedAutofillService augmentedService = enableAugmentedService(); 88 89 AugmentedHelper.resetAugmentedService(); 90 augmentedService.waitUntilDisconnected(); 91 } 92 93 @Test 94 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 95 public void testAutoFill_neitherServiceCanAutofill() throws Exception { 96 // Set services 97 enableService(); 98 enableAugmentedService(); 99 100 // Set expectations 101 final EditText username = mActivity.getUsername(); 102 final AutofillValue expectedFocusedValue = username.getAutofillValue(); 103 final AutofillId usernameId = username.getAutofillId(); 104 sReplier.addResponse(NO_RESPONSE); 105 sAugmentedReplier.addResponse(NO_AUGMENTED_RESPONSE); 106 107 // Trigger autofill 108 mActivity.onUsername(View::requestFocus); 109 sReplier.getNextFillRequest(); 110 final AugmentedFillRequest augmentedRequest = sAugmentedReplier.getNextFillRequest(); 111 112 // Assert request 113 assertBasicRequestInfo(augmentedRequest, mActivity, usernameId, expectedFocusedValue); 114 115 // Make sure standard Autofill UI is not shown. 116 mUiBot.assertNoDatasetsEver(); 117 118 // Make sure Augmented Autofill UI is not shown. 119 mAugmentedUiBot.assertUiNeverShown(); 120 } 121 122 @Test 123 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 124 public void testAutoFill_neitherServiceCanAutofill_manualRequest() throws Exception { 125 // Set services 126 enableService(); 127 enableAugmentedService(); 128 129 // Set expectations 130 final EditText username = mActivity.getUsername(); 131 final AutofillValue expectedFocusedValue = username.getAutofillValue(); 132 final AutofillId usernameId = username.getAutofillId(); 133 sReplier.addResponse(NO_RESPONSE); 134 sAugmentedReplier.addResponse(NO_AUGMENTED_RESPONSE); 135 136 // Trigger autofill 137 mActivity.forceAutofillOnUsername(); 138 sReplier.getNextFillRequest(); 139 final AugmentedFillRequest augmentedRequest = sAugmentedReplier.getNextFillRequest(); 140 141 // Assert request 142 assertBasicRequestInfo(augmentedRequest, mActivity, usernameId, expectedFocusedValue); 143 144 // Make sure standard Autofill UI is not shown. 145 mUiBot.assertNoDatasetsEver(); 146 147 // Make sure Augmented Autofill UI is not shown. 148 mAugmentedUiBot.assertUiNeverShown(); 149 } 150 151 @Test 152 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 153 public void testAutoFill_neitherServiceCanAutofill_thenManualRequest() throws Exception { 154 // Set services 155 enableService(); 156 enableAugmentedService(); 157 158 // Set expectations 159 final EditText username = mActivity.getUsername(); 160 final AutofillValue expectedFocusedValue = username.getAutofillValue(); 161 final AutofillId expectedFocusedId = username.getAutofillId(); 162 sReplier.addResponse(NO_RESPONSE); 163 sAugmentedReplier.addResponse(NO_AUGMENTED_RESPONSE); 164 165 // Trigger autofill 166 mActivity.onUsername(View::requestFocus); 167 sReplier.getNextFillRequest(); 168 final AugmentedFillRequest request = sAugmentedReplier.getNextFillRequest(); 169 170 // Assert request 171 assertBasicRequestInfo(request, mActivity, expectedFocusedId, expectedFocusedValue); 172 173 // Make sure standard Autofill UI is not shown. 174 mUiBot.assertNoDatasetsEver(); 175 176 // Make sure Augmented Autofill UI is not shown. 177 mAugmentedUiBot.assertUiNeverShown(); 178 179 // Try again, forcing it 180 sReplier.addResponse(new CannedFillResponse.Builder() 181 .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD) 182 .addDataset(new CannedDataset.Builder() 183 .setField(ID_USERNAME, "dude") 184 .setField(ID_PASSWORD, "sweet") 185 .setPresentation(createPresentation("The Dude")) 186 .build()) 187 .build()); 188 mActivity.expectAutoFill("dude", "sweet"); 189 mActivity.forceAutofillOnUsername(); 190 final FillRequest fillRequest = sReplier.getNextFillRequest(); 191 assertHasFlags(fillRequest.flags, FLAG_MANUAL_REQUEST); 192 mAugmentedUiBot.assertUiNeverShown(); 193 194 mUiBot.selectDataset("The Dude"); 195 mActivity.assertAutoFilled(); 196 197 // Now force save to make sure the values changes are notified 198 mActivity.onUsername((v) -> v.setText("malkovich")); 199 mActivity.onPassword((v) -> v.setText("malkovich")); 200 final String expectedMessage = getWelcomeMessage("malkovich"); 201 final String actualMessage = mActivity.tapLogin(); 202 assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage); 203 204 // Assert the snack bar is shown and tap "Save". 205 mUiBot.updateForAutofill(true, SAVE_DATA_TYPE_PASSWORD); 206 final SaveRequest saveRequest = sReplier.getNextSaveRequest(); 207 sReplier.assertNoUnhandledSaveRequests(); 208 assertThat(saveRequest.datasetIds).isNull(); 209 210 // Assert value of expected fields - should not be sanitized. 211 final ViewNode usernameNode = findNodeByResourceId(saveRequest.structure, ID_USERNAME); 212 assertTextAndValue(usernameNode, "malkovich"); 213 final ViewNode passwordNode = findNodeByResourceId(saveRequest.structure, ID_PASSWORD); 214 assertTextAndValue(passwordNode, "malkovich"); 215 } 216 217 @Test 218 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 219 public void testAutoFill_notImportantForAutofill_thenManualRequest() throws Exception { 220 // Set services 221 enableService(); 222 enableAugmentedService(); 223 224 // Set IMPORTANT_FOR_AUTOFILL_NO 225 mActivity.onUsername((v) -> v.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO)); 226 227 // Set expectations 228 final EditText username = mActivity.getUsername(); 229 final AutofillValue expectedFocusedValue = username.getAutofillValue(); 230 final AutofillId expectedFocusedId = username.getAutofillId(); 231 sAugmentedReplier.addResponse(NO_AUGMENTED_RESPONSE); 232 233 // Trigger autofill 234 mActivity.onUsername(View::requestFocus); 235 sReplier.assertOnFillRequestNotCalled(); 236 final AugmentedFillRequest request = sAugmentedReplier.getNextFillRequest(); 237 238 // Assert request 239 assertBasicRequestInfo(request, mActivity, expectedFocusedId, expectedFocusedValue); 240 241 // Make sure standard Autofill UI is not shown. 242 mUiBot.assertNoDatasetsEver(); 243 244 // Make sure Augmented Autofill UI is not shown. 245 mAugmentedUiBot.assertUiNeverShown(); 246 247 // Try again, forcing it 248 sReplier.addResponse(new CannedFillResponse.Builder() 249 .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD) 250 .addDataset(new CannedDataset.Builder() 251 .setField(ID_USERNAME, "dude") 252 .setField(ID_PASSWORD, "sweet") 253 .setPresentation(createPresentation("The Dude")) 254 .build()) 255 .build()); 256 mActivity.expectAutoFill("dude", "sweet"); 257 mActivity.forceAutofillOnUsername(); 258 final FillRequest fillRequest = sReplier.getNextFillRequest(); 259 assertHasFlags(fillRequest.flags, FLAG_MANUAL_REQUEST); 260 mAugmentedUiBot.assertUiNeverShown(); 261 262 mUiBot.selectDataset("The Dude"); 263 mActivity.assertAutoFilled(); 264 265 // Now force save to make sure the values changes are notified 266 mActivity.onUsername((v) -> v.setText("malkovich")); 267 mActivity.onPassword((v) -> v.setText("malkovich")); 268 final String expectedMessage = getWelcomeMessage("malkovich"); 269 final String actualMessage = mActivity.tapLogin(); 270 assertWithMessage("Wrong welcome msg").that(actualMessage).isEqualTo(expectedMessage); 271 272 // Assert the snack bar is shown and tap "Save". 273 mUiBot.updateForAutofill(true, SAVE_DATA_TYPE_PASSWORD); 274 final SaveRequest saveRequest = sReplier.getNextSaveRequest(); 275 sReplier.assertNoUnhandledSaveRequests(); 276 assertThat(saveRequest.datasetIds).isNull(); 277 278 // Assert value of expected fields - should not be sanitized. 279 final ViewNode usernameNode = findNodeByResourceId(saveRequest.structure, ID_USERNAME); 280 assertTextAndValue(usernameNode, "malkovich"); 281 final ViewNode passwordNode = findNodeByResourceId(saveRequest.structure, ID_PASSWORD); 282 assertTextAndValue(passwordNode, "malkovich"); 283 } 284 285 @Test 286 public void testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField() throws Exception { 287 // Set services 288 enableService(); 289 enableAugmentedService(); 290 291 // Set expectations 292 final EditText username = mActivity.getUsername(); 293 final AutofillId usernameId = username.getAutofillId(); 294 final AutofillValue expectedFocusedValue = username.getAutofillValue(); 295 sReplier.addResponse(NO_RESPONSE); 296 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 297 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me") 298 .setField(usernameId, "dude") 299 .build(), usernameId) 300 .build()); 301 mActivity.expectAutoFill("dude"); 302 303 // Trigger autofill 304 mActivity.onUsername(View::requestFocus); 305 sReplier.getNextFillRequest(); 306 final AugmentedFillRequest request = sAugmentedReplier.getNextFillRequest(); 307 308 // Assert request 309 assertBasicRequestInfo(request, mActivity, usernameId, expectedFocusedValue); 310 311 // Make sure standard Autofill UI is not shown. 312 mUiBot.assertNoDatasetsEver(); 313 314 // Make sure Augmented Autofill UI is shown. 315 final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me"); 316 317 // Autofill 318 ui.click(); 319 mActivity.assertAutoFilled(); 320 mAugmentedUiBot.assertUiGone(); 321 } 322 323 @Test 324 public void testAutoFill_augmentedFillRequestCancelled() throws Exception { 325 // Set services 326 enableService(); 327 enableAugmentedService(); 328 329 // Set expectations 330 final EditText username = mActivity.getUsername(); 331 final AutofillId usernameId = username.getAutofillId(); 332 sReplier.addResponse(NO_RESPONSE); 333 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 334 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me") 335 .setField(usernameId, "dude") 336 .build(), usernameId) 337 .setDelay(AUGMENTED_FILL_TIMEOUT.ms() + 6000) 338 .build()); 339 340 // Trigger autofill 341 mActivity.onUsername(View::requestFocus); 342 sReplier.getNextFillRequest(); 343 sAugmentedReplier.getNextFillRequest(); 344 345 // Make sure standard Autofill UI is not shown. 346 mUiBot.assertNoDatasetsEver(); 347 348 // Make sure Augmented Autofill UI is shown. 349 mAugmentedUiBot.assertUiNeverShown(); 350 } 351 352 @Test 353 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 354 public void testAutoFill_mainServiceReturnedNull_augmentedAutofillTwoFields() throws Exception { 355 // Set services 356 enableService(); 357 enableAugmentedService(); 358 359 // Set expectations 360 final EditText username = mActivity.getUsername(); 361 final AutofillId usernameId = username.getAutofillId(); 362 final AutofillValue expectedFocusedValue = username.getAutofillValue(); 363 sReplier.addResponse(NO_RESPONSE); 364 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 365 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me") 366 .setField(usernameId, "dude") 367 .setField(mActivity.getPassword().getAutofillId(), "sweet") 368 .build(), usernameId) 369 .build()); 370 mActivity.expectAutoFill("dude", "sweet"); 371 372 // Trigger autofill 373 mActivity.onUsername(View::requestFocus); 374 sReplier.getNextFillRequest(); 375 final AugmentedFillRequest request = sAugmentedReplier.getNextFillRequest(); 376 377 // Assert request 378 assertBasicRequestInfo(request, mActivity, usernameId, expectedFocusedValue); 379 380 // Make sure standard Autofill UI is not shown. 381 mUiBot.assertNoDatasetsEver(); 382 383 // Make sure Augmented Autofill UI is shown. 384 final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me"); 385 386 // Autofill 387 ui.click(); 388 mActivity.assertAutoFilled(); 389 mAugmentedUiBot.assertUiGone(); 390 } 391 392 @Test 393 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 394 public void testCancellationSignalCalledAfterTimeout() throws Exception { 395 // Set services 396 enableService(); 397 enableAugmentedService(); 398 399 // Set expectations 400 sReplier.addResponse(NO_RESPONSE); 401 sAugmentedReplier.addResponse(DO_NOT_REPLY_AUGMENTED_RESPONSE); 402 final OneTimeCancellationSignalListener listener = 403 new OneTimeCancellationSignalListener(AUGMENTED_FILL_TIMEOUT.ms() + 5000); 404 405 // Trigger autofill 406 mActivity.onUsername(View::requestFocus); 407 sReplier.getNextFillRequest(); 408 409 final CancellationSignal cancellationSignal = sAugmentedReplier.getNextFillRequest() 410 .cancellationSignal; 411 412 assertThat(cancellationSignal).isNotNull(); 413 cancellationSignal.setOnCancelListener(listener); 414 415 // Assert results 416 listener.assertOnCancelCalled(); 417 } 418 419 @Test 420 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 421 public void testCancellationSignalCalled_retriggerAugmentedAutofill() throws Exception { 422 // Set services 423 enableService(); 424 enableAugmentedService(); 425 426 // Set expectations 427 final EditText username = mActivity.getUsername(); 428 final AutofillId usernameId = username.getAutofillId(); 429 final AutofillValue expectedFocusedValue = username.getAutofillValue(); 430 sReplier.addResponse(NO_RESPONSE); 431 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 432 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me") 433 .setField(usernameId, "dude") 434 .setField(mActivity.getPassword().getAutofillId(), "sweet") 435 .build(), usernameId) 436 .build()); 437 438 final OneTimeCancellationSignalListener listener = 439 new OneTimeCancellationSignalListener(AUGMENTED_FILL_TIMEOUT.ms() + 5000); 440 441 // Trigger autofill 442 mActivity.onUsername(View::requestFocus); 443 sReplier.getNextFillRequest(); 444 final AugmentedFillRequest request = sAugmentedReplier.getNextFillRequest(); 445 446 // Assert request 447 assertBasicRequestInfo(request, mActivity, usernameId, expectedFocusedValue); 448 mAugmentedUiBot.assertUiShown(usernameId, "Augment Me"); 449 450 final CancellationSignal cancellationSignal = request.cancellationSignal; 451 452 assertThat(cancellationSignal).isNotNull(); 453 cancellationSignal.setOnCancelListener(listener); 454 455 // Move focus away to make sure Augmented Autofill UI is gone. 456 mActivity.clearFocus(); 457 mAugmentedUiBot.assertUiGone(); 458 459 // Set expectations for username again. 460 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 461 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me") 462 .setField(usernameId, "dude") 463 .setField(mActivity.getPassword().getAutofillId(), "sweet") 464 .build(), usernameId) 465 .build()); 466 467 // Tap on username again 468 mActivity.onUsername(View::requestFocus); 469 final AugmentedFillRequest request2 = sAugmentedReplier.getNextFillRequest(); 470 471 // Assert first request cancelled 472 listener.assertOnCancelCalled(); 473 474 // Assert request 475 assertBasicRequestInfo(request2, mActivity, usernameId, expectedFocusedValue); 476 final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me"); 477 478 // ...and autofill this time 479 mActivity.expectAutoFill("dude", "sweet"); 480 ui.click(); 481 mActivity.assertAutoFilled(); 482 mAugmentedUiBot.assertUiGone(); 483 } 484 485 @Test 486 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 487 public void testAugmentedAutoFill_multipleRequests() throws Exception { 488 // Set services 489 enableService(); 490 enableAugmentedService(); 491 492 // Set expectations 493 final EditText username = mActivity.getUsername(); 494 final AutofillId usernameId = username.getAutofillId(); 495 final AutofillValue usernameValue = username.getAutofillValue(); 496 sReplier.addResponse(NO_RESPONSE); 497 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 498 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("req1") 499 .build(), usernameId) 500 .build()); 501 502 // Trigger autofill 503 mActivity.onUsername(View::requestFocus); 504 sReplier.getNextFillRequest(); 505 final AugmentedFillRequest request1 = sAugmentedReplier.getNextFillRequest(); 506 507 // Assert request 508 assertBasicRequestInfo(request1, mActivity, usernameId, usernameValue); 509 510 // Make sure standard Autofill UI is not shown. 511 mUiBot.assertNoDatasetsEver(); 512 513 // Make sure Augmented Autofill UI is shown. 514 mAugmentedUiBot.assertUiShown(usernameId, "req1"); 515 516 // Move focus away to make sure Augmented Autofill UI is gone. 517 mActivity.onLogin(View::requestFocus); 518 mAugmentedUiBot.assertUiGone(); 519 520 // Tap on password field 521 final EditText password = mActivity.getPassword(); 522 final AutofillId passwordId = password.getAutofillId(); 523 final AutofillValue passwordValue = password.getAutofillValue(); 524 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 525 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("req2") 526 .build(), passwordId) 527 .build()); 528 mActivity.onPassword(View::requestFocus); 529 mUiBot.assertNoDatasetsEver(); 530 final AugmentedFillRequest request2 = sAugmentedReplier.getNextFillRequest(); 531 assertBasicRequestInfo(request2, mActivity, passwordId, passwordValue); 532 533 mAugmentedUiBot.assertUiShown(passwordId, "req2"); 534 535 // Tap on username again... 536 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 537 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me") 538 .setField(usernameId, "dude") 539 .setField(passwordId, "sweet") 540 .build(), usernameId) 541 .build()); 542 543 mActivity.onUsername(View::requestFocus); 544 final AugmentedFillRequest request3 = sAugmentedReplier.getNextFillRequest(); 545 assertBasicRequestInfo(request3, mActivity, usernameId, usernameValue); 546 final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me"); 547 548 // ...and autofill this time 549 mActivity.expectAutoFill("dude", "sweet"); 550 ui.click(); 551 mActivity.assertAutoFilled(); 552 mAugmentedUiBot.assertUiGone(); 553 } 554 555 @Test 556 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 557 public void testAugmentedAutoFill_thenEditField() throws Exception { 558 // Set services 559 enableService(); 560 enableAugmentedService(); 561 562 // Set expectations 563 final EditText username = mActivity.getUsername(); 564 final AutofillId usernameId = username.getAutofillId(); 565 final AutofillValue expectedFocusedValue = username.getAutofillValue(); 566 sReplier.addResponse(NO_RESPONSE); 567 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 568 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me") 569 .setField(usernameId, "dude") 570 .build(), usernameId) 571 .build()); 572 mActivity.expectAutoFill("dude"); 573 574 // Trigger autofill 575 mActivity.onUsername(View::requestFocus); 576 sReplier.getNextFillRequest(); 577 final AugmentedFillRequest request = sAugmentedReplier.getNextFillRequest(); 578 579 // Assert request 580 assertBasicRequestInfo(request, mActivity, usernameId, expectedFocusedValue); 581 582 // Make sure standard Autofill UI is not shown. 583 mUiBot.assertNoDatasetsEver(); 584 585 // Make sure Augmented Autofill UI is shown. 586 final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me"); 587 588 // Autofill 589 ui.click(); 590 mActivity.assertAutoFilled(); 591 mAugmentedUiBot.assertUiGone(); 592 assertViewAutofillState(mActivity.getUsername(), true); 593 594 // Now change value and make sure autofill status is changed 595 mActivity.onUsername((v) -> v.setText("I AM GROOT")); 596 assertViewAutofillState(mActivity.getUsername(), false); 597 } 598 599 @Test 600 public void testAugmentedAutoFill_callback() throws Exception { 601 // Set services 602 enableService(); 603 enableAugmentedService(); 604 605 // Set expectations 606 final MyAutofillCallback callback = mActivity.registerCallback(); 607 final EditText username = mActivity.getUsername(); 608 final AutofillId usernameId = username.getAutofillId(); 609 final AutofillValue usernameValue = username.getAutofillValue(); 610 sReplier.addResponse(NO_RESPONSE); 611 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 612 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("req1") 613 .build(), usernameId) 614 .build()); 615 616 // Trigger autofill 617 mActivity.onUsername(View::requestFocus); 618 sReplier.getNextFillRequest(); 619 final AugmentedFillRequest request1 = sAugmentedReplier.getNextFillRequest(); 620 621 // Assert request 622 assertBasicRequestInfo(request1, mActivity, usernameId, usernameValue); 623 624 // Make sure standard Autofill UI is not shown. 625 mUiBot.assertNoDatasetsEver(); 626 627 // Make sure Augmented Autofill UI is shown. 628 callback.assertUiShownEvent(username); 629 mAugmentedUiBot.assertUiShown(usernameId, "req1"); 630 631 // Move focus away to make sure Augmented Autofill UI is gone. 632 mActivity.onLogin(View::requestFocus); 633 mAugmentedUiBot.assertUiGone(); 634 callback.assertUiHiddenEvent(username); 635 636 // Tap on password field 637 final EditText password = mActivity.getPassword(); 638 final AutofillId passwordId = password.getAutofillId(); 639 final AutofillValue passwordValue = password.getAutofillValue(); 640 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 641 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("req2") 642 .build(), passwordId) 643 .build()); 644 mActivity.onPassword(View::requestFocus); 645 mUiBot.assertNoDatasetsEver(); 646 final AugmentedFillRequest request2 = sAugmentedReplier.getNextFillRequest(); 647 assertBasicRequestInfo(request2, mActivity, passwordId, passwordValue); 648 649 callback.assertUiShownEvent(password); 650 mAugmentedUiBot.assertUiShown(passwordId, "req2"); 651 652 // Tap on username again... 653 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 654 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me") 655 .setField(usernameId, "dude") 656 .setField(passwordId, "sweet") 657 .build(), usernameId) 658 .build()); 659 660 mActivity.onUsername(View::requestFocus); 661 final AugmentedFillRequest request3 = sAugmentedReplier.getNextFillRequest(); 662 assertBasicRequestInfo(request3, mActivity, usernameId, usernameValue); 663 final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me"); 664 665 // ...and autofill this time 666 mActivity.expectAutoFill("dude", "sweet"); 667 ui.click(); 668 mActivity.assertAutoFilled(); 669 mAugmentedUiBot.assertUiGone(); 670 callback.assertUiHiddenEvent(password); 671 } 672 673 @Test 674 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 675 public void testAugmentedAutoFill_rotateDevice() throws Exception { 676 assumeTrue("Rotation is supported", Helper.isRotationSupported(mContext)); 677 678 // Set services 679 enableService(); 680 enableAugmentedService(); 681 682 // Set expectations 683 final EditText username = mActivity.getUsername(); 684 final AutofillId usernameId = username.getAutofillId(); 685 final AutofillValue usernameValue = username.getAutofillValue(); 686 sReplier.addResponse(NO_RESPONSE); 687 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 688 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me 1") 689 .setField(usernameId, "dude1") 690 .build(), usernameId) 691 .build()); 692 693 // Trigger autofill 694 mActivity.onUsername(View::requestFocus); 695 sReplier.getNextFillRequest(); 696 final AugmentedFillRequest request1 = sAugmentedReplier.getNextFillRequest(); 697 698 AugmentedLoginActivity currentActivity = mActivity; 699 700 // Assert request 701 assertBasicRequestInfo(request1, currentActivity, usernameId, usernameValue); 702 703 // Make sure standard Autofill UI is not shown. 704 mUiBot.assertNoDatasetsEver(); 705 706 // Make sure Augmented Autofill UI is shown. 707 mAugmentedUiBot.assertUiShown(usernameId, "Augment Me 1"); 708 709 // 1st landscape rotation 710 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 711 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me 2") 712 .setField(usernameId, "dude2") 713 .build(), usernameId) 714 .build()); 715 mUiBot.setScreenOrientation(LANDSCAPE); 716 mUiBot.assertNoDatasetsEver(); 717 718 // Must update currentActivity after each rotation because it generates a new instance 719 currentActivity = LoginActivity.getCurrentActivity(); 720 721 final AugmentedFillRequest request2 = sAugmentedReplier.getNextFillRequest(); 722 assertBasicRequestInfo(request2, currentActivity, usernameId, usernameValue); 723 mAugmentedUiBot.assertUiShown(usernameId, "Augment Me 2"); 724 725 // Rotate back 726 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 727 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me 3") 728 .setField(usernameId, "dude3") 729 .build(), usernameId) 730 .build()); 731 mUiBot.setScreenOrientation(PORTRAIT); 732 mUiBot.assertNoDatasetsEver(); 733 currentActivity = LoginActivity.getCurrentActivity(); 734 735 final AugmentedFillRequest request3 = sAugmentedReplier.getNextFillRequest(); 736 assertBasicRequestInfo(request3, currentActivity, usernameId, usernameValue); 737 mAugmentedUiBot.assertUiShown(usernameId, "Augment Me 3"); 738 739 // 2nd landscape rotation 740 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 741 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me 4") 742 .setField(usernameId, "dude4") 743 .build(), usernameId) 744 .build()); 745 mUiBot.setScreenOrientation(LANDSCAPE); 746 mUiBot.assertNoDatasetsEver(); 747 currentActivity = LoginActivity.getCurrentActivity(); 748 749 final AugmentedFillRequest request4 = sAugmentedReplier.getNextFillRequest(); 750 assertBasicRequestInfo(request4, currentActivity, usernameId, usernameValue); 751 mAugmentedUiBot.assertUiShown(usernameId, "Augment Me 4"); 752 753 // Final rotation - should be enough.... 754 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 755 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me 5") 756 .setField(usernameId, "dude5") 757 .build(), usernameId) 758 .build()); 759 mUiBot.setScreenOrientation(PORTRAIT); 760 mUiBot.assertNoDatasetsEver(); 761 currentActivity = LoginActivity.getCurrentActivity(); 762 763 final AugmentedFillRequest request5 = sAugmentedReplier.getNextFillRequest(); 764 assertBasicRequestInfo(request5, mActivity, usernameId, usernameValue); 765 final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me 5"); 766 767 // ..then autofill 768 769 // Must get the latest activity because each rotation creates a new object. 770 currentActivity.expectAutoFill("dude5"); 771 ui.click(); 772 mAugmentedUiBot.assertUiGone(); 773 currentActivity.assertAutoFilled(); 774 } 775 776 @Test 777 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 778 public void testAugmentedAutoFill_mainServiceDisabled() throws Exception { 779 // Set services 780 Helper.disableAutofillService(sContext); 781 enableAugmentedService(); 782 783 // Set expectations 784 final EditText username = mActivity.getUsername(); 785 final AutofillId usernameId = username.getAutofillId(); 786 final AutofillValue usernameValue = username.getAutofillValue(); 787 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 788 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me") 789 .setField(usernameId, "dude") 790 .build(), usernameId) 791 .build()); 792 mActivity.expectAutoFill("dude"); 793 794 // Trigger autofill 795 mActivity.onUsername(View::requestFocus); 796 final AugmentedFillRequest request = sAugmentedReplier.getNextFillRequest(); 797 798 // Assert request 799 assertBasicRequestInfo(request, mActivity, usernameId, usernameValue); 800 801 // Make sure standard Autofill UI is not shown. 802 mUiBot.assertNoDatasetsEver(); 803 804 // Make sure Augmented Autofill UI is shown. 805 final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me"); 806 807 // Autofill 808 ui.click(); 809 mActivity.assertAutoFilled(); 810 mAugmentedUiBot.assertUiGone(); 811 } 812 813 @Test 814 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 815 public void testAugmentedAutoFill_mainServiceDisabled_manualRequest() throws Exception { 816 // Set services 817 Helper.disableAutofillService(sContext); 818 enableAugmentedService(); 819 820 // Set expectations 821 final EditText username = mActivity.getUsername(); 822 final AutofillId usernameId = username.getAutofillId(); 823 final AutofillValue usernameValue = username.getAutofillValue(); 824 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 825 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me") 826 .setField(usernameId, "dude") 827 .build(), usernameId) 828 .build()); 829 mActivity.expectAutoFill("dude"); 830 831 // Trigger autofill 832 mActivity.forceAutofillOnUsername(); 833 final AugmentedFillRequest request = sAugmentedReplier.getNextFillRequest(); 834 835 // Assert request 836 assertBasicRequestInfo(request, mActivity, usernameId, usernameValue); 837 838 // Make sure standard Autofill UI is not shown. 839 mUiBot.assertNoDatasetsEver(); 840 841 // Make sure Augmented Autofill UI is shown. 842 final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me"); 843 844 // Autofill 845 ui.click(); 846 mActivity.assertAutoFilled(); 847 mAugmentedUiBot.assertUiGone(); 848 } 849 850 @Test 851 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 852 public void testAugmentedAutoFill_mainServiceDisabled_autoThenManualRequest() throws Exception { 853 // Set services 854 Helper.disableAutofillService(sContext); 855 enableAugmentedService(); 856 857 // Set expectations 858 final EditText username = mActivity.getUsername(); 859 final AutofillId usernameId = username.getAutofillId(); 860 final AutofillValue usernameValue = username.getAutofillValue(); 861 sAugmentedReplier.addResponse(NO_AUGMENTED_RESPONSE); 862 863 // Trigger autofill 864 mActivity.onUsername(View::requestFocus); 865 final AugmentedFillRequest request1 = sAugmentedReplier.getNextFillRequest(); 866 assertBasicRequestInfo(request1, mActivity, usernameId, usernameValue); 867 868 // Make sure standard no UI is not shown. 869 mUiBot.assertNoDatasetsEver(); 870 mAugmentedUiBot.assertUiNeverShown(); 871 872 873 // Trigger 2nd request, manually 874 sAugmentedReplier.addResponse(new CannedAugmentedFillResponse.Builder() 875 .setDataset(new CannedAugmentedFillResponse.Dataset.Builder("Augment Me") 876 .setField(usernameId, "dude") 877 .build(), usernameId) 878 .build()); 879 mActivity.expectAutoFill("dude"); 880 mActivity.forceAutofillOnUsername(); 881 final AugmentedFillRequest request2 = sAugmentedReplier.getNextFillRequest(); 882 assertBasicRequestInfo(request2, mActivity, usernameId, usernameValue); 883 884 // Make sure standard Autofill UI is not shown. 885 mUiBot.assertNoDatasetsEver(); 886 887 // Make sure Augmented Autofill UI is shown. 888 final UiObject2 ui = mAugmentedUiBot.assertUiShown(usernameId, "Augment Me"); 889 890 // Autofill 891 ui.click(); 892 mActivity.assertAutoFilled(); 893 mAugmentedUiBot.assertUiGone(); 894 } 895 896 @Test 897 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 898 public void testAugmentedAutoFill_mainServiceDisabled_valueChangedOnSecondRequest() 899 throws Exception { 900 // Set services 901 Helper.disableAutofillService(sContext); 902 enableAugmentedService(); 903 904 // Set expectations 905 final EditText username = mActivity.getUsername(); 906 final AutofillId usernameId = username.getAutofillId(); 907 final AutofillValue initialValue = username.getAutofillValue(); 908 sAugmentedReplier.addResponse(NO_AUGMENTED_RESPONSE); 909 910 // Trigger autofill 911 mActivity.onUsername(View::requestFocus); 912 final AugmentedFillRequest request1 = sAugmentedReplier.getNextFillRequest(); 913 914 // Assert request 915 assertBasicRequestInfo(request1, mActivity, usernameId, initialValue); 916 917 // Make sure UIs were not shown 918 mUiBot.assertNoDatasetsEver(); 919 mAugmentedUiBot.assertUiNeverShown(); 920 921 // Change field value 922 mActivity.onUsername((v) -> v.setText("DOH")); 923 924 // Trigger autofill again 925 sAugmentedReplier.addResponse(NO_AUGMENTED_RESPONSE); 926 mActivity.onUsername(View::performClick); 927 final AugmentedFillRequest request2 = sAugmentedReplier.getNextFillRequest(); 928 929 // Assert 2nd request 930 assertBasicRequestInfo(request2, mActivity, usernameId, "DOH"); 931 932 // Make sure UIs were not shown 933 mUiBot.assertNoDatasetsEver(); 934 mAugmentedUiBot.assertUiNeverShown(); 935 } 936 937 @Test 938 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 939 public void testSetAugmentedAutofillWhitelist_noStandardServiceSet() throws Exception { 940 final AutofillManager mgr = mActivity.getAutofillManager(); 941 assertThrows(SecurityException.class, 942 () -> mgr.setAugmentedAutofillWhitelist((Set<String>) null, 943 (Set<ComponentName>) null)); 944 } 945 946 @Test 947 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 948 public void testSetAugmentedAutofillWhitelist_notAugmentedService() throws Exception { 949 enableService(); 950 final AutofillManager mgr = mActivity.getAutofillManager(); 951 assertThrows(SecurityException.class, 952 () -> mgr.setAugmentedAutofillWhitelist((Set<String>) null, 953 (Set<ComponentName>) null)); 954 } 955 956 @Test 957 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 958 public void testAugmentedAutofill_packageNotWhitelisted() throws Exception { 959 // Set services 960 enableService(); 961 enableAugmentedService(); 962 963 final AutofillManager mgr = mActivity.getAutofillManager(); 964 mgr.setAugmentedAutofillWhitelist((Set) null, (Set) null); 965 966 // Set expectations 967 sReplier.addResponse(NO_RESPONSE); 968 969 // Trigger autofill 970 mActivity.onUsername(View::requestFocus); 971 sReplier.getNextFillRequest(); 972 973 // Assert no fill requests 974 sAugmentedReplier.assertNoUnhandledFillRequests(); 975 976 // Make sure standard Autofill UI is not shown. 977 mUiBot.assertNoDatasetsEver(); 978 979 // Make sure Augmented Autofill UI is not shown. 980 mAugmentedUiBot.assertUiNeverShown(); 981 } 982 983 @Test 984 @AppModeFull(reason = "testAutoFill_mainServiceReturnedNull_augmentedAutofillOneField enough") 985 public void testAugmentedAutofill_activityNotWhitelisted() throws Exception { 986 // Set services 987 enableService(); 988 enableAugmentedService(); 989 990 final AutofillManager mgr = mActivity.getAutofillManager(); 991 final ArraySet<ComponentName> components = new ArraySet<>(); 992 components.add(new ComponentName(Helper.MY_PACKAGE, "some.activity")); 993 mgr.setAugmentedAutofillWhitelist(null, components); 994 995 // Set expectations 996 sReplier.addResponse(NO_RESPONSE); 997 998 // Trigger autofill 999 mActivity.onUsername(View::requestFocus); 1000 sReplier.getNextFillRequest(); 1001 1002 // Assert no fill requests 1003 sAugmentedReplier.assertNoUnhandledFillRequests(); 1004 1005 // Make sure standard Autofill UI is not shown. 1006 mUiBot.assertNoDatasetsEver(); 1007 1008 // Make sure Augmented Autofill UI is not shown. 1009 mAugmentedUiBot.assertUiNeverShown(); 1010 } 1011 1012 /* 1013 * TODO(b/123542344) - add moarrrr tests: 1014 * 1015 * - Augmented service returned null 1016 * - Focus back and forth between username and passwod 1017 * - When Augmented service shows UI on one field (like username) but not other. 1018 * - When Augmented service shows UI on one field (like username) on both. 1019 * - Tap back 1020 * - Tap home (then bring activity back) 1021 * - Acitivy is killed (and restored) 1022 * - Main service returns non-null response that doesn't show UI (for example, has just 1023 * SaveInfo) 1024 * - Augmented autofill show UI, user fills, Save UI is shown 1025 * - etc ... 1026 * - No augmented autofill calls when the main service is not set. 1027 * - etc... 1028 */ 1029 } 1030