1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.chrome.browser.password_manager;
6 
7 import android.app.Activity;
8 import android.content.Context;
9 import android.content.DialogInterface;
10 import android.text.SpannableString;
11 import android.text.Spanned;
12 import android.text.method.LinkMovementMethod;
13 import android.text.style.ClickableSpan;
14 import android.view.LayoutInflater;
15 import android.view.View;
16 import android.widget.TextView;
17 
18 import androidx.appcompat.app.AlertDialog;
19 
20 import org.chromium.base.annotations.CalledByNative;
21 import org.chromium.base.annotations.NativeMethods;
22 import org.chromium.chrome.R;
23 import org.chromium.ui.base.WindowAndroid;
24 
25 /**
26  * The auto sign-in first run experience dialog is shown instead of usual auto sign-in snackbar
27  * when the user first encounters the auto sign-in feature.
28  */
29 public class AutoSigninFirstRunDialog
30         implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
31     private final Context mContext;
32     private final String mTitle;
33     private final String mExplanation;
34     private final int mExplanationLinkStart;
35     private final int mExplanationLinkEnd;
36     private final String mOkButtonText;
37     private final String mTurnOffButtonText;
38     private long mNativeAutoSigninFirstRunDialog;
39     private AlertDialog mDialog;
40     private boolean mWasDismissedByNative;
41 
AutoSigninFirstRunDialog(Context context, long nativeAutoSigninFirstRunDialog, String title, String explanation, int explanationLinkStart, int explanationLinkEnd, String okButtonText, String turnOffButtonText)42     private AutoSigninFirstRunDialog(Context context, long nativeAutoSigninFirstRunDialog,
43             String title, String explanation, int explanationLinkStart, int explanationLinkEnd,
44             String okButtonText, String turnOffButtonText) {
45         mNativeAutoSigninFirstRunDialog = nativeAutoSigninFirstRunDialog;
46         mContext = context;
47         mTitle = title;
48         mExplanation = explanation;
49         mExplanationLinkStart = explanationLinkStart;
50         mExplanationLinkEnd = explanationLinkEnd;
51         mOkButtonText = okButtonText;
52         mTurnOffButtonText = turnOffButtonText;
53     }
54 
55     @CalledByNative
createAndShowDialog(WindowAndroid windowAndroid, long nativeAutoSigninFirstRunDialog, String title, String explanation, int explanationLinkStart, int explanationLinkEnd, String okButtonText, String turnOffButtonText)56     private static AutoSigninFirstRunDialog createAndShowDialog(WindowAndroid windowAndroid,
57             long nativeAutoSigninFirstRunDialog, String title, String explanation,
58             int explanationLinkStart, int explanationLinkEnd, String okButtonText,
59             String turnOffButtonText) {
60         Activity activity = windowAndroid.getActivity().get();
61         if (activity == null) return null;
62 
63         AutoSigninFirstRunDialog dialog = new AutoSigninFirstRunDialog(activity,
64                 nativeAutoSigninFirstRunDialog, title, explanation, explanationLinkStart,
65                 explanationLinkEnd, okButtonText, turnOffButtonText);
66         dialog.show();
67         return dialog;
68     }
69 
show()70     private void show() {
71         final AlertDialog.Builder builder =
72                 new AlertDialog.Builder(mContext, R.style.Theme_Chromium_AlertDialog)
73                         .setTitle(mTitle)
74                         .setPositiveButton(mOkButtonText, this)
75                         .setNegativeButton(mTurnOffButtonText, this);
76         View view = LayoutInflater.from(mContext).inflate(
77                 R.layout.auto_sign_in_first_run_dialog, null);
78         TextView summaryView = (TextView) view.findViewById(R.id.summary);
79 
80         if (mExplanationLinkStart != mExplanationLinkEnd && mExplanationLinkEnd != 0) {
81             SpannableString spanableExplanation = new SpannableString(mExplanation);
82             spanableExplanation.setSpan(new ClickableSpan() {
83                 @Override
84                 public void onClick(View view) {
85                     AutoSigninFirstRunDialogJni.get().onLinkClicked(
86                             mNativeAutoSigninFirstRunDialog, AutoSigninFirstRunDialog.this);
87                     mDialog.dismiss();
88                 }
89             }, mExplanationLinkStart, mExplanationLinkEnd, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
90             summaryView.setText(spanableExplanation);
91             summaryView.setMovementMethod(LinkMovementMethod.getInstance());
92         } else {
93             summaryView.setText(mExplanation);
94             summaryView.setMovementMethod(LinkMovementMethod.getInstance());
95         }
96         builder.setView(view);
97 
98         mDialog = builder.create();
99         mDialog.setCanceledOnTouchOutside(false);
100         mDialog.setOnDismissListener(this);
101         mDialog.show();
102     }
103 
104     @Override
onClick(DialogInterface dialog, int whichButton)105     public void onClick(DialogInterface dialog, int whichButton) {
106         if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
107             AutoSigninFirstRunDialogJni.get().onTurnOffClicked(
108                     mNativeAutoSigninFirstRunDialog, AutoSigninFirstRunDialog.this);
109         } else if (whichButton == DialogInterface.BUTTON_POSITIVE) {
110             AutoSigninFirstRunDialogJni.get().onOkClicked(
111                     mNativeAutoSigninFirstRunDialog, AutoSigninFirstRunDialog.this);
112         }
113     }
114 
115     @Override
onDismiss(DialogInterface dialog)116     public void onDismiss(DialogInterface dialog) {
117         destroy();
118     }
119 
destroy()120     private void destroy() {
121         assert mNativeAutoSigninFirstRunDialog != 0;
122         AutoSigninFirstRunDialogJni.get().destroy(
123                 mNativeAutoSigninFirstRunDialog, AutoSigninFirstRunDialog.this);
124         mNativeAutoSigninFirstRunDialog = 0;
125         mDialog = null;
126     }
127 
128     @CalledByNative
dismissDialog()129     private void dismissDialog() {
130         assert !mWasDismissedByNative;
131         mWasDismissedByNative = true;
132         mDialog.dismiss();
133     }
134 
135     @NativeMethods
136     interface Natives {
onTurnOffClicked( long nativeAutoSigninFirstRunDialogAndroid, AutoSigninFirstRunDialog caller)137         void onTurnOffClicked(
138                 long nativeAutoSigninFirstRunDialogAndroid, AutoSigninFirstRunDialog caller);
onOkClicked( long nativeAutoSigninFirstRunDialogAndroid, AutoSigninFirstRunDialog caller)139         void onOkClicked(
140                 long nativeAutoSigninFirstRunDialogAndroid, AutoSigninFirstRunDialog caller);
destroy(long nativeAutoSigninFirstRunDialogAndroid, AutoSigninFirstRunDialog caller)141         void destroy(long nativeAutoSigninFirstRunDialogAndroid, AutoSigninFirstRunDialog caller);
onLinkClicked( long nativeAutoSigninFirstRunDialogAndroid, AutoSigninFirstRunDialog caller)142         void onLinkClicked(
143                 long nativeAutoSigninFirstRunDialogAndroid, AutoSigninFirstRunDialog caller);
144     }
145 }
146