Commit 96c1d191 authored by Ioana Pandele's avatar Ioana Pandele Committed by Commit Bot

Add explanation text to the password generation dialog

This is the same text that used to be displayed in the password generation
popup. It includes a link sending the user to the place in settings where
they can manage their saved passwords.

Bug: 835234
Change-Id: I7a072fe75323c813b43d20b1fdc545656dff789c
Reviewed-on: https://chromium-review.googlesource.com/1113920Reviewed-by: default avatarMaxim Kolosovskiy <kolos@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Commit-Queue: Ioana Pandele <ioanap@chromium.org>
Cr-Commit-Position: refs/heads/master@{#571510}
parent 5fa724b4
...@@ -14,5 +14,13 @@ ...@@ -14,5 +14,13 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/generated_password" android:id="@+id/generated_password"
android:textAppearance="@style/BlackHint1"/> android:textAppearance="@style/BlackHint1"
android:layout_marginBottom="20dp"/>
<org.chromium.ui.widget.TextViewWithClickableSpans
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/generation_save_explanation"
android:textAppearance="@style/BlackBody"
android:layout_marginBottom="20dp"/>
</LinearLayout> </LinearLayout>
\ No newline at end of file
...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.password_manager; ...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.password_manager;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.password_manager.PasswordGenerationDialogCoordinator.SaveExplanationText;
import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.base.WindowAndroid;
/** /**
...@@ -31,10 +32,13 @@ public class PasswordGenerationDialogBridge { ...@@ -31,10 +32,13 @@ public class PasswordGenerationDialogBridge {
} }
@CalledByNative @CalledByNative
public void showDialog(String generatedPassword) { public void showDialog(String generatedPassword, String explanationString, int linkRangeStart,
int linkRangeEnd) {
mGeneratedPassword = generatedPassword; mGeneratedPassword = generatedPassword;
mPasswordGenerationDialog.showDialog( mPasswordGenerationDialog.showDialog(generatedPassword,
generatedPassword, this::onPasswordAcceptedOrRejected); new SaveExplanationText(explanationString, linkRangeStart, linkRangeEnd,
(view) -> onSavedPasswordsLinkClicked()),
this::onPasswordAcceptedOrRejected);
} }
@CalledByNative @CalledByNative
...@@ -44,9 +48,7 @@ public class PasswordGenerationDialogBridge { ...@@ -44,9 +48,7 @@ public class PasswordGenerationDialogBridge {
} }
private void onPasswordAcceptedOrRejected(boolean accepted) { private void onPasswordAcceptedOrRejected(boolean accepted) {
if (mNativePasswordGenerationDialogViewAndroid == 0) { if (mNativePasswordGenerationDialogViewAndroid == 0) return;
return;
}
if (accepted) { if (accepted) {
nativePasswordAccepted(mNativePasswordGenerationDialogViewAndroid, mGeneratedPassword); nativePasswordAccepted(mNativePasswordGenerationDialogViewAndroid, mGeneratedPassword);
...@@ -56,7 +58,14 @@ public class PasswordGenerationDialogBridge { ...@@ -56,7 +58,14 @@ public class PasswordGenerationDialogBridge {
mPasswordGenerationDialog.dismissDialog(); mPasswordGenerationDialog.dismissDialog();
} }
private void onSavedPasswordsLinkClicked() {
if (mNativePasswordGenerationDialogViewAndroid == 0) return;
nativeOnSavedPasswordsLinkClicked(mNativePasswordGenerationDialogViewAndroid);
}
private native void nativePasswordAccepted( private native void nativePasswordAccepted(
long nativePasswordGenerationDialogViewAndroid, String generatedPassword); long nativePasswordGenerationDialogViewAndroid, String generatedPassword);
private native void nativePasswordRejected(long nativePasswordGenerationDialogViewAndroid); private native void nativePasswordRejected(long nativePasswordGenerationDialogViewAndroid);
private native void nativeOnSavedPasswordsLinkClicked(
long nativePasswordGenerationDialogViewAndroid);
} }
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package org.chromium.chrome.browser.password_manager; package org.chromium.chrome.browser.password_manager;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.view.View;
import org.chromium.base.Callback; import org.chromium.base.Callback;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
...@@ -19,16 +20,34 @@ public class PasswordGenerationDialogCoordinator { ...@@ -19,16 +20,34 @@ public class PasswordGenerationDialogCoordinator {
private final PasswordGenerationDialogModel mModel; private final PasswordGenerationDialogModel mModel;
private final PasswordGenerationDialogViewHolder mViewHolder; private final PasswordGenerationDialogViewHolder mViewHolder;
/**
* Wrapper class for all the elements needed to display the explanation text.
*/
public static class SaveExplanationText {
public final String mExplanationString;
public final int mLinkRangeStart;
public final int mLinkRangeEnd;
public final Callback<View> mOnLinkClickedCallback;
public SaveExplanationText(String explanationString, int linkRangeStart, int linkRangeEnd,
Callback<View> onLinkClickedCallback) {
mExplanationString = explanationString;
mLinkRangeStart = linkRangeStart;
mLinkRangeEnd = linkRangeEnd;
mOnLinkClickedCallback = onLinkClickedCallback;
}
}
public PasswordGenerationDialogCoordinator(@NonNull ChromeActivity activity) { public PasswordGenerationDialogCoordinator(@NonNull ChromeActivity activity) {
mModel = new PasswordGenerationDialogModel(); mModel = new PasswordGenerationDialogModel();
mViewHolder = new PasswordGenerationDialogViewHolder(activity); mViewHolder = new PasswordGenerationDialogViewHolder(activity);
mModalDialogManager = activity.getModalDialogManager(); mModalDialogManager = activity.getModalDialogManager();
} }
public void showDialog( public void showDialog(String generatedPassword, SaveExplanationText saveExplanationText,
String generatedPassword, Callback<Boolean> onPasswordAcceptedOrRejected) { Callback<Boolean> onPasswordAcceptedOrRejected) {
PasswordGenerationDialogMediator.initializeState( PasswordGenerationDialogMediator.initializeState(
mModel, generatedPassword, onPasswordAcceptedOrRejected); mModel, generatedPassword, saveExplanationText, onPasswordAcceptedOrRejected);
PasswordGenerationDialogViewBinder.bind(mModel, mViewHolder); PasswordGenerationDialogViewBinder.bind(mModel, mViewHolder);
mModalDialogManager.showDialog(mViewHolder.getView(), ModalDialogManager.APP_MODAL); mModalDialogManager.showDialog(mViewHolder.getView(), ModalDialogManager.APP_MODAL);
} }
......
...@@ -9,8 +9,10 @@ import org.chromium.base.Callback; ...@@ -9,8 +9,10 @@ import org.chromium.base.Callback;
/** Mediator class responsible for initializing the model state. */ /** Mediator class responsible for initializing the model state. */
public class PasswordGenerationDialogMediator { public class PasswordGenerationDialogMediator {
public static void initializeState(PasswordGenerationDialogModel model, String password, public static void initializeState(PasswordGenerationDialogModel model, String password,
PasswordGenerationDialogCoordinator.SaveExplanationText saveExplanationText,
Callback<Boolean> onPasswordAcceptedOrRejected) { Callback<Boolean> onPasswordAcceptedOrRejected) {
model.setValue(PasswordGenerationDialogModel.GENERATED_PASSWORD, password); model.setValue(PasswordGenerationDialogModel.GENERATED_PASSWORD, password);
model.setValue(PasswordGenerationDialogModel.SAVE_EXPLANATION_TEXT, saveExplanationText);
model.setValue(PasswordGenerationDialogModel.PASSWORD_ACTION_CALLBACK, model.setValue(PasswordGenerationDialogModel.PASSWORD_ACTION_CALLBACK,
onPasswordAcceptedOrRejected); onPasswordAcceptedOrRejected);
} }
......
...@@ -15,12 +15,16 @@ class PasswordGenerationDialogModel extends PropertyModel { ...@@ -15,12 +15,16 @@ class PasswordGenerationDialogModel extends PropertyModel {
/** The generated password to be displayed in the dialog. */ /** The generated password to be displayed in the dialog. */
public static final ObjectPropertyKey<String> GENERATED_PASSWORD = new ObjectPropertyKey<>(); public static final ObjectPropertyKey<String> GENERATED_PASSWORD = new ObjectPropertyKey<>();
/** Explanation text for how the generated password is saved. */
public static final ObjectPropertyKey<PasswordGenerationDialogCoordinator.SaveExplanationText>
SAVE_EXPLANATION_TEXT = new ObjectPropertyKey<>();
/** Callback invoked when the password is accepted or rejected by the user. */ /** Callback invoked when the password is accepted or rejected by the user. */
public static final ObjectPropertyKey<Callback<Boolean>> PASSWORD_ACTION_CALLBACK = public static final ObjectPropertyKey<Callback<Boolean>> PASSWORD_ACTION_CALLBACK =
new ObjectPropertyKey<>(); new ObjectPropertyKey<>();
/** Default constructor */ /** Default constructor */
public PasswordGenerationDialogModel() { public PasswordGenerationDialogModel() {
super(GENERATED_PASSWORD, PASSWORD_ACTION_CALLBACK); super(GENERATED_PASSWORD, SAVE_EXPLANATION_TEXT, PASSWORD_ACTION_CALLBACK);
} }
} }
...@@ -49,6 +49,8 @@ public class PasswordGenerationDialogViewBinder { ...@@ -49,6 +49,8 @@ public class PasswordGenerationDialogViewBinder {
model.getValue(PasswordGenerationDialogModel.PASSWORD_ACTION_CALLBACK))); model.getValue(PasswordGenerationDialogModel.PASSWORD_ACTION_CALLBACK)));
viewHolder.setGeneratedPassword( viewHolder.setGeneratedPassword(
model.getValue(PasswordGenerationDialogModel.GENERATED_PASSWORD)); model.getValue(PasswordGenerationDialogModel.GENERATED_PASSWORD));
viewHolder.setSaveExplanationText(
model.getValue(PasswordGenerationDialogModel.SAVE_EXPLANATION_TEXT));
viewHolder.initializeView(); viewHolder.initializeView();
} }
} }
...@@ -6,11 +6,17 @@ package org.chromium.chrome.browser.password_manager; ...@@ -6,11 +6,17 @@ package org.chromium.chrome.browser.password_manager;
import android.content.Context; import android.content.Context;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.widget.TextView; import android.widget.TextView;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.modaldialog.ModalDialogView; import org.chromium.chrome.browser.modaldialog.ModalDialogView;
import org.chromium.chrome.browser.password_manager.PasswordGenerationDialogCoordinator.SaveExplanationText;
import org.chromium.ui.text.NoUnderlineClickableSpan;
import org.chromium.ui.widget.TextViewWithClickableSpans;
/** Class holding a {@link ModalDialogView} that is lazily created after all the data is made /** Class holding a {@link ModalDialogView} that is lazily created after all the data is made
* available. * available.
...@@ -18,10 +24,12 @@ import org.chromium.chrome.browser.modaldialog.ModalDialogView; ...@@ -18,10 +24,12 @@ import org.chromium.chrome.browser.modaldialog.ModalDialogView;
public class PasswordGenerationDialogViewHolder { public class PasswordGenerationDialogViewHolder {
private ModalDialogView mView; private ModalDialogView mView;
private String mGeneratedPassword; private String mGeneratedPassword;
private SaveExplanationText mSaveExplanationText;
private Context mContext; private Context mContext;
private ModalDialogView.Controller mController; private ModalDialogView.Controller mController;
// TODO(ioanap): Change to a text label for now. // TODO(crbug.com/835234): Make the generated password editable.
private TextView mGeneratedPasswordText; private TextView mGeneratedPasswordTextView;
private TextViewWithClickableSpans mSaveExplantaionTextView;
public PasswordGenerationDialogViewHolder(Context context) { public PasswordGenerationDialogViewHolder(Context context) {
mContext = context; mContext = context;
...@@ -31,6 +39,10 @@ public class PasswordGenerationDialogViewHolder { ...@@ -31,6 +39,10 @@ public class PasswordGenerationDialogViewHolder {
mGeneratedPassword = generatedPassword; mGeneratedPassword = generatedPassword;
} }
public void setSaveExplanationText(SaveExplanationText saveExplanationText) {
mSaveExplanationText = saveExplanationText;
}
public void setController(ModalDialogView.Controller controller) { public void setController(ModalDialogView.Controller controller) {
mController = controller; mController = controller;
} }
...@@ -42,8 +54,18 @@ public class PasswordGenerationDialogViewHolder { ...@@ -42,8 +54,18 @@ public class PasswordGenerationDialogViewHolder {
params.negativeButtonTextId = R.string.password_generation_dialog_cancel_button; params.negativeButtonTextId = R.string.password_generation_dialog_cancel_button;
params.customView = params.customView =
LayoutInflater.from(mContext).inflate(R.layout.password_generation_dialog, null); LayoutInflater.from(mContext).inflate(R.layout.password_generation_dialog, null);
mGeneratedPasswordText = params.customView.findViewById(R.id.generated_password); mGeneratedPasswordTextView = params.customView.findViewById(R.id.generated_password);
mGeneratedPasswordText.setText(mGeneratedPassword); mGeneratedPasswordTextView.setText(mGeneratedPassword);
mSaveExplantaionTextView = params.customView.findViewById(R.id.generation_save_explanation);
SpannableString explanationSpan =
new SpannableString(mSaveExplanationText.mExplanationString);
explanationSpan.setSpan(
new NoUnderlineClickableSpan(mSaveExplanationText.mOnLinkClickedCallback),
mSaveExplanationText.mLinkRangeStart, mSaveExplanationText.mLinkRangeEnd,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mSaveExplantaionTextView.setText(explanationSpan);
mSaveExplantaionTextView.setMovementMethod(LinkMovementMethod.getInstance());
mView = new ModalDialogView(mController, params); mView = new ModalDialogView(mController, params);
} }
......
...@@ -1857,6 +1857,7 @@ chrome_test_java_sources = [ ...@@ -1857,6 +1857,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeUnitTest.java", "javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerDisableIncognitoModeUnitTest.java",
"javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageIntegrationTest.java",
"javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageUnitTest.java", "javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageUnitTest.java",
"javatests/src/org/chromium/chrome/browser/password_manager/PasswordGenerationDialogTest.java",
"javatests/src/org/chromium/chrome/browser/photo_picker/PhotoPickerDialogTest.java", "javatests/src/org/chromium/chrome/browser/photo_picker/PhotoPickerDialogTest.java",
"javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java", "javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java",
"javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java", "javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java",
......
// Copyright 2018 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 static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import android.support.test.filters.SmallTest;
import android.view.View;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.quality.Strictness;
import org.chromium.base.Callback;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class PasswordGenerationDialogTest {
private PasswordGenerationDialogCoordinator mDialog;
private String mGeneratedPassword = "generatedpassword";
private String mExplanationString = "This has a link.";
@Mock
private Callback<View> mExplanationTextLinkCallback;
@Mock
private Callback<Boolean> mOnPasswordAcceptedOrRejectedCallback;
@Rule
public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
new ChromeActivityTestRule<>(ChromeActivity.class);
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
@Before
public void setUp() throws InterruptedException {
mActivityTestRule.startMainActivityOnBlankPage();
mDialog = new PasswordGenerationDialogCoordinator(mActivityTestRule.getActivity());
ThreadUtils.runOnUiThreadBlocking(
() -> mDialog.showDialog(mGeneratedPassword,
new PasswordGenerationDialogCoordinator.SaveExplanationText(
mExplanationString, 12, 16, mExplanationTextLinkCallback),
mOnPasswordAcceptedOrRejectedCallback));
}
@Test
@SmallTest
public void testDialogSubviewsData() {
onView(withId(R.id.generated_password)).check(matches(withText(mGeneratedPassword)));
onView(withId(R.id.generation_save_explanation))
.check(matches(withText(mExplanationString)));
}
@Test
@SmallTest
public void testSavedPasswordsLinkCallback() {
onView(withId(R.id.generation_save_explanation)).perform(click());
verify(mExplanationTextLinkCallback).onResult(any());
}
@Test
@SmallTest
public void testAcceptedPasswordCallback() {
onView(withId(R.id.positive_button)).perform(click());
verify(mOnPasswordAcceptedOrRejectedCallback).onResult(true);
}
@Test
@SmallTest
public void testRejectedPasswordCallback() {
onView(withId(R.id.negative_button)).perform(click());
verify(mOnPasswordAcceptedOrRejectedCallback).onResult(false);
}
}
...@@ -6,9 +6,14 @@ ...@@ -6,9 +6,14 @@
#include "base/android/jni_android.h" #include "base/android/jni_android.h"
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/strings/string16.h"
#include "chrome/browser/password_manager/password_accessory_controller.h" #include "chrome/browser/password_manager/password_accessory_controller.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#include "jni/PasswordGenerationDialogBridge_jni.h" #include "jni/PasswordGenerationDialogBridge_jni.h"
#include "ui/android/window_android.h" #include "ui/android/window_android.h"
#include "ui/base/l10n/l10n_util.h"
PasswordGenerationDialogViewAndroid::PasswordGenerationDialogViewAndroid( PasswordGenerationDialogViewAndroid::PasswordGenerationDialogViewAndroid(
PasswordAccessoryController* controller) PasswordAccessoryController* controller)
...@@ -29,9 +34,17 @@ PasswordGenerationDialogViewAndroid::~PasswordGenerationDialogViewAndroid() { ...@@ -29,9 +34,17 @@ PasswordGenerationDialogViewAndroid::~PasswordGenerationDialogViewAndroid() {
void PasswordGenerationDialogViewAndroid::Show(base::string16& password) { void PasswordGenerationDialogViewAndroid::Show(base::string16& password) {
JNIEnv* env = base::android::AttachCurrentThread(); JNIEnv* env = base::android::AttachCurrentThread();
base::string16 link =
l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SMART_LOCK);
size_t offset = 0;
base::string16 explanation_text =
l10n_util::GetStringFUTF16(IDS_PASSWORD_GENERATION_PROMPT, link, &offset);
Java_PasswordGenerationDialogBridge_showDialog( Java_PasswordGenerationDialogBridge_showDialog(
env, java_object_, env, java_object_, base::android::ConvertUTF16ToJavaString(env, password),
base::android::ConvertUTF16ToJavaString(env, password)); base::android::ConvertUTF16ToJavaString(env, explanation_text), offset,
offset + link.length());
} }
void PasswordGenerationDialogViewAndroid::PasswordAccepted( void PasswordGenerationDialogViewAndroid::PasswordAccepted(
...@@ -49,6 +62,12 @@ void PasswordGenerationDialogViewAndroid::PasswordRejected( ...@@ -49,6 +62,12 @@ void PasswordGenerationDialogViewAndroid::PasswordRejected(
// mainly for metrics. // mainly for metrics.
} }
void PasswordGenerationDialogViewAndroid::OnSavedPasswordsLinkClicked(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) {
controller_->OnSavedPasswordsLinkClicked();
}
// static // static
std::unique_ptr<PasswordGenerationDialogViewInterface> std::unique_ptr<PasswordGenerationDialogViewInterface>
PasswordGenerationDialogViewInterface::Create( PasswordGenerationDialogViewInterface::Create(
......
...@@ -38,6 +38,11 @@ class PasswordGenerationDialogViewAndroid ...@@ -38,6 +38,11 @@ class PasswordGenerationDialogViewAndroid
void PasswordRejected(JNIEnv* env, void PasswordRejected(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj); const base::android::JavaParamRef<jobject>& obj);
// Called from Java via JNI.
void OnSavedPasswordsLinkClicked(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
private: private:
// The controller provides data for this view and owns it. // The controller provides data for this view and owns it.
PasswordAccessoryController* controller_; PasswordAccessoryController* controller_;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <vector> #include <vector>
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "chrome/browser/android/preferences/preferences_launcher.h"
#include "chrome/browser/password_manager/password_accessory_view_interface.h" #include "chrome/browser/password_manager/password_accessory_view_interface.h"
#include "chrome/browser/password_manager/password_generation_dialog_view_interface.h" #include "chrome/browser/password_manager/password_generation_dialog_view_interface.h"
#include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
...@@ -199,6 +200,10 @@ void PasswordAccessoryController::GeneratedPasswordRejected() { ...@@ -199,6 +200,10 @@ void PasswordAccessoryController::GeneratedPasswordRejected() {
dialog_view_.reset(); dialog_view_.reset();
} }
void PasswordAccessoryController::OnSavedPasswordsLinkClicked() {
chrome::android::PreferencesLauncher::ShowPasswordSettings();
}
gfx::NativeView PasswordAccessoryController::container_view() const { gfx::NativeView PasswordAccessoryController::container_view() const {
return web_contents_->GetNativeView(); return web_contents_->GetNativeView();
} }
......
...@@ -83,6 +83,10 @@ class PasswordAccessoryController ...@@ -83,6 +83,10 @@ class PasswordAccessoryController
// Called from the modal dialog if the user rejected the generated password. // Called from the modal dialog if the user rejected the generated password.
void GeneratedPasswordRejected(); void GeneratedPasswordRejected();
// Called from the modal dialog when the user taps on the link contained
// in the explanation text that leads to the saved passwords.
void OnSavedPasswordsLinkClicked();
// The web page view containing the focused field. // The web page view containing the focused field.
gfx::NativeView container_view() const; gfx::NativeView container_view() const;
......
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