Commit bd31d8e5 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

[PwdCheckAndroid] Load data into edit fragment

With this CL, the edit fragment retrieves the compromised credential
from the start argument and fills them into the form. It also ensures
that temporary destruction of the fragment keeps the password and the
credential data.

Screenshot in the bug.

Bug: 1114720, 1092444
Change-Id: I8a0fe9a47f56b0af38465babd29c93afd8f669b4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2352901
Commit-Queue: Friedrich [CET] <fhorschig@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798635}
parent 8c4380f2
...@@ -44,6 +44,7 @@ android_library("public_java") { ...@@ -44,6 +44,7 @@ android_library("public_java") {
"//third_party/android_deps:androidx_fragment_fragment_java", "//third_party/android_deps:androidx_fragment_fragment_java",
"//third_party/android_deps:androidx_preference_preference_java", "//third_party/android_deps:androidx_preference_preference_java",
"//third_party/android_deps:androidx_recyclerview_recyclerview_java", "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
"//third_party/android_deps:material_design_java",
] ]
sources = [ sources = [
"java/src/org/chromium/chrome/browser/password_check/PasswordCheck.java", "java/src/org/chromium/chrome/browser/password_check/PasswordCheck.java",
...@@ -94,6 +95,7 @@ android_library("test_java") { ...@@ -94,6 +95,7 @@ android_library("test_java") {
testonly = true testonly = true
sources = [ sources = [
"javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckEditViewTest.java",
"javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckIntegrationTest.java",
"javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java", "javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java",
] ]
...@@ -123,6 +125,7 @@ android_library("test_java") { ...@@ -123,6 +125,7 @@ android_library("test_java") {
"//third_party/android_deps:androidx_recyclerview_recyclerview_java", "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
"//third_party/android_deps:androidx_test_runner_java", "//third_party/android_deps:androidx_test_runner_java",
"//third_party/android_deps:espresso_java", "//third_party/android_deps:espresso_java",
"//third_party/android_sdk:android_test_base_java",
"//third_party/hamcrest:hamcrest_java", "//third_party/hamcrest:hamcrest_java",
"//third_party/junit", "//third_party/junit",
"//third_party/mockito:mockito_java", "//third_party/mockito:mockito_java",
......
...@@ -5,14 +5,19 @@ ...@@ -5,14 +5,19 @@
package org.chromium.chrome.browser.password_check; package org.chromium.chrome.browser.password_check;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.EditText;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
/** /**
...@@ -22,7 +27,13 @@ import androidx.preference.PreferenceFragmentCompat; ...@@ -22,7 +27,13 @@ import androidx.preference.PreferenceFragmentCompat;
*/ */
public class PasswordCheckEditFragmentView extends PreferenceFragmentCompat { public class PasswordCheckEditFragmentView extends PreferenceFragmentCompat {
public static final String EXTRA_COMPROMISED_CREDENTIAL = "extra_compromised_credential"; public static final String EXTRA_COMPROMISED_CREDENTIAL = "extra_compromised_credential";
private static final String EXTRA_NEW_PASSWORD = "extra_new_password"; @VisibleForTesting
static final String EXTRA_NEW_PASSWORD = "extra_new_password";
private String mNewPassword;
private CompromisedCredential mCredential;
private EditText mPasswordText;
@Override @Override
public void onCreatePreferences(Bundle bundle, String s) {} public void onCreatePreferences(Bundle bundle, String s) {}
...@@ -35,10 +46,73 @@ public class PasswordCheckEditFragmentView extends PreferenceFragmentCompat { ...@@ -35,10 +46,73 @@ public class PasswordCheckEditFragmentView extends PreferenceFragmentCompat {
return inflater.inflate(R.layout.password_check_edit_fragment, container, false); return inflater.inflate(R.layout.password_check_edit_fragment, container, false);
} }
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mCredential = getCredentialFromInstanceStateOrLaunchBundle(savedInstanceState);
mNewPassword = getNewPasswordFromInstanceStateOrLaunchBundle(savedInstanceState);
EditText siteText = (EditText) view.findViewById(R.id.site_edit);
siteText.setText(mCredential.getDisplayOrigin());
EditText usernameText = (EditText) view.findViewById(R.id.username_edit);
usernameText.setText(mCredential.getDisplayUsername());
mPasswordText = (EditText) view.findViewById(R.id.password_edit);
mPasswordText.setText(mCredential.getPassword());
mPasswordText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable editable) {
mNewPassword = mPasswordText.getText().toString();
if (TextUtils.isEmpty(mNewPassword)) {
// TODO(crbug.com/1114720): setError on R.id.password_label.
}
}
});
}
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear(); // Remove help and feedback for this screen. menu.clear(); // Remove help and feedback for this screen.
inflater.inflate(R.menu.password_check_editor_action_bar_menu, menu); inflater.inflate(R.menu.password_check_editor_action_bar_menu, menu);
// TODO(crbug.com/1092444): Make the back arrow an 'X'. // TODO(crbug.com/1092444): Make the back arrow an 'X'.
} }
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(EXTRA_COMPROMISED_CREDENTIAL, mCredential);
outState.putString(EXTRA_NEW_PASSWORD, mNewPassword);
}
private CompromisedCredential getCredentialFromInstanceStateOrLaunchBundle(
Bundle savedInstanceState) {
if (savedInstanceState != null
&& savedInstanceState.containsKey(EXTRA_COMPROMISED_CREDENTIAL)) {
return savedInstanceState.getParcelable(EXTRA_COMPROMISED_CREDENTIAL);
}
Bundle extras = getArguments();
assert extras != null
&& extras.containsKey(EXTRA_COMPROMISED_CREDENTIAL)
: "PasswordCheckEditFragmentView must be launched with a compromised credential "
+ "extra!";
return extras.getParcelable(EXTRA_COMPROMISED_CREDENTIAL);
}
private String getNewPasswordFromInstanceStateOrLaunchBundle(Bundle savedInstanceState) {
if (savedInstanceState != null && savedInstanceState.containsKey(EXTRA_NEW_PASSWORD)) {
return savedInstanceState.getParcelable(EXTRA_NEW_PASSWORD);
}
Bundle extras = getArguments();
if (extras != null && extras.containsKey(EXTRA_NEW_PASSWORD)) {
return extras.getParcelable(EXTRA_NEW_PASSWORD);
}
return mCredential.getPassword();
}
} }
// 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_check;
import static junit.framework.Assert.assertTrue;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.chromium.chrome.browser.password_check.PasswordCheckEditFragmentView.EXTRA_COMPROMISED_CREDENTIAL;
import static org.chromium.chrome.browser.password_check.PasswordCheckEditFragmentView.EXTRA_NEW_PASSWORD;
import static org.chromium.content_public.browser.test.util.CriteriaHelper.pollUiThread;
import static org.chromium.content_public.browser.test.util.TestThreadUtils.runOnUiThreadBlocking;
import android.os.Bundle;
import android.text.InputType;
import android.widget.EditText;
import androidx.test.filters.MediumTest;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.url.GURL;
/**
* View tests for the Password Check Edit screen only.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class PasswordCheckEditViewTest {
private static final CompromisedCredential ANA =
new CompromisedCredential("https://some-url.com/signin",
new GURL("https://some-url.com/"), "Ana", "some-url.com", "Ana", "password",
"https://some-url.com/.well-known/change-password", "", false, false);
private PasswordCheckEditFragmentView mPasswordCheckEditView;
@Rule
public SettingsActivityTestRule<PasswordCheckEditFragmentView> mTestRule =
new SettingsActivityTestRule<>(PasswordCheckEditFragmentView.class);
@Before
public void setUp() throws InterruptedException {
MockitoAnnotations.initMocks(this);
setUpUiLaunchedFromSettings();
}
@Test
@MediumTest
public void testLoadsCredential() {
pollUiThread(() -> mPasswordCheckEditView != null);
EditText origin = mPasswordCheckEditView.getView().findViewById(R.id.site_edit);
assertNotNull(origin);
assertNotNull(origin.getText());
assertNotNull(origin.getText().toString());
assertThat(origin.getText().toString(), equalTo(ANA.getDisplayOrigin()));
EditText username = mPasswordCheckEditView.getView().findViewById(R.id.username_edit);
assertNotNull(username);
assertNotNull(username.getText());
assertNotNull(username.getText().toString());
assertThat(username.getText().toString(), equalTo(ANA.getDisplayUsername()));
EditText password = mPasswordCheckEditView.getView().findViewById(R.id.password_edit);
assertNotNull(password);
assertNotNull(password.getText());
assertNotNull(password.getText().toString());
assertThat(password.getText().toString(), equalTo(ANA.getPassword()));
assertTrue((password.getInputType() & InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) != 0);
}
@Test
@MediumTest
public void testSavesCredentialAndChangedPasswordInBundle() {
pollUiThread(() -> mPasswordCheckEditView != null);
// Change the password.
final String newPassword = "NewPassword";
EditText password = mPasswordCheckEditView.getView().findViewById(R.id.password_edit);
assertNotNull(password);
runOnUiThreadBlocking(() -> password.setText(newPassword));
// Save state (e.g. like happening on destruction).
Bundle bundle = new Bundle();
mPasswordCheckEditView.onSaveInstanceState(bundle);
// Verify the data that reconstructs the page contains all updated information.
assertTrue(bundle.containsKey(EXTRA_COMPROMISED_CREDENTIAL));
assertTrue(bundle.containsKey(EXTRA_NEW_PASSWORD));
assertThat(bundle.getParcelable(EXTRA_COMPROMISED_CREDENTIAL), equalTo(ANA));
assertThat(bundle.getString(EXTRA_NEW_PASSWORD), equalTo(newPassword));
}
private void setUpUiLaunchedFromSettings() {
Bundle fragmentArgs = new Bundle();
fragmentArgs.putParcelable(EXTRA_COMPROMISED_CREDENTIAL, ANA);
mTestRule.startSettingsActivity(fragmentArgs);
mPasswordCheckEditView = mTestRule.getFragment();
}
}
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