Commit e07c80ba authored by Victor Hugo Vianna Silva's avatar Victor Hugo Vianna Silva Committed by Commit Bot

[b4p/Settings] Introduce MergePasswordsStoreCopiesBehavior

This CL moves the code in PasswordsSection responsible for retrieving
saved passwords and deduplicating copies into a new Polymer behavior.
Future CLs will introduce the "passwords on device" WebUI page, which
will also use this behavior. A similar behavior will also be introduced
for exceptions.

As a minor note: hasSavedPasswords_ is not factored out since the new
page is only interested on whether each of its subsections is empty or
not.

Bug: 1049141
Change-Id: Id919aa18ae4bcd57c4f9c71fefff259485752bbf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2225906Reviewed-by: default avatarFriedrich [CET] <fhorschig@chromium.org>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Commit-Queue: Victor Vianna <victorvianna@google.com>
Cr-Commit-Position: refs/heads/master@{#774652}
parent 4e292920
......@@ -16,6 +16,7 @@ js_type_check("closure_compile_module") {
":blocking_request_manager",
":credit_card_edit_dialog",
":credit_card_list_entry",
":merge_passwords_store_copies_behavior",
":multi_store_id_handler",
":multi_store_password_ui_entry",
":password_check",
......@@ -228,6 +229,7 @@ js_library("passwords_export_dialog") {
js_library("passwords_section") {
deps = [
":merge_passwords_store_copies_behavior",
":multi_store_password_ui_entry",
":password_list_item",
":password_manager_proxy",
......@@ -241,7 +243,6 @@ js_library("passwords_section") {
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
"//ui/webui/resources/js:assert.m",
"//ui/webui/resources/js:i18n_behavior.m",
"//ui/webui/resources/js:list_property_update_behavior.m",
"//ui/webui/resources/js:util.m",
"//ui/webui/resources/js:web_ui_listener_behavior.m",
"//ui/webui/resources/js/cr/ui:focus_without_ink.m",
......@@ -288,6 +289,14 @@ js_library("show_password_behavior") {
externs_list = [ "$externs_path/passwords_private.js" ]
}
js_library("merge_passwords_store_copies_behavior") {
deps = [
":multi_store_password_ui_entry",
":password_manager_proxy",
"//ui/webui/resources/js:list_property_update_behavior.m",
]
}
js_library("remove_password_behavior") {
deps = [
":multi_store_password_ui_entry",
......
// 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.
/**
* @fileoverview This behavior bundles the functionality for retrieving
* saved passwords from the password manager and deduplicating eventual copies
* existing stored both on the device and in the account.
*/
import {assert} from 'chrome://resources/js/assert.m.js';
import {ListPropertyUpdateBehavior} from 'chrome://resources/js/list_property_update_behavior.m.js';
import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js';
import {PasswordManagerImpl, PasswordManagerProxy} from './password_manager_proxy.js';
/**
* @polymerBehavior
*/
const MergePasswordsStoreCopiesBehaviorImpl = {
properties: {
/**
* Saved passwords after deduplicating versions that are repeated in the
* account and on the device.
* @type {!Array<!MultiStorePasswordUiEntry>}
*/
savedPasswords: {
type: Array,
value: () => [],
},
/**
* @type {?function(!Array<PasswordManagerProxy.PasswordUiEntry>):void}
* @private
*/
setSavedPasswordsListener_: {
type: Object,
value: null,
},
},
/** @override */
attached() {
this.setSavedPasswordsListener_ = passwordList => {
const mergedPasswordList =
this.mergePasswordsStoreDuplicates_(passwordList);
// getCombinedId() is unique for each |entry|. If both copies are removed,
// updateList() will consider this a removal. If only one copy is removed,
// this will be treated as a removal plus an insertion.
const getCombinedId =
entry => [entry.deviceId, entry.accountId].join('_');
this.updateList('savedPasswords', getCombinedId, mergedPasswordList);
};
PasswordManagerImpl.getInstance().getSavedPasswordList(
this.setSavedPasswordsListener_);
PasswordManagerImpl.getInstance().addSavedPasswordListChangedListener(
this.setSavedPasswordsListener_);
this.notifySplices('savedPasswords', []);
},
detached() {
PasswordManagerImpl.getInstance().removeSavedPasswordListChangedListener(
assert(this.setSavedPasswordsListener_));
},
/**
* @param {!Array<!PasswordManagerProxy.PasswordUiEntry>} passwordList
* @return {!Array<!MultiStorePasswordUiEntry>}
* @private
*/
mergePasswordsStoreDuplicates_(passwordList) {
/** @type {!Array<!MultiStorePasswordUiEntry>} */
const multiStoreEntries = [];
/** @type {!Map<number, !MultiStorePasswordUiEntry>} */
const frontendIdToMergedEntry = new Map();
for (const entry of passwordList) {
if (frontendIdToMergedEntry.has(entry.frontendId)) {
frontendIdToMergedEntry.get(entry.frontendId).merge(entry);
} else {
const multiStoreEntry = new MultiStorePasswordUiEntry(entry);
frontendIdToMergedEntry.set(entry.frontendId, multiStoreEntry);
multiStoreEntries.push(multiStoreEntry);
}
}
return multiStoreEntries;
},
};
/**
* @polymerBehavior
*/
export const MergePasswordsStoreCopiesBehavior =
[ListPropertyUpdateBehavior, MergePasswordsStoreCopiesBehaviorImpl];
......@@ -24,7 +24,6 @@ import 'chrome://resources/cr_elements/shared_style_css.m.js';
import {assert} from 'chrome://resources/js/assert.m.js';
import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js';
import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
import {ListPropertyUpdateBehavior} from 'chrome://resources/js/list_property_update_behavior.m.js';
import {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
......@@ -39,6 +38,7 @@ import {SyncBrowserProxyImpl, SyncPrefs, SyncStatus} from '../people_page/sync_b
import '../prefs/prefs.m.js';
import {PrefsBehavior} from '../prefs/prefs_behavior.m.js';
import {routes} from '../route.js';
import {MergePasswordsStoreCopiesBehavior} from './merge_passwords_store_copies_behavior.js';
import {Router} from '../router.m.js';
import '../settings_shared_css.m.js';
import '../site_favicon.js';
......@@ -75,7 +75,7 @@ Polymer({
behaviors: [
I18nBehavior,
WebUIListenerBehavior,
ListPropertyUpdateBehavior,
MergePasswordsStoreCopiesBehavior,
PasswordCheckBehavior,
IronA11yKeysBehavior,
GlobalScrollTargetBehavior,
......@@ -94,16 +94,6 @@ Polymer({
notify: true,
},
/**
* Saved passwords after deduplicating versions that are repeated in the
* account and on the device.
* @type {!Array<!MultiStorePasswordUiEntry>}
*/
savedPasswords: {
type: Array,
value: () => [],
},
/**
* An array of sites to display.
* @type {!Array<!PasswordManagerProxy.ExceptionEntry>}
......@@ -270,12 +260,6 @@ Polymer({
*/
setIsOptedInForAccountStorageListener_: null,
/**
* @type {?function(!Array<PasswordManagerProxy.PasswordUiEntry>):void}
* @private
*/
setSavedPasswordsListener_: null,
/**
* @type {?function(!Array<PasswordManagerProxy.ExceptionEntry>):void}
* @private
......@@ -289,26 +273,12 @@ Polymer({
this.isOptedInForAccountStorage_ = optedIn;
};
const setSavedPasswordsListener = passwordList => {
const mergedPasswordList =
this.mergePasswordsStoreDuplicates_(passwordList);
// getCombinedId() is unique for each |entry|. If both copies are removed,
// updateList() will consider this a removal. If only one copy is removed,
// this will be treated as a removal plus an insertion.
const getCombinedId =
entry => [entry.deviceId, entry.accountId].join('_');
this.updateList('savedPasswords', getCombinedId, mergedPasswordList);
this.hasStoredPasswords_ = passwordList.length > 0;
};
const setPasswordExceptionsListener = list => {
this.passwordExceptions = list;
};
this.setIsOptedInForAccountStorageListener_ =
setIsOptedInForAccountStorageListener;
this.setSavedPasswordsListener_ = setSavedPasswordsListener;
this.setPasswordExceptionsListener_ = setPasswordExceptionsListener;
// Set the manager. These can be overridden by tests.
......@@ -330,19 +300,14 @@ Polymer({
// Request initial data.
this.passwordManager_.isOptedInForAccountStorage().then(
setIsOptedInForAccountStorageListener);
this.passwordManager_.getSavedPasswordList(setSavedPasswordsListener);
this.passwordManager_.getExceptionList(setPasswordExceptionsListener);
// Listen for changes.
this.passwordManager_.addAccountStorageOptInStateListener(
setIsOptedInForAccountStorageListener);
this.passwordManager_.addSavedPasswordListChangedListener(
setSavedPasswordsListener);
this.passwordManager_.addExceptionListChangedListener(
setPasswordExceptionsListener);
this.notifySplices('savedPasswords', []);
const syncBrowserProxy = SyncBrowserProxyImpl.getInstance();
const syncStatusChanged = syncStatus => this.syncStatus_ = syncStatus;
......@@ -367,8 +332,6 @@ Polymer({
/** @override */
detached() {
this.passwordManager_.removeSavedPasswordListChangedListener(
assert(this.setSavedPasswordsListener_));
this.passwordManager_.removeExceptionListChangedListener(
assert(this.setPasswordExceptionsListener_));
this.passwordManager_.removeAccountStorageOptInStateListener(
......@@ -428,28 +391,6 @@ Polymer({
(!!this.storedAccounts_ && this.storedAccounts_.length > 0);
},
/**
* @param {!Array<!PasswordManagerProxy.PasswordUiEntry>} passwordList
* @return {!Array<!MultiStorePasswordUiEntry>}
* @private
*/
mergePasswordsStoreDuplicates_(passwordList) {
/** @type {!Array<!MultiStorePasswordUiEntry>} */
const multiStoreEntries = [];
/** @type {!Map<number, !MultiStorePasswordUiEntry>} */
const frontendIdToMergedEntry = new Map();
for (const entry of passwordList) {
if (frontendIdToMergedEntry.has(entry.frontendId)) {
frontendIdToMergedEntry.get(entry.frontendId).merge(entry);
} else {
const multiStoreEntry = new MultiStorePasswordUiEntry(entry);
frontendIdToMergedEntry.set(entry.frontendId, multiStoreEntry);
multiStoreEntries.push(multiStoreEntry);
}
}
return multiStoreEntries;
},
/**
* @return {boolean}
* @private
......
......@@ -86,6 +86,10 @@
file="autofill_page/blocking_request_manager.js"
compress="false" type="BINDATA" />
</if>
<include name="IDR_SETTINGS_AUTOFILL_PAGE_MERGE_PASSWORDS_STORE_COPIES_BEHAVIOR_JS"
file="autofill_page/merge_passwords_store_copies_behavior.js"
compress="false" type="BINDATA"
preprocess="true" />
<include name="IDR_SETTINGS_AUTOFILL_PAGE_MULTI_STORE_EXCEPTION_ENTRY_JS"
file="autofill_page/multi_store_exception_entry.js"
compress="false" type="BINDATA" />
......
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