blob: b83f04bccbd5ed625a02874a5550e7b664d08bd7 [file] [log] [blame]
// 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.keyboard_accessory.all_passwords_bottom_sheet;
import static org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet.AllPasswordsBottomSheetMetricsRecorder.UMA_ALL_PASSWORDS_BOTTOM_SHEET_ACTIONS;
import static org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet.AllPasswordsBottomSheetMetricsRecorder.recordHistogram;
import static org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet.AllPasswordsBottomSheetProperties.SHEET_ITEMS;
import static org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet.AllPasswordsBottomSheetProperties.VISIBLE;
import org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet.AllPasswordsBottomSheetMetricsRecorder.AllPasswordsBottomSheetActions;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason;
import org.chromium.components.embedder_support.util.UrlUtilities;
import org.chromium.ui.modelutil.ListModel;
import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
import org.chromium.ui.modelutil.PropertyModel;
import java.util.Arrays;
import java.util.Locale;
/**
* Contains the logic for the AllPasswordsBottomSheet. It sets the state of the model and reacts to
* events like clicks.
*/
class AllPasswordsBottomSheetMediator {
private AllPasswordsBottomSheetCoordinator.Delegate mDelegate;
private PropertyModel mModel;
private Credential[] mCredentials;
private boolean mIsPasswordField;
private boolean mSearchUsed;
void initialize(AllPasswordsBottomSheetCoordinator.Delegate delegate, PropertyModel model) {
assert delegate != null;
mDelegate = delegate;
mModel = model;
}
void showCredentials(Credential[] credentials, boolean isPasswordField) {
assert credentials != null;
Arrays.sort(credentials, AllPasswordsBottomSheetMediator::compareCredentials);
mCredentials = credentials;
mIsPasswordField = isPasswordField;
ListModel<ListItem> sheetItems = mModel.get(SHEET_ITEMS);
sheetItems.clear();
for (Credential credential : mCredentials) {
if (credential.getPassword().isEmpty() && isPasswordField) continue;
final PropertyModel model =
AllPasswordsBottomSheetProperties.CredentialProperties.createCredentialModel(
credential, this::onCredentialSelected, mIsPasswordField);
sheetItems.add(
new ListItem(AllPasswordsBottomSheetProperties.ItemType.CREDENTIAL, model));
}
mModel.set(VISIBLE, true);
}
/**
* Filters the credentials list based on the passed text and adds the resulting credentials to
* the model.
* @param newText the text used to filter the credentials.
*/
void onQueryTextChange(String newText) {
mSearchUsed = true;
ListModel<ListItem> sheetItems = mModel.get(SHEET_ITEMS);
sheetItems.clear();
for (Credential credential : mCredentials) {
if ((credential.getPassword().isEmpty() && mIsPasswordField)
|| shouldBeFiltered(newText, credential)) {
continue;
}
final PropertyModel model =
AllPasswordsBottomSheetProperties.CredentialProperties.createCredentialModel(
credential, this::onCredentialSelected, mIsPasswordField);
sheetItems.add(
new ListItem(AllPasswordsBottomSheetProperties.ItemType.CREDENTIAL, model));
}
}
/**
* Returns true if no substring in the passed credential matches the searchQuery ignoring the
* characters case.
* @param searchQuery the text to check if passed credential has it.
* @param credential its username and origin will be checked for matching string.
* @return Returns whether the entry with the passed credential should be filtered.
*/
private boolean shouldBeFiltered(final String searchQuery, final Credential credential) {
return searchQuery != null
&& !credential.getOriginUrl()
.toLowerCase(Locale.ENGLISH)
.contains(searchQuery.toLowerCase(Locale.ENGLISH))
&& !credential.getUsername()
.toLowerCase(Locale.getDefault())
.contains(searchQuery.toLowerCase(Locale.getDefault()));
}
void onCredentialSelected(Credential credential) {
recordHistogram(UMA_ALL_PASSWORDS_BOTTOM_SHEET_ACTIONS,
AllPasswordsBottomSheetActions.CREDENTIAL_SELECTED,
AllPasswordsBottomSheetActions.COUNT);
if (mSearchUsed) {
recordHistogram(UMA_ALL_PASSWORDS_BOTTOM_SHEET_ACTIONS,
AllPasswordsBottomSheetActions.SEARCH_USED,
AllPasswordsBottomSheetActions.COUNT);
}
mModel.set(VISIBLE, false);
mDelegate.onCredentialSelected(credential);
}
void onDismissed(@StateChangeReason Integer reason) {
if (!mModel.get(VISIBLE)) return; // Dismiss only if not dismissed yet.
recordHistogram(UMA_ALL_PASSWORDS_BOTTOM_SHEET_ACTIONS,
AllPasswordsBottomSheetActions.SHEET_DISMISSED,
AllPasswordsBottomSheetActions.COUNT);
mModel.set(VISIBLE, false);
mDelegate.onDismissed();
}
private static int compareCredentials(Credential credential1, Credential credential2) {
String displayOrigin1 = credential1.isAndroidCredential()
? credential1.getAppDisplayName().toLowerCase(Locale.ENGLISH)
: UrlUtilities.getDomainAndRegistry(credential1.getOriginUrl(), false);
String displayOrigin2 = credential2.isAndroidCredential()
? credential2.getAppDisplayName().toLowerCase(Locale.ENGLISH)
: UrlUtilities.getDomainAndRegistry(credential2.getOriginUrl(), false);
return displayOrigin1.compareTo(displayOrigin2);
}
}