Commit b29d720e authored by Maxim Kolosovskiy's avatar Maxim Kolosovskiy Committed by Commit Bot

[Autofill Assistant] Integration test for the password change flows

This CL also add an Android wrapper for ChromePasswordManagerClient. The
wrapper is need to modify the client from Java side in order to skip the
intent verification.

The test for password change flow is moved to a dedicated file (
AutofillAssistantPasswordManagerIntegrationTest.java).

Bug: 1057608
Change-Id: Iee1e17fda164277fb05ef87eb52592c7b4a4abd5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2112560
Commit-Queue: Maxim Kolosovskiy <kolos@chromium.org>
Commit-Queue: Andrew Grieve <agrieve@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarClemens Arbesser <arbesser@google.com>
Reviewed-by: default avatarFriedrich [CET] <fhorschig@chromium.org>
Auto-Submit: Maxim Kolosovskiy <kolos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#752836}
parent d9eaa1e9
...@@ -839,6 +839,7 @@ android_library("chrome_test_java") { ...@@ -839,6 +839,7 @@ android_library("chrome_test_java") {
"//chrome/browser/android/metrics:ukm_javatests", "//chrome/browser/android/metrics:ukm_javatests",
"//chrome/browser/download/android:java", "//chrome/browser/download/android:java",
"//chrome/browser/flags:java", "//chrome/browser/flags:java",
"//chrome/browser/password_manager/android_test_helpers:test_support_java",
"//chrome/browser/performance_hints/android:java", "//chrome/browser/performance_hints/android:java",
"//chrome/browser/preferences:java", "//chrome/browser/preferences:java",
"//chrome/browser/profiles/android:java", "//chrome/browser/profiles/android:java",
...@@ -1284,6 +1285,7 @@ chrome_common_shared_library("libchromefortest") { ...@@ -1284,6 +1285,7 @@ chrome_common_shared_library("libchromefortest") {
"//base/test:test_support", "//base/test:test_support",
"//chrome:chrome_android_core", "//chrome:chrome_android_core",
"//chrome/browser/android/metrics:ukm_utils_for_test", "//chrome/browser/android/metrics:ukm_utils_for_test",
"//chrome/browser/password_manager/android_test_helpers:android_wrappers",
"//chrome/browser/subresource_filter:test_support", "//chrome/browser/subresource_filter:test_support",
"//components/autofill_assistant/browser:test_support", "//components/autofill_assistant/browser:test_support",
"//components/crash/android:crash_android", "//components/crash/android:crash_android",
...@@ -1607,6 +1609,7 @@ java_group("chrome_public_base_module_java_for_test") { ...@@ -1607,6 +1609,7 @@ java_group("chrome_public_base_module_java_for_test") {
":chrome_public_base_module_java", ":chrome_public_base_module_java",
"//chrome/android/features/autofill_assistant:autofill_assistant_java_test_support", "//chrome/android/features/autofill_assistant:autofill_assistant_java_test_support",
"//chrome/browser/android/metrics:ukm_java_test_support", "//chrome/browser/android/metrics:ukm_java_test_support",
"//chrome/browser/password_manager/android_test_helpers:test_support_java",
"//chrome/browser/subresource_filter:subresource_filter_java_test_support", "//chrome/browser/subresource_filter:subresource_filter_java_test_support",
"//chrome/browser/thumbnail:thumbnail_java_test_support", "//chrome/browser/thumbnail:thumbnail_java_test_support",
"//components/minidump_uploader:minidump_uploader_java", "//components/minidump_uploader:minidump_uploader_java",
......
...@@ -243,6 +243,7 @@ android_library("test_java") { ...@@ -243,6 +243,7 @@ android_library("test_java") {
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantInfoBoxUiTest.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantOverlayIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantOverlayIntegrationTest.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantOverlayUiTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantOverlayUiTest.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPasswordManagerIntegrationTest.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPersonalDataManagerTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPersonalDataManagerTest.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTextUtilsTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTextUtilsTest.java",
"javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java",
...@@ -259,6 +260,7 @@ android_library("test_java") { ...@@ -259,6 +260,7 @@ android_library("test_java") {
"//chrome/android:chrome_java", "//chrome/android:chrome_java",
"//chrome/android:chrome_test_util_java", "//chrome/android:chrome_test_util_java",
"//chrome/browser/image_fetcher:java", "//chrome/browser/image_fetcher:java",
"//chrome/browser/password_manager/android_test_helpers:test_support_java",
"//chrome/browser/preferences:java", "//chrome/browser/preferences:java",
"//chrome/test/android:chrome_java_test_support", "//chrome/test/android:chrome_java_test_support",
"//components/autofill_assistant/browser:proto_java", "//components/autofill_assistant/browser:proto_java",
......
include_rules = [ include_rules = [
"+components/browser_ui/widget/android", "+components/browser_ui/widget/android",
"+chrome/browser/password_manager/android_test_helpers",
"-content/public/android",
"+content/public/android/java/src/org/chromium/content_public/browser", "+content/public/android/java/src/org/chromium/content_public/browser",
] ]
...@@ -26,7 +26,6 @@ import static org.hamcrest.MatcherAssert.assertThat; ...@@ -26,7 +26,6 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.iterableWithSize; import static org.hamcrest.Matchers.iterableWithSize;
...@@ -75,7 +74,6 @@ import org.chromium.chrome.browser.autofill_assistant.proto.ProcessedActionProto ...@@ -75,7 +74,6 @@ import org.chromium.chrome.browser.autofill_assistant.proto.ProcessedActionProto
import org.chromium.chrome.browser.autofill_assistant.proto.ProcessedActionStatusProto; import org.chromium.chrome.browser.autofill_assistant.proto.ProcessedActionStatusProto;
import org.chromium.chrome.browser.autofill_assistant.proto.PromptProto; import org.chromium.chrome.browser.autofill_assistant.proto.PromptProto;
import org.chromium.chrome.browser.autofill_assistant.proto.PromptProto.Choice; import org.chromium.chrome.browser.autofill_assistant.proto.PromptProto.Choice;
import org.chromium.chrome.browser.autofill_assistant.proto.SetFormFieldValueProto;
import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto; import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto;
import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto.PresentationProto; import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto.PresentationProto;
import org.chromium.chrome.browser.autofill_assistant.proto.TextInputProto; import org.chromium.chrome.browser.autofill_assistant.proto.TextInputProto;
...@@ -188,60 +186,6 @@ public class AutofillAssistantCollectUserDataIntegrationTest { ...@@ -188,60 +186,6 @@ public class AutofillAssistantCollectUserDataIntegrationTest {
assertThat(getElementValue(getWebContents(), "exp_year"), is("2050")); assertThat(getElementValue(getWebContents(), "exp_year"), is("2050"));
} }
/**
* Fill a form with a password generated by Chrome.
*/
@Test
@MediumTest
public void testEnterGeneratedPassword() throws Exception {
ArrayList<ActionProto> list = new ArrayList<>();
list.add(
(ActionProto) ActionProto.newBuilder()
.setSetFormValue(
SetFormFieldValueProto.newBuilder()
.addValue(SetFormFieldValueProto.KeyPress.newBuilder()
.setGeneratePassword(
SetFormFieldValueProto
.GeneratePassword
.newBuilder()
.setMemoryKey(
"memory-key")))
.setElement(ElementReferenceProto.newBuilder().addSelectors(
"#password")))
.build());
list.add(
(ActionProto) ActionProto.newBuilder()
.setSetFormValue(
SetFormFieldValueProto.newBuilder()
.addValue(SetFormFieldValueProto.KeyPress.newBuilder()
.setClientMemoryKey("memory-key"))
.setElement(ElementReferenceProto.newBuilder().addSelectors(
"#password-conf")))
.build());
list.add((ActionProto) ActionProto.newBuilder()
.setPrompt(PromptProto.newBuilder().setMessage("Prompt").addChoices(
PromptProto.Choice.newBuilder()))
.build());
AutofillAssistantTestScript script = new AutofillAssistantTestScript(
(SupportedScriptProto) SupportedScriptProto.newBuilder()
.setPath("form_target_website.html")
.setPresentation(PresentationProto.newBuilder().setAutostart(true).setChip(
ChipProto.newBuilder().setText("Password generation")))
.build(),
list);
AutofillAssistantTestService testService =
new AutofillAssistantTestService(Collections.singletonList(script));
startAutofillAssistant(mTestRule.getActivity(), testService);
waitUntilViewMatchesCondition(withText("Prompt"), isCompletelyDisplayed());
String password = getElementValue(getWebContents(), "password");
String confirmation_password = getElementValue(getWebContents(), "password-conf");
assertThat(password.length(), greaterThan(0));
assertThat(password, is(confirmation_password));
}
/** /**
* Showcasts an element of the webpage and checks that it can be interacted with. * Showcasts an element of the webpage and checks that it can be interacted with.
*/ */
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.autofill_assistant;
import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.getElementValue;
import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilViewMatchesCondition;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.chrome.browser.autofill_assistant.proto.ActionProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ChipProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ElementReferenceProto;
import org.chromium.chrome.browser.autofill_assistant.proto.PromptProto;
import org.chromium.chrome.browser.autofill_assistant.proto.SetFormFieldValueProto;
import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto;
import org.chromium.chrome.browser.autofill_assistant.proto.SupportedScriptProto.PresentationProto;
import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.password_manager.PasswordChangeLauncher;
import org.chromium.chrome.browser.password_manager.PasswordManagerClientBridgeForTesting;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import java.util.ArrayList;
import java.util.Collections;
/**
* Integration tests for password change flows.
*/
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@RunWith(ChromeJUnit4ClassRunner.class)
public class AutofillAssistantPasswordManagerIntegrationTest {
@Rule
public CustomTabActivityTestRule mTestRule = new CustomTabActivityTestRule();
private static final String TEST_PAGE = "/components/test/data/autofill_assistant/html/"
+ "form_target_website.html";
private WebContents getWebContents() {
return mTestRule.getWebContents();
}
@Before
public void setUp() throws Exception {
AutofillAssistantPreferencesUtil.setInitialPreferences(true);
mTestRule.startCustomTabActivityWithIntent(CustomTabsTestUtils.createMinimalCustomTabIntent(
InstrumentationRegistry.getTargetContext(),
mTestRule.getTestServer().getURL(TEST_PAGE)));
TestThreadUtils.runOnUiThreadBlocking(
()
-> PasswordManagerClientBridgeForTesting.setLeakDialogWasShownForTesting(
getWebContents(), true));
}
@After
public void tearDown() {
TestThreadUtils.runOnUiThreadBlocking(
()
-> PasswordManagerClientBridgeForTesting.setLeakDialogWasShownForTesting(
getWebContents(), false));
}
/**
* Helper function to start a password change flow.
*/
private void startPasswordChangeFlow(AutofillAssistantTestScript script, String username) {
AutofillAssistantTestService testService =
new AutofillAssistantTestService(Collections.singletonList(script));
testService.scheduleForInjection();
TestThreadUtils.runOnUiThreadBlocking(
()
-> PasswordChangeLauncher.start(getWebContents().getTopLevelNativeWindow(),
getWebContents().getLastCommittedUrl(), username));
}
/**
* Run a password change flow (fill a form with username, old password, new password).
*/
@Test
@MediumTest
public void testPasswordChangeFlow() throws Exception {
ArrayList<ActionProto> list = new ArrayList<>();
list.add(
(ActionProto) ActionProto.newBuilder()
.setSetFormValue(
SetFormFieldValueProto.newBuilder()
.addValue(SetFormFieldValueProto.KeyPress.newBuilder()
.setUseUsername(true))
.setElement(ElementReferenceProto.newBuilder().addSelectors(
"#username")))
.build());
// TODO(crbug.com/1057608): Implement Android wrapper for PasswordStore to add a step and
// verification for current password filling.
list.add(
(ActionProto) ActionProto.newBuilder()
.setSetFormValue(
SetFormFieldValueProto.newBuilder()
.addValue(SetFormFieldValueProto.KeyPress.newBuilder()
.setGeneratePassword(
SetFormFieldValueProto
.GeneratePassword
.newBuilder()
.setMemoryKey(
"memory-key")))
.setElement(ElementReferenceProto.newBuilder().addSelectors(
"#new-password")))
.build());
list.add(
(ActionProto) ActionProto.newBuilder()
.setSetFormValue(
SetFormFieldValueProto.newBuilder()
.addValue(SetFormFieldValueProto.KeyPress.newBuilder()
.setClientMemoryKey("memory-key"))
.setElement(ElementReferenceProto.newBuilder().addSelectors(
"#password-conf")))
.build());
list.add((ActionProto) ActionProto.newBuilder()
.setPrompt(PromptProto.newBuilder().setMessage("Prompt").addChoices(
PromptProto.Choice.newBuilder()))
.build());
AutofillAssistantTestScript script = new AutofillAssistantTestScript(
(SupportedScriptProto) SupportedScriptProto.newBuilder()
.setPath("form_target_website.html")
.setPresentation(PresentationProto.newBuilder().setAutostart(true).setChip(
ChipProto.newBuilder().setText("Password generation")))
.build(),
list);
String username = "test_username";
startPasswordChangeFlow(script, username);
waitUntilViewMatchesCondition(withText("Prompt"), isCompletelyDisplayed());
assertThat(getElementValue(getWebContents(), "username"), is(username));
String password = getElementValue(getWebContents(), "new-password");
String confirmation_password = getElementValue(getWebContents(), "password-conf");
assertThat(password.length(), greaterThan(0));
assertThat(password, is(confirmation_password));
}
}
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/config/android/rules.gni")
static_library("android_wrappers") {
testonly = true
sources = [ "chrome_password_manager_client_android_wrapper.cc" ]
deps = [
"//base",
"//chrome/browser:browser",
"//chrome/browser/password_manager/android_test_helpers:jni_headers",
"//content/public/browser",
]
}
generate_jni("jni_headers") {
testonly = true
sources = [ "javatests/src/org/chromium/chrome/browser/password_manager/PasswordManagerClientBridgeForTesting.java" ]
}
android_library("test_support_java") {
testonly = true
sources = [ "javatests/src/org/chromium/chrome/browser/password_manager/PasswordManagerClientBridgeForTesting.java" ]
deps = [
"//base:base_jni_headers",
"//base:jni_java",
"//content/public/android:content_java",
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <jni.h>
#include "base/android/scoped_java_ref.h"
#include "build/build_config.h"
#include "chrome/browser/password_manager/android_test_helpers/jni_headers/PasswordManagerClientBridgeForTesting_jni.h"
#include "chrome/browser/password_manager/chrome_password_manager_client.h"
#include "content/public/browser/web_contents.h"
namespace password_manager {
// static
void JNI_PasswordManagerClientBridgeForTesting_SetLeakDialogWasShownForTesting(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& j_web_contents,
jboolean j_value) {
content::WebContents* web_contents =
content::WebContents::FromJavaWebContents(j_web_contents);
return ChromePasswordManagerClient::FromWebContents(web_contents)
->SetCredentialLeakDialogWasShownForTesting(j_value);
}
} // namespace password_manager
include_rules = [
"-content/public/android",
"+content/public/android/java/src/org/chromium/content_public/browser",
]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.password_manager;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.content_public.browser.WebContents;
/**
* Android bridge to |ChromePasswordManagerClient| for Java tests.
*/
@JNINamespace("password_manager")
public class PasswordManagerClientBridgeForTesting {
@VisibleForTesting
public static void setLeakDialogWasShownForTesting(WebContents webContents, boolean value) {
PasswordManagerClientBridgeForTestingJni.get().setLeakDialogWasShownForTesting(
webContents, value);
}
@NativeMethods
interface Natives {
void setLeakDialogWasShownForTesting(WebContents webContents, boolean value);
}
}
...@@ -254,8 +254,8 @@ class ChromePasswordManagerClient ...@@ -254,8 +254,8 @@ class ChromePasswordManagerClient
} }
bool WasCredentialLeakDialogShown() const override; bool WasCredentialLeakDialogShown() const override;
void SetCredentialLeakDialogWasShownForTesting() { void SetCredentialLeakDialogWasShownForTesting(bool value) {
was_leak_dialog_shown_ = true; was_leak_dialog_shown_ = value;
} }
#endif #endif
......
...@@ -72,9 +72,10 @@ ...@@ -72,9 +72,10 @@
<h4>Password Form</h4> <h4>Password Form</h4>
<div> <div>
<form id="form3" action="https://example.com/" method="post"> <form id="form3" action="https://example.com/" method="post">
Username: <input type="text" id="username" name="username"><br> <div>Username: <input type="text" id="username" name="username"><div>
Password: <input type="password" id="password" name="password"><br> <div>Old password: <input type="password" id="old-password" name="old-password"></div>
Confirmation password: <input type="password" id="password-conf" name="password-conf"> <div>New password: <input type="password" id="new-password" name="new-password"></div>
<div>Confirmation password: <input type="password" id="password-conf" name="password-conf"></div>
</form> </form>
</div> </div>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment