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") { ...@@ -16,6 +16,7 @@ js_type_check("closure_compile_module") {
":blocking_request_manager", ":blocking_request_manager",
":credit_card_edit_dialog", ":credit_card_edit_dialog",
":credit_card_list_entry", ":credit_card_list_entry",
":merge_passwords_store_copies_behavior",
":multi_store_id_handler", ":multi_store_id_handler",
":multi_store_password_ui_entry", ":multi_store_password_ui_entry",
":password_check", ":password_check",
...@@ -228,6 +229,7 @@ js_library("passwords_export_dialog") { ...@@ -228,6 +229,7 @@ js_library("passwords_export_dialog") {
js_library("passwords_section") { js_library("passwords_section") {
deps = [ deps = [
":merge_passwords_store_copies_behavior",
":multi_store_password_ui_entry", ":multi_store_password_ui_entry",
":password_list_item", ":password_list_item",
":password_manager_proxy", ":password_manager_proxy",
...@@ -241,7 +243,6 @@ js_library("passwords_section") { ...@@ -241,7 +243,6 @@ js_library("passwords_section") {
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m", "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
"//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:assert.m",
"//ui/webui/resources/js:i18n_behavior.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:util.m",
"//ui/webui/resources/js:web_ui_listener_behavior.m", "//ui/webui/resources/js:web_ui_listener_behavior.m",
"//ui/webui/resources/js/cr/ui:focus_without_ink.m", "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
...@@ -288,6 +289,14 @@ js_library("show_password_behavior") { ...@@ -288,6 +289,14 @@ js_library("show_password_behavior") {
externs_list = [ "$externs_path/passwords_private.js" ] 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") { js_library("remove_password_behavior") {
deps = [ deps = [
":multi_store_password_ui_entry", ":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'; ...@@ -24,7 +24,6 @@ import 'chrome://resources/cr_elements/shared_style_css.m.js';
import {assert} from 'chrome://resources/js/assert.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 {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js';
import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.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 {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.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'; 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 ...@@ -39,6 +38,7 @@ import {SyncBrowserProxyImpl, SyncPrefs, SyncStatus} from '../people_page/sync_b
import '../prefs/prefs.m.js'; import '../prefs/prefs.m.js';
import {PrefsBehavior} from '../prefs/prefs_behavior.m.js'; import {PrefsBehavior} from '../prefs/prefs_behavior.m.js';
import {routes} from '../route.js'; import {routes} from '../route.js';
import {MergePasswordsStoreCopiesBehavior} from './merge_passwords_store_copies_behavior.js';
import {Router} from '../router.m.js'; import {Router} from '../router.m.js';
import '../settings_shared_css.m.js'; import '../settings_shared_css.m.js';
import '../site_favicon.js'; import '../site_favicon.js';
...@@ -75,7 +75,7 @@ Polymer({ ...@@ -75,7 +75,7 @@ Polymer({
behaviors: [ behaviors: [
I18nBehavior, I18nBehavior,
WebUIListenerBehavior, WebUIListenerBehavior,
ListPropertyUpdateBehavior, MergePasswordsStoreCopiesBehavior,
PasswordCheckBehavior, PasswordCheckBehavior,
IronA11yKeysBehavior, IronA11yKeysBehavior,
GlobalScrollTargetBehavior, GlobalScrollTargetBehavior,
...@@ -94,16 +94,6 @@ Polymer({ ...@@ -94,16 +94,6 @@ Polymer({
notify: true, 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. * An array of sites to display.
* @type {!Array<!PasswordManagerProxy.ExceptionEntry>} * @type {!Array<!PasswordManagerProxy.ExceptionEntry>}
...@@ -270,12 +260,6 @@ Polymer({ ...@@ -270,12 +260,6 @@ Polymer({
*/ */
setIsOptedInForAccountStorageListener_: null, setIsOptedInForAccountStorageListener_: null,
/**
* @type {?function(!Array<PasswordManagerProxy.PasswordUiEntry>):void}
* @private
*/
setSavedPasswordsListener_: null,
/** /**
* @type {?function(!Array<PasswordManagerProxy.ExceptionEntry>):void} * @type {?function(!Array<PasswordManagerProxy.ExceptionEntry>):void}
* @private * @private
...@@ -289,26 +273,12 @@ Polymer({ ...@@ -289,26 +273,12 @@ Polymer({
this.isOptedInForAccountStorage_ = optedIn; 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 => { const setPasswordExceptionsListener = list => {
this.passwordExceptions = list; this.passwordExceptions = list;
}; };
this.setIsOptedInForAccountStorageListener_ = this.setIsOptedInForAccountStorageListener_ =
setIsOptedInForAccountStorageListener; setIsOptedInForAccountStorageListener;
this.setSavedPasswordsListener_ = setSavedPasswordsListener;
this.setPasswordExceptionsListener_ = setPasswordExceptionsListener; this.setPasswordExceptionsListener_ = setPasswordExceptionsListener;
// Set the manager. These can be overridden by tests. // Set the manager. These can be overridden by tests.
...@@ -330,19 +300,14 @@ Polymer({ ...@@ -330,19 +300,14 @@ Polymer({
// Request initial data. // Request initial data.
this.passwordManager_.isOptedInForAccountStorage().then( this.passwordManager_.isOptedInForAccountStorage().then(
setIsOptedInForAccountStorageListener); setIsOptedInForAccountStorageListener);
this.passwordManager_.getSavedPasswordList(setSavedPasswordsListener);
this.passwordManager_.getExceptionList(setPasswordExceptionsListener); this.passwordManager_.getExceptionList(setPasswordExceptionsListener);
// Listen for changes. // Listen for changes.
this.passwordManager_.addAccountStorageOptInStateListener( this.passwordManager_.addAccountStorageOptInStateListener(
setIsOptedInForAccountStorageListener); setIsOptedInForAccountStorageListener);
this.passwordManager_.addSavedPasswordListChangedListener(
setSavedPasswordsListener);
this.passwordManager_.addExceptionListChangedListener( this.passwordManager_.addExceptionListChangedListener(
setPasswordExceptionsListener); setPasswordExceptionsListener);
this.notifySplices('savedPasswords', []);
const syncBrowserProxy = SyncBrowserProxyImpl.getInstance(); const syncBrowserProxy = SyncBrowserProxyImpl.getInstance();
const syncStatusChanged = syncStatus => this.syncStatus_ = syncStatus; const syncStatusChanged = syncStatus => this.syncStatus_ = syncStatus;
...@@ -367,8 +332,6 @@ Polymer({ ...@@ -367,8 +332,6 @@ Polymer({
/** @override */ /** @override */
detached() { detached() {
this.passwordManager_.removeSavedPasswordListChangedListener(
assert(this.setSavedPasswordsListener_));
this.passwordManager_.removeExceptionListChangedListener( this.passwordManager_.removeExceptionListChangedListener(
assert(this.setPasswordExceptionsListener_)); assert(this.setPasswordExceptionsListener_));
this.passwordManager_.removeAccountStorageOptInStateListener( this.passwordManager_.removeAccountStorageOptInStateListener(
...@@ -428,28 +391,6 @@ Polymer({ ...@@ -428,28 +391,6 @@ Polymer({
(!!this.storedAccounts_ && this.storedAccounts_.length > 0); (!!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} * @return {boolean}
* @private * @private
......
...@@ -86,6 +86,10 @@ ...@@ -86,6 +86,10 @@
file="autofill_page/blocking_request_manager.js" file="autofill_page/blocking_request_manager.js"
compress="false" type="BINDATA" /> compress="false" type="BINDATA" />
</if> </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" <include name="IDR_SETTINGS_AUTOFILL_PAGE_MULTI_STORE_EXCEPTION_ENTRY_JS"
file="autofill_page/multi_store_exception_entry.js" file="autofill_page/multi_store_exception_entry.js"
compress="false" type="BINDATA" /> 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