chromium/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java

// Copyright 2015 The Chromium Authors
// 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.sync.ui;

import static org.chromium.components.sync.Passphrase.isExplicitPassphraseType;

import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.View;
import android.widget.CheckedTextView;

import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;

import org.chromium.chrome.R;
import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils;
import org.chromium.components.sync.PassphraseType;
import org.chromium.ui.text.SpanApplier;
import org.chromium.ui.text.SpanApplier.SpanInfo;
import org.chromium.ui.widget.TextViewWithClickableSpans;

/** Dialog to ask the user select what type of password to use for encryption. */
public class PassphraseTypeDialogFragment extends DialogFragment
        implements DialogInterface.OnClickListener {
    public interface Listener {
        /**
         * Called when the user doesn't have a custom passphrase and taps the option to set up one.
         * This is the only PassphraseType transition allowed by the dialog. Note the passphrase
         * itself hasn't been chosen yet.
         */
        void onChooseCustomPassphraseRequested();
    }

    /** This argument should contain a single value of type {@link PassphraseType}. */
    private static final String ARG_CURRENT_TYPE = "arg_current_type";

    private static final String ARG_IS_CUSTOM_PASSPHRASE_ALLOWED =
            "arg_is_custom_passphrase_allowed";

    public static PassphraseTypeDialogFragment create(
            @PassphraseType int currentType, boolean isCustomPassphraseAllowed) {
        assert currentType >= 0 && currentType <= PassphraseType.MAX_VALUE;
        PassphraseTypeDialogFragment dialog = new PassphraseTypeDialogFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_CURRENT_TYPE, currentType);
        args.putBoolean(ARG_IS_CUSTOM_PASSPHRASE_ALLOWED, isCustomPassphraseAllowed);
        dialog.setArguments(args);
        return dialog;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final View dialog =
                getActivity().getLayoutInflater().inflate(R.layout.sync_passphrase_types, null);

        final CheckedTextView explicitPassphraseCheckbox =
                dialog.findViewById(R.id.explicit_passphrase_checkbox);
        final CheckedTextView keystorePassphraseCheckbox =
                dialog.findViewById(R.id.keystore_passphrase_checkbox);
        final TextViewWithClickableSpans resetSyncLink = dialog.findViewById(R.id.reset_sync_link);

        if (isExplicitPassphraseType(getArguments().getInt(ARG_CURRENT_TYPE))) {
            explicitPassphraseCheckbox.setChecked(true);
            explicitPassphraseCheckbox.setEnabled(false);
            keystorePassphraseCheckbox.setEnabled(false);
            resetSyncLink.setMovementMethod(LinkMovementMethod.getInstance());
            resetSyncLink.setText(getResetSyncText());
        } else {
            keystorePassphraseCheckbox.setChecked(true);
            resetSyncLink.setVisibility(View.GONE);
            if (getArguments().getBoolean(ARG_IS_CUSTOM_PASSPHRASE_ALLOWED)) {
                explicitPassphraseCheckbox.setOnClickListener(
                        this::onCustomPassphraseCheckboxClicked);
            } else {
                explicitPassphraseCheckbox.setEnabled(false);
            }
        }

        return new AlertDialog.Builder(getActivity(), R.style.ThemeOverlay_BrowserUI_AlertDialog)
                .setNegativeButton(R.string.cancel, this)
                .setTitle(R.string.sync_passphrase_type_title)
                .setView(dialog)
                .create();
    }

    private SpannableString getResetSyncText() {
        return SpanApplier.applySpans(
                getString(R.string.sync_passphrase_encryption_reset_instructions),
                new SpanInfo(
                        "BEGIN_LINK",
                        "END_LINK",
                        new ClickableSpan() {
                            @Override
                            public void onClick(View view) {
                                SyncSettingsUtils.openSyncDashboard(getActivity());
                            }
                        }));
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (which == DialogInterface.BUTTON_NEGATIVE) {
            dismiss();
        }
    }

    private void onCustomPassphraseCheckboxClicked(View unused) {
        ((Listener) getTargetFragment()).onChooseCustomPassphraseRequested();
        dismiss();
    }
}