// Copyright 2014 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.preferences.password;

import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.SearchView;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;

import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.Callback;
import org.chromium.base.ContentUriUtils;
import org.chromium.base.ContextUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference;
import org.chromium.chrome.browser.preferences.ChromeBasePreference;
import org.chromium.chrome.browser.preferences.ChromeSwitchPreference;
import org.chromium.chrome.browser.preferences.ManagedPreferenceDelegate;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.preferences.Preferences;
import org.chromium.chrome.browser.preferences.PreferencesLauncher;
import org.chromium.chrome.browser.preferences.TextMessagePreference;
import org.chromium.ui.text.SpanApplier;
import org.chromium.ui.widget.Toast;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

/**
 * The "Save passwords" screen in Settings, which allows the user to enable or disable password
 * saving, to view saved passwords (just the username and URL), and to delete saved passwords.
 */
public class SavePasswordsPreferences
        extends PreferenceFragment implements PasswordManagerHandler.PasswordListObserver,
                                              Preference.OnPreferenceClickListener {
    // ExportState describes at which state a password export is.
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({EXPORT_STATE_INACTIVE, EXPORT_STATE_REQUESTED, EXPORT_STATE_CONFIRMED})
    private @interface ExportState {}
    /**
     * EXPORT_STATE_INACTIVE: there is no currently running export. Either the user did not request
     * one, or the last one completed (i.e., a share intent picker or an error message were
     * displayed or the user cancelled it).
     */
    private static final int EXPORT_STATE_INACTIVE = 0;
    /**
     * EXPORT_STATE_REQUESTED: the user requested the export in the menu but did not authenticate
     * and confirm it yet.
     */
    private static final int EXPORT_STATE_REQUESTED = 1;
    /**
     * EXPORT_STATE_CONFIRMED: the user confirmed the export and Chrome is still busy preparing the
     * data for the share intent.
     */
    private static final int EXPORT_STATE_CONFIRMED = 2;

    // Keys for name/password dictionaries.
    public static final String PASSWORD_LIST_URL = "url";
    public static final String PASSWORD_LIST_NAME = "name";
    public static final String PASSWORD_LIST_PASSWORD = "password";

    // Used to pass the password id into a new activity.
    public static final String PASSWORD_LIST_ID = "id";

    // The key for saving |mSearchQuery| to instance bundle.
    private static final String SAVED_STATE_SEARCH_QUERY = "saved-state-search-query";

    // The key for saving |mExportState| to instance bundle.
    private static final String SAVED_STATE_EXPORT_STATE = "saved-state-export-state";

    // The key for saving |mExportFileUri| to instance bundle.
    private static final String SAVED_STATE_EXPORT_FILE_URI = "saved-state-export-file-uri";

    public static final String PREF_SAVE_PASSWORDS_SWITCH = "save_passwords_switch";
    public static final String PREF_AUTOSIGNIN_SWITCH = "autosignin_switch";

    // A PasswordEntryEditor receives a boolean value with this key. If set true, the the entry was
    // part of a search result.
    public static final String EXTRA_FOUND_VIA_SEARCH = "found_via_search_args";

    private static final String PREF_KEY_CATEGORY_SAVED_PASSWORDS = "saved_passwords";
    private static final String PREF_KEY_CATEGORY_EXCEPTIONS = "exceptions";
    private static final String PREF_KEY_MANAGE_ACCOUNT_LINK = "manage_account_link";
    private static final String PREF_KEY_SAVED_PASSWORDS_NO_TEXT = "saved_passwords_no_text";

    // Name of the feature controlling the password export functionality.
    private static final String EXPORT_PASSWORDS = "PasswordExport";

    // Name of the subdirectory in cache which stores the exported passwords file.
    private static final String PASSWORDS_CACHE_DIR = "/passwords";

    // Name of the histogram that records whether the user visiting the settings triggered the
    // search.
    private static final String HISTOGRAM_SEARCH_TRIGGERED =
            "PasswordManager.Android.PasswordSearchTriggered";

    // Potential values of the histogram recording the result of exporting. This needs to match
    // ExportPasswordsResult from
    // //components/password_manager/core/browser/password_manager_metrics_util.h.
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({EXPORT_RESULT_SUCCESS, EXPORT_RESULT_USER_ABORTED, EXPORT_RESULT_WRITE_FAILED,
            EXPORT_RESULT_NO_CONSUMER})
    @VisibleForTesting
    public @interface HistogramExportResult {}
    @VisibleForTesting
    public static final int EXPORT_RESULT_SUCCESS = 0;
    @VisibleForTesting
    public static final int EXPORT_RESULT_USER_ABORTED = 1;
    @VisibleForTesting
    public static final int EXPORT_RESULT_WRITE_FAILED = 2;
    @VisibleForTesting
    public static final int EXPORT_RESULT_NO_CONSUMER = 3;
    // If you add new values to HistogramExportResult, also update EXPORT_RESULT_COUNT to match its
    // new size.
    private static final int EXPORT_RESULT_COUNT = 4;

    private static final int ORDER_SWITCH = 0;
    private static final int ORDER_AUTO_SIGNIN_CHECKBOX = 1;
    private static final int ORDER_MANAGE_ACCOUNT_LINK = 2;
    private static final int ORDER_SAVED_PASSWORDS = 3;
    private static final int ORDER_EXCEPTIONS = 4;
    private static final int ORDER_SAVED_PASSWORDS_NO_TEXT = 5;

    private boolean mNoPasswords;
    private boolean mNoPasswordExceptions;

    @ExportState
    private int mExportState;

    // When the user requests that passwords are exported and once the passwords are sent over from
    // native code and stored in a cache file, this variable contains the content:// URI for that
    // cache file, or an empty URI if there was a problem with storing to that file. During all
    // other times, this variable is null. In particular, after the export is requested, the
    // variable being null means that the passwords have not arrived from the native code yet.
    @Nullable
    private Uri mExportFileUri;

    // Just before the exporting flow requests the passwords to be serialized by the native code,
    // this timestamp is assigned the result of System.currentTimeMillis().
    private Long mExportPreparationStart;

    private MenuItem mHelpItem;

    private String mSearchQuery;
    private Preference mLinkPref;
    private ChromeSwitchPreference mSavePasswordsSwitch;
    private ChromeBaseCheckBoxPreference mAutoSignInSwitch;
    private TextMessagePreference mEmptyView;
    private boolean mSearchRecorded;
    private Menu mMenuForTesting;

    // Contains the reference to the progress-bar dialog after the user confirms the password
    // export and before the serialized passwords arrive, so that the dialog can be dismissed on the
    // passwords' arrival. It is null during all other times.
    @Nullable
    private ProgressBarDialogFragment mProgressBarDialogFragment;

    // If an error dialog should be shown, this contains the arguments for it, such as the error
    // message. If no error dialog should be shown, this is null.
    @Nullable
    private ExportErrorDialogFragment.ErrorDialogParams mErrorDialogParams;

    // Contains the reference to the export warning dialog when it is displayed, so that the dialog
    // can be dismissed if Chrome goes to background (without being killed) and is restored too late
    // for the reauthentication time window to still allow exporting. It is null during all other
    // times.
    private ExportWarningDialogFragment mExportWarningDialogFragment;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getActivity().setTitle(R.string.prefs_saved_passwords);
        setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity()));
        PasswordManagerHandlerProvider.getInstance().addObserver(this);

        setHasOptionsMenu(providesPasswordExport() || providesPasswordSearch());

        if (savedInstanceState == null) return;

        if (savedInstanceState.containsKey(SAVED_STATE_EXPORT_STATE)) {
            mExportState = savedInstanceState.getInt(SAVED_STATE_EXPORT_STATE);
            if (mExportState == EXPORT_STATE_CONFIRMED) {
                // If export is underway, ensure that the UI is updated.
                tryExporting();
            }
        }
        if (savedInstanceState.containsKey(SAVED_STATE_EXPORT_FILE_URI)) {
            String uriString = savedInstanceState.getString(SAVED_STATE_EXPORT_FILE_URI);
            if (uriString.isEmpty()) {
                mExportFileUri = Uri.EMPTY;
            } else {
                mExportFileUri = Uri.parse(uriString);
            }
        }
        if (savedInstanceState.containsKey(SAVED_STATE_SEARCH_QUERY)) {
            mSearchQuery = savedInstanceState.getString(SAVED_STATE_SEARCH_QUERY);
            mSearchRecorded = mSearchQuery != null; // We record a search when a query is set.
        }
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.clear();
        mMenuForTesting = menu;
        inflater.inflate(R.menu.save_password_preferences_action_bar_menu, menu);
        menu.findItem(R.id.export_passwords).setVisible(providesPasswordExport());
        menu.findItem(R.id.export_passwords).setEnabled(false);
        MenuItem searchItem = menu.findItem(R.id.menu_id_search);
        searchItem.setVisible(providesPasswordSearch());
        if (providesPasswordSearch()) {
            mHelpItem = menu.findItem(R.id.menu_id_general_help);
            setUpSearchAction(searchItem);
        }
    }

    /**
     * Prepares the searchItem's icon and searchView. Sets up listeners to clicks and interactions
     * with the searchItem or its searchView.
     * @param searchItem the item containing the SearchView. Must not be null.
     */
    private void setUpSearchAction(MenuItem searchItem) {
        SearchView searchView = (SearchView) searchItem.getActionView();
        searchView.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
        searchItem.setIcon(convertToPlainWhite(searchItem.getIcon()));
        if (mSearchQuery != null) { // If a query was recovered, restore the search view.
            searchItem.expandActionView();
            searchView.setIconified(false);
            searchView.setQuery(mSearchQuery, false);
        }
        searchItem.setOnMenuItemClickListener((MenuItem m) -> {
            filterPasswords("");
            return false; // Continue with the default action.
        });
        searchView.findViewById(R.id.search_close_btn).setOnClickListener((View v) -> {
            searchView.setQuery(null, false);
            searchView.setIconified(true);
            filterPasswords(null); // Reset filter to bring back all preferences.
        });
        searchView.setOnSearchClickListener(view -> filterPasswords(""));
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return true; // Continue with default action - nothing.
            }

            @Override
            public boolean onQueryTextChange(String query) {
                maybeRecordTriggeredPasswordSearch(true);
                return filterPasswords(query);
            }
        });
    }

    /**
     * Record the search only, if the feature is enabled and it hasn't been recorded for this
     * instance of the view.
     * @param searchTriggered Whether to log a triggered search or no triggered search.
     */
    private void maybeRecordTriggeredPasswordSearch(boolean searchTriggered) {
        if (providesPasswordSearch() && !mSearchRecorded) {
            mSearchRecorded = true;
            RecordHistogram.recordBooleanHistogram(HISTOGRAM_SEARCH_TRIGGERED, searchTriggered);
        }
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        menu.findItem(R.id.export_passwords)
                .setEnabled(!mNoPasswords && mExportState == EXPORT_STATE_INACTIVE);
        super.onPrepareOptionsMenu(menu);
    }

    // An encapsulation of a URI and an error string, used by the processing in
    // exportPasswordsIntoFile.
    private static class ExportResult {
        public final Uri mUri;
        @Nullable
        public final String mError;

        // Constructs the successful result: a valid URI and no error.
        public ExportResult(Uri uri) {
            assert uri != null && uri != Uri.EMPTY;
            mUri = uri;
            mError = null;
        }

        // Constructs the failed result: an empty URI and a non-empty error string.
        public ExportResult(String error) {
            assert !TextUtils.isEmpty(error);
            mUri = Uri.EMPTY;
            mError = error;
        }
    }

    /**
     * A helper method which first fires an AsyncTask to turn the string with serialized passwords
     * into a cache file with a shareable URI, and then, depending on success, either calls the code
     * for firing the share intent or displays an error.
     * @param serializedPasswords A string with a CSV representation of the user's passwords.
     */
    private void shareSerializedPasswords(byte[] serializedPasswords) {
        AsyncTask<byte[], Void, ExportResult> task = new AsyncTask<byte[], Void, ExportResult>() {
            @Override
            protected ExportResult doInBackground(byte[]... serializedPasswords) {
                assert serializedPasswords.length == 1;
                // Record the time it took to read and serialise the passwords. This excludes the
                // time to write them into a file, to be consistent with desktop (where writing is
                // blocked on the user choosing a file destination).
                RecordHistogram.recordMediumTimesHistogram(
                        "PasswordManager.TimeReadingExportedPasswords",
                        System.currentTimeMillis() - mExportPreparationStart,
                        TimeUnit.MILLISECONDS);
                return exportPasswordsIntoFile(serializedPasswords[0]);
            }

            @Override
            protected void onPostExecute(ExportResult result) {
                // Don't display any UI if the user cancelled the export in the meantime.
                if (mExportState == EXPORT_STATE_INACTIVE) return;

                if (result.mError != null) {
                    showExportErrorAndAbort(R.string.save_password_preferences_export_tips,
                            result.mError, R.string.try_again, EXPORT_RESULT_WRITE_FAILED);
                } else {
                    mExportFileUri = result.mUri;
                    tryExporting();
                }
            }
        };
        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, serializedPasswords);
    }

    /** Starts the password export flow.
     * Current state of export flow: the user just tapped the menu item for export
     * The next steps are: passing reauthentication, confirming the export, waiting for exported
     * data (if needed) and choosing a consumer app for the data.
     */
    private void startExporting() {
        assert mExportState == EXPORT_STATE_INACTIVE;
        // Disable re-triggering exporting until the current exporting finishes.
        mExportState = EXPORT_STATE_REQUESTED;

        // Start fetching the serialized passwords now to use the time the user spends
        // reauthenticating and reading the warning message. If the user cancels the export or
        // fails the reauthentication, the serialised passwords will simply get ignored when
        // they arrive.
        mExportPreparationStart = System.currentTimeMillis();
        PasswordManagerHandlerProvider.getInstance().getPasswordManagerHandler().serializePasswords(
                new Callback<byte[]>() {
                    @Override
                    public void onResult(byte[] serializedPasswords) {
                        shareSerializedPasswords(serializedPasswords);
                    }
                });
        if (!ReauthenticationManager.isScreenLockSetUp(getActivity().getApplicationContext())) {
            Toast.makeText(getActivity().getApplicationContext(),
                         R.string.password_export_set_lock_screen, Toast.LENGTH_LONG)
                    .show();
            // Re-enable exporting, the current one was cancelled by Chrome.
            mExportState = EXPORT_STATE_INACTIVE;
        } else if (ReauthenticationManager.authenticationStillValid(
                           ReauthenticationManager.REAUTH_SCOPE_BULK)) {
            exportAfterReauth();
        } else {
            ReauthenticationManager.displayReauthenticationFragment(
                    R.string.lockscreen_description_export, getView().getId(), getFragmentManager(),
                    ReauthenticationManager.REAUTH_SCOPE_BULK);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.export_passwords) {
            startExporting();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Continues with the password export flow after the user successfully reauthenticated.
     * Current state of export flow: the user tapped the menu item for export and passed
     * reauthentication. The next steps are: confirming the export, waiting for exported data (if
     * needed) and choosing a consumer app for the data.
     */
    private void exportAfterReauth() {
        assert mExportWarningDialogFragment == null;
        mExportWarningDialogFragment = new ExportWarningDialogFragment();
        mExportWarningDialogFragment.setExportWarningHandler(
                new ExportWarningDialogFragment.Handler() {
                    /**
                     * On positive button response asks the parent to continue with the export flow.
                     */
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        if (which == AlertDialog.BUTTON_POSITIVE) {
                            mExportState = EXPORT_STATE_CONFIRMED;
                            // If the error dialog has been waiting, display it now, otherwise
                            // continue the export flow.
                            if (mErrorDialogParams != null) {
                                showExportErrorDialogFragment();
                            } else {
                                tryExporting();
                            }
                        } else if (which == AlertDialog.BUTTON_NEGATIVE) {
                            RecordHistogram.recordEnumeratedHistogram(
                                    "PasswordManager.ExportPasswordsToCSVResult",
                                    EXPORT_RESULT_USER_ABORTED, EXPORT_RESULT_COUNT);
                        }
                    }

                    /**
                     * Mark the dismissal of the dialog, so that waiting UI (such as error
                     * reporting) can be shown.
                     */
                    @Override
                    public void onDismiss() {
                        // Unless the positive button action moved the exporting state forward,
                        // cancel the export. This happens both when the user taps the negative
                        // button or when they tap outside of the dialog to dismiss it.
                        if (mExportState != EXPORT_STATE_CONFIRMED) {
                            mExportState = EXPORT_STATE_INACTIVE;
                        }

                        mExportWarningDialogFragment = null;
                        // If the error dialog has been waiting, display it now.
                        if (mErrorDialogParams != null) showExportErrorDialogFragment();
                    }
                });
        mExportWarningDialogFragment.show(getFragmentManager(), null);
    }

    /**
     * Starts the exporting intent if both blocking events are completed: serializing and the
     * confirmation flow.
     * At this point, the user the user has tapped the menu item for export and passed
     * reauthentication. Upon calling this method, the user has either also confirmed the export, or
     * the exported data have been prepared. The method is called twice, once for each of those
     * events. The next step after both the export is confirmed and the data is ready is to offer
     * the user an intent chooser for sharing the exported passwords.
     */
    private void tryExporting() {
        if (mExportState != EXPORT_STATE_CONFIRMED) return;
        if (mExportFileUri == null) {
            // The serialization has not finished. Until this finishes, a progress bar is
            // displayed with an option to cancel the export.
            assert mProgressBarDialogFragment == null;
            mProgressBarDialogFragment = new ProgressBarDialogFragment();
            mProgressBarDialogFragment.setCancelProgressHandler(
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            if (which == AlertDialog.BUTTON_NEGATIVE) {
                                mExportState = EXPORT_STATE_INACTIVE;
                                RecordHistogram.recordEnumeratedHistogram(
                                        "PasswordManager.ExportPasswordsToCSVResult",
                                        EXPORT_RESULT_USER_ABORTED, EXPORT_RESULT_COUNT);
                            }
                        }
                    });
            mProgressBarDialogFragment.show(getFragmentManager(), null);
        } else {
            // Note: if the serialization is quicker than the user interacting with the
            // confirmation dialog, then there is no progress bar shown.
            if (mProgressBarDialogFragment != null) mProgressBarDialogFragment.dismiss();
            sendExportIntent();
        }
    }

    /**
     * Call this to abort the export UI flow and display an error description to the user.
     * @param descriptionId The resource ID of a string with a brief explanation of the error.
     * @param detailedDescription An optional string with more technical details about the error.
     * @param positiveButtonLabelId The resource ID of the label of the positive button in the error
     * dialog.
     */
    @VisibleForTesting
    public void showExportErrorAndAbort(int descriptionId, @Nullable String detailedDescription,
            int positiveButtonLabelId, @HistogramExportResult int histogramExportResult) {
        assert mErrorDialogParams == null;
        if (mProgressBarDialogFragment != null) mProgressBarDialogFragment.dismiss();

        RecordHistogram.recordEnumeratedHistogram("PasswordManager.ExportPasswordsToCSVResult",
                histogramExportResult, EXPORT_RESULT_COUNT);

        mErrorDialogParams = new ExportErrorDialogFragment.ErrorDialogParams();
        mErrorDialogParams.positiveButtonLabelId = positiveButtonLabelId;
        mErrorDialogParams.description = getActivity().getResources().getString(descriptionId);

        if (detailedDescription != null) {
            mErrorDialogParams.detailedDescription = getActivity().getResources().getString(
                    R.string.save_password_preferences_export_error_details, detailedDescription);
        }

        if (mExportWarningDialogFragment == null) showExportErrorDialogFragment();
    }

    /**
     * This is a helper method to {@link showExportErrorAndAbort}, responsible for showing the
     * actual UI.*/
    private void showExportErrorDialogFragment() {
        assert mErrorDialogParams != null;

        ExportErrorDialogFragment exportErrorDialogFragment = new ExportErrorDialogFragment();
        int positiveButtonLabelId = mErrorDialogParams.positiveButtonLabelId;
        exportErrorDialogFragment.initialize(mErrorDialogParams);
        mErrorDialogParams = null;

        exportErrorDialogFragment.setExportErrorHandler(new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (which == AlertDialog.BUTTON_POSITIVE) {
                    if (positiveButtonLabelId
                            == R.string.save_password_preferences_export_learn_google_drive) {
                        // Link to the help article about how to use Google Drive.
                        Intent intent = new Intent(Intent.ACTION_VIEW,
                                Uri.parse("https://support.google.com/drive/answer/2424384"));
                        intent.setPackage(getActivity().getPackageName());
                        getActivity().startActivity(intent);
                    } else if (positiveButtonLabelId == R.string.try_again) {
                        mExportState = EXPORT_STATE_INACTIVE;
                        startExporting();
                    }
                } else if (which == AlertDialog.BUTTON_NEGATIVE) {
                    // Re-enable exporting, the current one was just cancelled.
                    mExportState = EXPORT_STATE_INACTIVE;
                }
            }
        });
        exportErrorDialogFragment.show(getFragmentManager(), null);
    }

    /**
     * This method saves the contents of |serializedPasswords| into a temporary file and returns a
     * sharing URI for it. In case of failure, returns EMPTY. It should only be run on the
     * background thread of an AsyncTask, because it does I/O operations.
     * @param serializedPasswords A byte array with serialized passwords in CSV format
     */
    private ExportResult exportPasswordsIntoFile(byte[] serializedPasswords) {
        // First ensure that the PASSWORDS_CACHE_DIR cache directory exists.
        File passwordsDir =
                new File(ContextUtils.getApplicationContext().getCacheDir() + PASSWORDS_CACHE_DIR);
        passwordsDir.mkdir();
        // Now create or overwrite the temporary file for exported passwords there and return its
        // content:// URI.
        File tempFile;
        try {
            tempFile = File.createTempFile("pwd-export", ".csv", passwordsDir);
        } catch (IOException e) {
            return new ExportResult(e.getMessage());
        }
        tempFile.deleteOnExit();
        try (BufferedOutputStream outputStream =
                        new BufferedOutputStream(new FileOutputStream(tempFile))) {
            outputStream.write(serializedPasswords);
        } catch (IOException e) {
            return new ExportResult(e.getMessage());
        }
        try {
            return new ExportResult(ContentUriUtils.getContentUriFromFile(tempFile));
        } catch (IllegalArgumentException e) {
            return new ExportResult(e.getMessage());
        }
    }

    /**
     * If the URI of the file with exported passwords is not null, passes it into an implicit
     * intent, so that the user can use a storage app to save the exported passwords.
     */
    private void sendExportIntent() {
        assert mExportState == EXPORT_STATE_CONFIRMED;
        mExportState = EXPORT_STATE_INACTIVE;

        if (mExportFileUri == Uri.EMPTY) return;

        Intent send = new Intent(Intent.ACTION_SEND);
        send.setType("text/csv");
        send.putExtra(Intent.EXTRA_STREAM, mExportFileUri);
        send.putExtra(
                Intent.EXTRA_SUBJECT, getString(R.string.save_password_preferences_export_subject));

        try {
            Intent chooser = Intent.createChooser(send, null);
            chooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            ContextUtils.getApplicationContext().startActivity(chooser);
            RecordHistogram.recordEnumeratedHistogram("PasswordManager.ExportPasswordsToCSVResult",
                    EXPORT_RESULT_SUCCESS, EXPORT_RESULT_COUNT);
        } catch (ActivityNotFoundException e) {
            showExportErrorAndAbort(R.string.save_password_preferences_export_no_app, null,
                    R.string.save_password_preferences_export_learn_google_drive,
                    EXPORT_RESULT_NO_CONSUMER);
        }
        mExportFileUri = null;
    }

    private boolean filterPasswords(String query) {
        mSearchQuery = query;
        // Hide the help option. It's not useful during search but might be clicked by accident.
        mHelpItem.setShowAsAction(mSearchQuery == null ? MenuItem.SHOW_AS_ACTION_NEVER
                                                       : MenuItem.SHOW_AS_ACTION_IF_ROOM);
        rebuildPasswordLists();
        return false; // Query has been handled. Don't trigger default action of SearchView.
    }

    /**
     * Empty screen message when no passwords or exceptions are stored.
     */
    private void displayEmptyScreenMessage() {
        mEmptyView = new TextMessagePreference(getActivity(), null);
        mEmptyView.setSummary(R.string.saved_passwords_none_text);
        mEmptyView.setKey(PREF_KEY_SAVED_PASSWORDS_NO_TEXT);
        mEmptyView.setOrder(ORDER_SAVED_PASSWORDS_NO_TEXT);
        getPreferenceScreen().addPreference(mEmptyView);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        ReauthenticationManager.resetLastReauth();
    }

    void rebuildPasswordLists() {
        mNoPasswords = false;
        mNoPasswordExceptions = false;
        getPreferenceScreen().removeAll();
        createSavePasswordsSwitch();
        createAutoSignInCheckbox();
        PasswordManagerHandlerProvider.getInstance()
                .getPasswordManagerHandler()
                .updatePasswordLists();
    }

    /**
     * Removes the UI displaying the list of saved passwords or exceptions.
     * @param preferenceCategoryKey The key string identifying the PreferenceCategory to be removed.
     */
    private void resetList(String preferenceCategoryKey) {
        PreferenceCategory profileCategory =
                (PreferenceCategory) getPreferenceScreen().findPreference(preferenceCategoryKey);
        if (profileCategory != null) {
            profileCategory.removeAll();
            getPreferenceScreen().removePreference(profileCategory);
        }
    }

    /**
     * Removes the message informing the user that there are no saved entries to display.
     */
    private void resetNoEntriesTextMessage() {
        Preference message = getPreferenceScreen().findPreference(PREF_KEY_SAVED_PASSWORDS_NO_TEXT);
        if (message != null) {
            getPreferenceScreen().removePreference(message);
        }
    }

    @Override
    public void passwordListAvailable(int count) {
        resetList(PREF_KEY_CATEGORY_SAVED_PASSWORDS);
        resetNoEntriesTextMessage();

        mNoPasswords = count == 0;
        if (mNoPasswords) {
            if (mNoPasswordExceptions) displayEmptyScreenMessage();
            return;
        }

        displayManageAccountLink();

        PreferenceGroup passwordParent;
        if (mSearchQuery == null) {
            PreferenceCategory profileCategory = new PreferenceCategory(getActivity());
            profileCategory.setKey(PREF_KEY_CATEGORY_SAVED_PASSWORDS);
            profileCategory.setTitle(R.string.section_saved_passwords);
            profileCategory.setOrder(ORDER_SAVED_PASSWORDS);
            getPreferenceScreen().addPreference(profileCategory);
            passwordParent = profileCategory;
        } else {
            passwordParent = getPreferenceScreen();
        }
        for (int i = 0; i < count; i++) {
            SavedPasswordEntry saved = PasswordManagerHandlerProvider.getInstance()
                                               .getPasswordManagerHandler()
                                               .getSavedPasswordEntry(i);
            String url = saved.getUrl();
            String name = saved.getUserName();
            String password = saved.getPassword();
            if (shouldBeFiltered(url, name)) {
                continue; // The current password won't show with the active filter, try the next.
            }
            PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getActivity());
            screen.setTitle(url);
            screen.setOnPreferenceClickListener(this);
            screen.setSummary(name);
            Bundle args = screen.getExtras();
            args.putString(PASSWORD_LIST_NAME, name);
            args.putString(PASSWORD_LIST_URL, url);
            args.putString(PASSWORD_LIST_PASSWORD, password);
            args.putInt(PASSWORD_LIST_ID, i);
            passwordParent.addPreference(screen);
        }
        mNoPasswords = passwordParent.getPreferenceCount() == 0;
        if (mNoPasswords) {
            if (count == 0) displayEmptyScreenMessage(); // Show if the list was already empty.
            if (mSearchQuery == null) {
                // If not searching, the category needs to be removed again.
                getPreferenceScreen().removePreference(passwordParent);
            }
        }
    }

    /**
     * Returns true if there is a search query that requires the exclusion of an entry based on
     * the passed url or name.
     * @param url the visible URL of the entry to check. May be empty but must not be null.
     * @param name the visible user name of the entry to check. May be empty but must not be null.
     * @return Returns whether the entry with the passed url and name should be filtered.
     */
    private boolean shouldBeFiltered(final String url, final String name) {
        if (mSearchQuery == null) {
            return false;
        }
        return !url.toLowerCase(Locale.ENGLISH).contains(mSearchQuery.toLowerCase(Locale.ENGLISH))
                && !name.toLowerCase(Locale.getDefault())
                            .contains(mSearchQuery.toLowerCase(Locale.getDefault()));
    }

    @Override
    public void passwordExceptionListAvailable(int count) {
        if (mSearchQuery != null) return; // Don't show exceptions if a search is ongoing.
        resetList(PREF_KEY_CATEGORY_EXCEPTIONS);
        resetNoEntriesTextMessage();

        mNoPasswordExceptions = count == 0;
        if (mNoPasswordExceptions) {
            if (mNoPasswords) displayEmptyScreenMessage();
            return;
        }

        displayManageAccountLink();

        PreferenceCategory profileCategory = new PreferenceCategory(getActivity());
        profileCategory.setKey(PREF_KEY_CATEGORY_EXCEPTIONS);
        profileCategory.setTitle(R.string.section_saved_passwords_exceptions);
        profileCategory.setOrder(ORDER_EXCEPTIONS);
        getPreferenceScreen().addPreference(profileCategory);
        for (int i = 0; i < count; i++) {
            String exception = PasswordManagerHandlerProvider.getInstance()
                                       .getPasswordManagerHandler()
                                       .getSavedPasswordException(i);
            PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getActivity());
            screen.setTitle(exception);
            screen.setOnPreferenceClickListener(this);
            Bundle args = screen.getExtras();
            args.putString(PASSWORD_LIST_URL, exception);
            args.putInt(PASSWORD_LIST_ID, i);
            profileCategory.addPreference(screen);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mExportState == EXPORT_STATE_REQUESTED) {
            // If Chrome returns to foreground from being paused (but without being killed), and
            // exportAfterReauth was called before pausing, the warning dialog is still
            // displayed and ready to be used, and this is indicated by
            // |mExportWarningDialogFragment| being non-null.
            if (ReauthenticationManager.authenticationStillValid(
                        ReauthenticationManager.REAUTH_SCOPE_BULK)) {
                if (mExportWarningDialogFragment == null) exportAfterReauth();
            } else {
                if (mExportWarningDialogFragment != null) mExportWarningDialogFragment.dismiss();
                RecordHistogram.recordEnumeratedHistogram(
                        "PasswordManager.ExportPasswordsToCSVResult", EXPORT_RESULT_USER_ABORTED,
                        EXPORT_RESULT_COUNT);
                mExportState = EXPORT_STATE_INACTIVE;
            }
        }
        rebuildPasswordLists();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(SAVED_STATE_EXPORT_STATE, mExportState);
        if (mExportFileUri != null) {
            outState.putString(SAVED_STATE_EXPORT_FILE_URI, mExportFileUri.toString());
        }
        if (mSearchQuery != null) {
            outState.putString(SAVED_STATE_SEARCH_QUERY, mSearchQuery);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        maybeRecordTriggeredPasswordSearch(false);
        PasswordManagerHandlerProvider.getInstance().removeObserver(this);
    }

    /**
     *  Preference was clicked. Either navigate to manage account site or launch the PasswordEditor
     *  depending on which preference it was.
     */
    @Override
    public boolean onPreferenceClick(Preference preference) {
        if (preference == mLinkPref) {
            Intent intent = new Intent(
                    Intent.ACTION_VIEW, Uri.parse(PasswordUIView.getAccountDashboardURL()));
            intent.setPackage(getActivity().getPackageName());
            getActivity().startActivity(intent);
        } else {
            // Launch preference activity with PasswordEntryEditor fragment with
            // intent extras specifying the object.
            Intent intent = PreferencesLauncher.createIntentForSettingsPage(
                    getActivity(), PasswordEntryEditor.class.getName());
            intent.putExtra(Preferences.EXTRA_SHOW_FRAGMENT_ARGUMENTS, preference.getExtras());
            intent.putExtra(SavePasswordsPreferences.EXTRA_FOUND_VIA_SEARCH, mSearchQuery != null);
            startActivity(intent);
        }
        return true;
    }

    /**
     * Convert a given icon to a plain white version by applying the MATRIX_TRANSFORM_TO_WHITE color
     * filter. The resulting drawable will be brighter than a usual grayscale conversion.
     *
     * For grayscale conversion, use the function ColorMatrix#setSaturation(0) instead.
     * @param icon The drawable to be converted.
     * @return Returns the bright white version of the passed drawable.
     */
    private static Drawable convertToPlainWhite(Drawable icon) {
        icon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
        return icon;
    }

    private void createSavePasswordsSwitch() {
        if (mSearchQuery != null) {
            return; // Don't create this option when the preferences are filtered for passwords.
        }
        mSavePasswordsSwitch = new ChromeSwitchPreference(getActivity(), null);
        mSavePasswordsSwitch.setKey(PREF_SAVE_PASSWORDS_SWITCH);
        mSavePasswordsSwitch.setTitle(R.string.prefs_saved_passwords);
        mSavePasswordsSwitch.setOrder(ORDER_SWITCH);
        mSavePasswordsSwitch.setSummaryOn(R.string.text_on);
        mSavePasswordsSwitch.setSummaryOff(R.string.text_off);
        mSavePasswordsSwitch.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                PrefServiceBridge.getInstance().setRememberPasswordsEnabled((boolean) newValue);
                return true;
            }
        });
        mSavePasswordsSwitch.setManagedPreferenceDelegate(new ManagedPreferenceDelegate() {
            @Override
            public boolean isPreferenceControlledByPolicy(Preference preference) {
                return PrefServiceBridge.getInstance().isRememberPasswordsManaged();
            }
        });
        getPreferenceScreen().addPreference(mSavePasswordsSwitch);

        // Note: setting the switch state before the preference is added to the screen results in
        // some odd behavior where the switch state doesn't always match the internal enabled state
        // (e.g. the switch will say "On" when save passwords is really turned off), so
        // .setChecked() should be called after .addPreference()
        mSavePasswordsSwitch.setChecked(
                PrefServiceBridge.getInstance().isRememberPasswordsEnabled());
    }

    private void createAutoSignInCheckbox() {
        if (mSearchQuery != null) {
            return; // Don't create this option when the preferences are filtered for passwords.
        }
        mAutoSignInSwitch = new ChromeBaseCheckBoxPreference(getActivity(), null);
        mAutoSignInSwitch.setKey(PREF_AUTOSIGNIN_SWITCH);
        mAutoSignInSwitch.setTitle(R.string.passwords_auto_signin_title);
        mAutoSignInSwitch.setOrder(ORDER_AUTO_SIGNIN_CHECKBOX);
        mAutoSignInSwitch.setSummary(R.string.passwords_auto_signin_description);
        mAutoSignInSwitch.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                PrefServiceBridge.getInstance().setPasswordManagerAutoSigninEnabled(
                        (boolean) newValue);
                return true;
            }
        });
        mAutoSignInSwitch.setManagedPreferenceDelegate(new ManagedPreferenceDelegate() {
            @Override
            public boolean isPreferenceControlledByPolicy(Preference preference) {
                return PrefServiceBridge.getInstance().isPasswordManagerAutoSigninManaged();
            }
        });
        getPreferenceScreen().addPreference(mAutoSignInSwitch);
        mAutoSignInSwitch.setChecked(
                PrefServiceBridge.getInstance().isPasswordManagerAutoSigninEnabled());
    }

    private void displayManageAccountLink() {
        if (mSearchQuery != null && !mNoPasswords) {
            return; // Don't add the Manage Account link if there is a search going on.
        }
        if (getPreferenceScreen().findPreference(PREF_KEY_MANAGE_ACCOUNT_LINK) != null) {
            return; // Don't add the Manage Account link if it's present.
        }
        if (mLinkPref != null) {
            // If we created the link before, reuse it.
            getPreferenceScreen().addPreference(mLinkPref);
            return;
        }
        ForegroundColorSpan colorSpan = new ForegroundColorSpan(
                ApiCompatibilityUtils.getColor(getResources(), R.color.google_blue_700));
        SpannableString title = SpanApplier.applySpans(getString(R.string.manage_passwords_text),
                new SpanApplier.SpanInfo("<link>", "</link>", colorSpan));
        mLinkPref = new ChromeBasePreference(getActivity());
        mLinkPref.setKey(PREF_KEY_MANAGE_ACCOUNT_LINK);
        mLinkPref.setTitle(title);
        mLinkPref.setOnPreferenceClickListener(this);
        mLinkPref.setOrder(ORDER_MANAGE_ACCOUNT_LINK);
        getPreferenceScreen().addPreference(mLinkPref);
    }

    /**
     * Returns whether the password export feature is ready to use.
     * @return Returns true if the flag is set and the Reauthentication Api is available.
     */
    private boolean providesPasswordExport() {
        return ChromeFeatureList.isEnabled(EXPORT_PASSWORDS)
                && ReauthenticationManager.isReauthenticationApiAvailable();
    }

    /**
     * Returns whether the password search feature is ready to use.
     * @return Returns true if the flag is set.
     */
    private boolean providesPasswordSearch() {
        return ChromeFeatureList.isEnabled(ChromeFeatureList.PASSWORD_SEARCH);
    }

    @VisibleForTesting
    Menu getMenuForTesting() {
        return mMenuForTesting;
    }
}
