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

[Passwords/Settings] Restrict plaintext pwd to ShowPasswordBehavior

No behavior is changed.

Before this CL, passwords_section was responsible for initializing and
storing the displayed password strings of each element in savedPasswords
and multiStoreSavedPasswords. Those were even initialized to the empty
string, relying on implementation details of ShowPasswordBehavior
(an empty string means the plaintext password is not being shown).

This CL makes the password string a property of ShowPasswordBehavior,
simplifying the passwords_section code. As a consequence, the
PasswordUiEntryWithPassword and MultiStorePasswordUiEntryWithPassword
typedefs are no longer needed. RemovePasswordBehavior's entryToRemove
property and ShowPasswordBehavior's item property are both renamed to
entry, since they represent the same object.

Bug: None
Change-Id: I58b58626999de5144913730d853ae0a4b839ae56
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2215321
Commit-Queue: Victor Vianna <victorvianna@google.com>
Reviewed-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>
Cr-Commit-Position: refs/heads/master@{#771813}
parent 90150a27
...@@ -124,8 +124,3 @@ export class MultiStorePasswordUiEntry { ...@@ -124,8 +124,3 @@ export class MultiStorePasswordUiEntry {
* }} * }}
*/ */
MultiStorePasswordUiEntry.Contents; MultiStorePasswordUiEntry.Contents;
/**
* @typedef {{ entry: !MultiStorePasswordUiEntry, password: string }}
*/
export let MultiStorePasswordUiEntryWithPassword;
...@@ -36,20 +36,20 @@ ...@@ -36,20 +36,20 @@
<div hidden="[[!shouldShowStorageDetails]]" id="storageDetails" <div hidden="[[!shouldShowStorageDetails]]" id="storageDetails"
inner-h-t-m-l="[[getStorageDetailsMessage_()]]"></div> inner-h-t-m-l="[[getStorageDetailsMessage_()]]"></div>
<cr-input id="websiteInput" label="$i18n{editPasswordWebsiteLabel}" <cr-input id="websiteInput" label="$i18n{editPasswordWebsiteLabel}"
value="[[item.entry.urls.link]]" on-blur="onInputBlur_" readonly> value="[[entry.urls.link]]" on-blur="onInputBlur_" readonly>
</cr-input> </cr-input>
<cr-input id="usernameInput" label="$i18n{editPasswordUsernameLabel}" <cr-input id="usernameInput" label="$i18n{editPasswordUsernameLabel}"
value="[[item.entry.username]]" on-blur="onInputBlur_" readonly> value="[[entry.username]]" on-blur="onInputBlur_" readonly>
</cr-input> </cr-input>
<cr-input id="passwordInput" label="$i18n{editPasswordPasswordLabel}" <cr-input id="passwordInput" label="$i18n{editPasswordPasswordLabel}"
type="[[getPasswordInputType_(item.password)]]" type="[[getPasswordInputType_(password)]]"
value="[[getPassword_(item.password)]]" on-blur="onInputBlur_" value="[[getPassword_(password)]]" on-blur="onInputBlur_"
class="password-input" readonly> class="password-input" readonly>
<cr-icon-button id="showPasswordButton" <cr-icon-button id="showPasswordButton"
class$="[[getIconClass_(item.password)]]" slot="suffix" class$="[[getIconClass_(password)]]" slot="suffix"
hidden$="[[item.entry.federationText]]" hidden$="[[entry.federationText]]"
on-click="onShowPasswordButtonTap_" on-click="onShowPasswordButtonTap_"
title="[[showPasswordTitle_(item.password, title="[[showPasswordTitle_(password,
'$i18nPolymer{hidePassword}', '$i18nPolymer{hidePassword}',
'$i18nPolymer{showPassword}')]]"> '$i18nPolymer{showPassword}')]]">
</cr-icon-button> </cr-icon-button>
......
...@@ -65,7 +65,7 @@ Polymer({ ...@@ -65,7 +65,7 @@ Polymer({
getStorageDetailsMessage_() { getStorageDetailsMessage_() {
// TODO(crbug.com/1049141): Add support and tests for the multi-store case // TODO(crbug.com/1049141): Add support and tests for the multi-store case
// when dedup is being done. // when dedup is being done.
return this.item.entry.isPresentInAccount() ? return this.entry.isPresentInAccount() ?
this.i18nAdvanced('passwordStoredInAccount', {tags: ['b']}) : this.i18nAdvanced('passwordStoredInAccount', {tags: ['b']}) :
this.i18nAdvanced('passwordStoredOnDevice', {tags: ['b']}); this.i18nAdvanced('passwordStoredOnDevice', {tags: ['b']});
} }
......
...@@ -27,44 +27,44 @@ ...@@ -27,44 +27,44 @@
</style> </style>
<div class="list-item" focus-row-container> <div class="list-item" focus-row-container>
<div class="website-column no-min-width"> <div class="website-column no-min-width">
<site-favicon url="[[item.entry.urls.link]]"></site-favicon> <site-favicon url="[[entry.urls.link]]"></site-favicon>
<a id="originUrl" target="_blank" class="no-min-width" <a id="originUrl" target="_blank" class="no-min-width"
href="[[item.entry.urls.link]]" href="[[entry.urls.link]]"
focus-row-control focus-type="originUrl"> focus-row-control focus-type="originUrl">
<span class="text-elide"> <span class="text-elide">
<!-- This bdo tag is necessary to fix the display of domains <!-- This bdo tag is necessary to fix the display of domains
starting with numbers. --> starting with numbers. -->
<bdo dir="ltr">[[item.entry.urls.shown]]</bdo> <bdo dir="ltr">[[entry.urls.shown]]</bdo>
</span> </span>
</a> </a>
</div> </div>
<input id="username" class="username-column password-field" <input id="username" class="username-column password-field"
aria-label="$i18n{editPasswordUsernameLabel}" aria-label="$i18n{editPasswordUsernameLabel}"
readonly value="[[item.entry.username]]" readonly value="[[entry.username]]"
focus-row-control focus-type="username"> focus-row-control focus-type="username">
<div class="password-column"> <div class="password-column">
<template is="dom-if" if="[[!item.entry.federationText]]"> <template is="dom-if" if="[[!entry.federationText]]">
<input id="password" aria-label=$i18n{editPasswordPasswordLabel} <input id="password" aria-label=$i18n{editPasswordPasswordLabel}
type="[[getPasswordInputType_(item.password)]]" type="[[getPasswordInputType_(password)]]"
class="password-field password-input" readonly class="password-field password-input" readonly
disabled$="[[!item.password]]" on-click="onReadonlyInputTap_" disabled$="[[!password]]" on-click="onReadonlyInputTap_"
value="[[getPassword_(item.password)]]" value="[[getPassword_(password)]]"
focus-row-control focus-type="passwordField"> focus-row-control focus-type="passwordField">
<cr-icon-button id="showPasswordButton" <cr-icon-button id="showPasswordButton"
class$="[[getIconClass_(item.password)]]" class$="[[getIconClass_(password)]]"
on-click="onShowPasswordButtonTap_" on-click="onShowPasswordButtonTap_"
title="[[showPasswordTitle_(item.password, title="[[showPasswordTitle_(password,
'$i18nPolymer{hidePassword}', '$i18nPolymer{hidePassword}',
'$i18nPolymer{showPassword}')]]" '$i18nPolymer{showPassword}')]]"
focus-row-control focus-type="showPassword"></cr-icon-button> focus-row-control focus-type="showPassword"></cr-icon-button>
</template> </template>
<span class="password-field text-elide" id="federated" <span class="password-field text-elide" id="federated"
hidden$="[[!item.entry.federationText]]"> hidden$="[[!entry.federationText]]">
[[item.entry.federationText]] [[entry.federationText]]
</span> </span>
</div> </div>
<cr-icon-button class="icon-more-vert" id="passwordMenu" <cr-icon-button class="icon-more-vert" id="passwordMenu"
on-click="onPasswordMenuTap_" title="$i18n{moreActions}" on-click="onPasswordMenuTap_" title="$i18n{moreActions}"
focus-row-control focus-type="passwordMenu" focus-row-control focus-type="passwordMenu"
aria-label$="[[getMoreActionsLabel_(item)]]"></cr-icon-button> aria-label$="[[getMoreActionsLabel_(entry)]]"></cr-icon-button>
</div> </div>
...@@ -18,7 +18,7 @@ import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bun ...@@ -18,7 +18,7 @@ import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bun
import {loadTimeData} from '../i18n_setup.js'; import {loadTimeData} from '../i18n_setup.js';
import {MultiStorePasswordUiEntryWithPassword} from './multi_store_password_ui_entry.js'; import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js';
import {RemovePasswordBehavior} from './remove_password_behavior.js'; import {RemovePasswordBehavior} from './remove_password_behavior.js';
import {ShowPasswordBehavior} from './show_password_behavior.js'; import {ShowPasswordBehavior} from './show_password_behavior.js';
...@@ -38,7 +38,7 @@ Polymer({ ...@@ -38,7 +38,7 @@ Polymer({
* @private * @private
*/ */
onReadonlyInputTap_() { onReadonlyInputTap_() {
if (this.item.password) { if (this.password) {
this.$$('#password').select(); this.$$('#password').select();
} }
}, },
...@@ -54,16 +54,15 @@ Polymer({ ...@@ -54,16 +54,15 @@ Polymer({
/** /**
* Get the aria label for the More Actions button on this row. * Get the aria label for the More Actions button on this row.
* @param {!MultiStorePasswordUiEntryWithPassword} item This row's item.
* @private * @private
*/ */
getMoreActionsLabel_(item) { getMoreActionsLabel_() {
// Avoid using I18nBehavior.i18n, because it will filter sequences, which // Avoid using I18nBehavior.i18n, because it will filter sequences, which
// are otherwise not illegal for usernames. Polymer still protects against // are otherwise not illegal for usernames. Polymer still protects against
// XSS injection. // XSS injection.
return loadTimeData.getStringF( return loadTimeData.getStringF(
(item.entry.federationText) ? 'passwordRowFederatedMoreActionsButton' : (this.entry.federationText) ? 'passwordRowFederatedMoreActionsButton' :
'passwordRowMoreActionsButton', 'passwordRowMoreActionsButton',
item.entry.username, item.entry.urls.shown); this.entry.username, this.entry.urls.shown);
}, },
}); });
...@@ -265,11 +265,6 @@ PasswordManagerProxy.UrlCollection; ...@@ -265,11 +265,6 @@ PasswordManagerProxy.UrlCollection;
/** @typedef {chrome.passwordsPrivate.ExceptionEntry} */ /** @typedef {chrome.passwordsPrivate.ExceptionEntry} */
PasswordManagerProxy.ExceptionEntry; PasswordManagerProxy.ExceptionEntry;
/**
* @typedef {{ entry: !PasswordManagerProxy.PasswordUiEntry, password: string }}
*/
PasswordManagerProxy.UiEntryWithPassword;
/** @typedef {chrome.passwordsPrivate.PasswordExportProgress} */ /** @typedef {chrome.passwordsPrivate.PasswordExportProgress} */
PasswordManagerProxy.PasswordExportProgress; PasswordManagerProxy.PasswordExportProgress;
......
...@@ -169,7 +169,9 @@ ...@@ -169,7 +169,9 @@
class="cr-separators list-with-header" class="cr-separators list-with-header"
scroll-target="[[subpageScrollTarget]]" risk-selection> scroll-target="[[subpageScrollTarget]]" risk-selection>
<template> <template>
<password-list-item item="[[item]]" entry-to-remove="[[item.entry]]" <!-- The entry property is shared by ShowPasswordBehavior and
RemovePasswordBehavior. -->
<password-list-item entry="[[item]]"
tabindex$="[[tabIndex]]" focus-row-index="[[index]]" tabindex$="[[tabIndex]]" focus-row-index="[[index]]"
<if expr="chromeos"> <if expr="chromeos">
token-request-manager="[[tokenRequestManager_]]" token-request-manager="[[tokenRequestManager_]]"
...@@ -188,7 +190,7 @@ ...@@ -188,7 +190,7 @@
<template is="dom-if" if="[[enablePasswordCheck_]]"> <template is="dom-if" if="[[enablePasswordCheck_]]">
<button id="menuCopyPassword" class="dropdown-item" <button id="menuCopyPassword" class="dropdown-item"
on-click="onMenuCopyPasswordButtonTap_" on-click="onMenuCopyPasswordButtonTap_"
hidden$="[[activePassword.item.entry.federationText]]"> hidden$="[[activePassword.entry.federationText]]">
$i18n{copyPassword} $i18n{copyPassword}
</button> </button>
</template> </template>
...@@ -221,7 +223,8 @@ ...@@ -221,7 +223,8 @@
<if expr="chromeos"> <if expr="chromeos">
token-request-manager="[[tokenRequestManager_]]" token-request-manager="[[tokenRequestManager_]]"
</if> </if>
item="[[activePassword.item]]" entry="[[activePassword.entry]]"
password="{{activePassword.password}}"
should-show-storage-details= should-show-storage-details=
"[[shouldShowStorageDetailsInEditDialog_]]"> "[[shouldShowStorageDetailsInEditDialog_]]">
</password-edit-dialog> </password-edit-dialog>
......
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
* save any passwords. * save any passwords.
*/ */
/** @typedef {!{model: !{item: !PasswordManagerProxy.UiEntryWithPassword}}} */
let PasswordUiEntryEvent;
/** @typedef {!{model: !{item: !chrome.passwordsPrivate.ExceptionEntry}}} */ /** @typedef {!{model: !{item: !chrome.passwordsPrivate.ExceptionEntry}}} */
let ExceptionEntryEntryEvent; let ExceptionEntryEntryEvent;
...@@ -17,7 +15,7 @@ let ExceptionEntryEntryEvent; ...@@ -17,7 +15,7 @@ let ExceptionEntryEntryEvent;
import {afterNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {afterNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.m.js'; import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.m.js';
import {MultiStorePasswordUiEntry, MultiStorePasswordUiEntryWithPassword} from './multi_store_password_ui_entry.js'; import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js';
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.m.js'; import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.m.js';
...@@ -102,7 +100,7 @@ Polymer({ ...@@ -102,7 +100,7 @@ Polymer({
/** /**
* An array of passwords with all the stored versions. * An array of passwords with all the stored versions.
* @type {!Array<!PasswordManagerProxy.UiEntryWithPassword>} * @type {!Array<!PasswordManagerProxy.PasswordUiEntry>}
*/ */
savedPasswords: { savedPasswords: {
type: Array, type: Array,
...@@ -112,7 +110,7 @@ Polymer({ ...@@ -112,7 +110,7 @@ Polymer({
/** /**
* Saved passwords after deduplicating versions that are repeated in the * Saved passwords after deduplicating versions that are repeated in the
* account and on the device. * account and on the device.
* @type {!Array<!MultiStorePasswordUiEntryWithPassword>} * @type {!Array<!MultiStorePasswordUiEntry>}
*/ */
multiStoreSavedPasswords: { multiStoreSavedPasswords: {
type: Array, type: Array,
...@@ -190,7 +188,7 @@ Polymer({ ...@@ -190,7 +188,7 @@ Polymer({
shouldShowStorageDetailsInEditDialog_: { shouldShowStorageDetailsInEditDialog_: {
type: Boolean, type: Boolean,
value: false, value: false,
computed: 'computeShouldShowStorageDetailsInEditDialog_('+ computed: 'computeShouldShowStorageDetailsInEditDialog_(' +
'eligibleForAccountStorage_, isOptedInForAccountStorage_)', 'eligibleForAccountStorage_, isOptedInForAccountStorage_)',
}, },
...@@ -247,7 +245,7 @@ Polymer({ ...@@ -247,7 +245,7 @@ Polymer({
value: '', value: '',
}, },
/** @private {!MultiStorePasswordUiEntryWithPassword} */ /** @private {!MultiStorePasswordUiEntry} */
lastFocused_: Object, lastFocused_: Object,
/** @private */ /** @private */
...@@ -314,11 +312,12 @@ Polymer({ ...@@ -314,11 +312,12 @@ Polymer({
}; };
const setSavedPasswordsListener = list => { const setSavedPasswordsListener = list => {
const newList = list.map(entry => ({entry: entry, password: ''})); // Because the backend guarantees that entry.id uniquely identifies a
// Because the backend guarantees that item.entry.id uniquely identifies a
// given entry and is stable with regard to mutations to the list, it is // given entry and is stable with regard to mutations to the list, it is
// sufficient to just use this id to create a item uid. // sufficient to just use this id to create an entry uid.
this.updateList('savedPasswords', item => item.entry.id, newList); // TODO(crbug.com/1049141): Get rid of the savedPasswords property by
// finding a nice id to use here, such as [account_id]_[device_id].
this.updateList('savedPasswords', entry => entry.id, list);
this.hasStoredPasswords_ = list.length > 0; this.hasStoredPasswords_ = list.length > 0;
}; };
...@@ -457,10 +456,6 @@ Polymer({ ...@@ -457,10 +456,6 @@ Polymer({
onPasswordEditDialogClosed_() { onPasswordEditDialogClosed_() {
this.showPasswordEditDialog_ = false; this.showPasswordEditDialog_ = false;
focusWithoutInk(assert(this.activeDialogAnchorStack_.pop())); focusWithoutInk(assert(this.activeDialogAnchorStack_.pop()));
// Trigger a re-evaluation of the activePassword as the visibility state of
// the password might have changed.
this.activePassword.notifyPath('item.password');
}, },
/** /**
...@@ -474,15 +469,12 @@ Polymer({ ...@@ -474,15 +469,12 @@ Polymer({
}, },
/** /**
* @return {!Array<!MultiStorePasswordUiEntryWithPassword>} * @return {!Array<!MultiStorePasswordUiEntry>}
* @private * @private
*/ */
computeMultiStoreSavedPasswords_() { computeMultiStoreSavedPasswords_() {
return this.savedPasswords.map( return this.savedPasswords.map(
item => ({ entry => new MultiStorePasswordUiEntry(entry));
entry: new MultiStorePasswordUiEntry(item.entry),
password: item.password
}));
}, },
/** /**
...@@ -524,7 +516,7 @@ Polymer({ ...@@ -524,7 +516,7 @@ Polymer({
/** /**
* @param {string} filter * @param {string} filter
* @return {!Array<!MultiStorePasswordUiEntryWithPassword>} * @return {!Array<!MultiStorePasswordUiEntry>}
* @private * @private
*/ */
getFilteredMultiStorePasswords_(filter) { getFilteredMultiStorePasswords_(filter) {
...@@ -533,7 +525,7 @@ Polymer({ ...@@ -533,7 +525,7 @@ Polymer({
} }
return this.multiStoreSavedPasswords.filter( return this.multiStoreSavedPasswords.filter(
p => [p.entry.urls.shown, p.entry.username].some( p => [p.urls.shown, p.username].some(
term => term.toLowerCase().includes(filter.toLowerCase()))); term => term.toLowerCase().includes(filter.toLowerCase())));
}, },
...@@ -583,7 +575,7 @@ Polymer({ ...@@ -583,7 +575,7 @@ Polymer({
// result back to javascript. // result back to javascript.
this.passwordManager_ this.passwordManager_
.requestPlaintextPassword( .requestPlaintextPassword(
this.activePassword.item.entry.getAnyId(), this.activePassword.entry.getAnyId(),
chrome.passwordsPrivate.PlaintextReason.COPY) chrome.passwordsPrivate.PlaintextReason.COPY)
.catch(error => { .catch(error => {
// <if expr="chromeos"> // <if expr="chromeos">
...@@ -689,7 +681,7 @@ Polymer({ ...@@ -689,7 +681,7 @@ Polymer({
}, },
/** /**
* Returns true if the list exists and has items. * Returns true if the list exists and is not empty.
* @param {Array<Object>} list * @param {Array<Object>} list
* @return {boolean} * @return {boolean}
* @private * @private
......
...@@ -17,7 +17,7 @@ export const RemovePasswordBehavior = { ...@@ -17,7 +17,7 @@ export const RemovePasswordBehavior = {
* The password that will be removed. * The password that will be removed.
* @type {!MultiStorePasswordUiEntry} * @type {!MultiStorePasswordUiEntry}
*/ */
entryToRemove: Object, entry: Object,
}, },
/** /**
...@@ -35,13 +35,13 @@ export const RemovePasswordBehavior = { ...@@ -35,13 +35,13 @@ export const RemovePasswordBehavior = {
/** @type {!Array<number>} */ /** @type {!Array<number>} */
const idsToRemove = []; const idsToRemove = [];
if (this.entryToRemove.isPresentInAccount()) { if (this.entry.isPresentInAccount()) {
result.removedFromAccount = true; result.removedFromAccount = true;
idsToRemove.push(this.entryToRemove.accountId); idsToRemove.push(this.entry.accountId);
} }
if (this.entryToRemove.isPresentOnDevice()) { if (this.entry.isPresentOnDevice()) {
result.removedFromDevice = true; result.removedFromDevice = true;
idsToRemove.push(this.entryToRemove.deviceId); idsToRemove.push(this.entry.deviceId);
} }
if (idsToRemove.length) { if (idsToRemove.length) {
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
// <if expr="chromeos"> // <if expr="chromeos">
import {BlockingRequestManager} from './blocking_request_manager.js'; import {BlockingRequestManager} from './blocking_request_manager.js';
// </if> // </if>
import {MultiStorePasswordUiEntryWithPassword} from './multi_store_password_ui_entry.js'; import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js';
import {PasswordManagerImpl} from './password_manager_proxy.js'; import {PasswordManagerImpl} from './password_manager_proxy.js';
/** /**
...@@ -18,10 +18,18 @@ export const ShowPasswordBehavior = { ...@@ -18,10 +18,18 @@ export const ShowPasswordBehavior = {
properties: { properties: {
/** /**
* The password that is being displayed. * @type {!MultiStorePasswordUiEntry}
* @type {!MultiStorePasswordUiEntryWithPassword}
*/ */
item: Object, entry: Object,
/** The password that is being displayed. */
password: {
type: String,
value: '',
// If the password is initialized by the parent component, changes in
// visibility should be reflected there too.
notify: true
},
// <if expr="chromeos"> // <if expr="chromeos">
/** @type BlockingRequestManager */ /** @type BlockingRequestManager */
...@@ -35,8 +43,7 @@ export const ShowPasswordBehavior = { ...@@ -35,8 +43,7 @@ export const ShowPasswordBehavior = {
* @private * @private
*/ */
getPasswordInputType_() { getPasswordInputType_() {
return this.item.password || this.item.entry.federationText ? 'text' : return this.password || this.entry.federationText ? 'text' : 'password';
'password';
}, },
/** /**
...@@ -56,7 +63,7 @@ export const ShowPasswordBehavior = { ...@@ -56,7 +63,7 @@ export const ShowPasswordBehavior = {
* @private * @private
*/ */
getIconClass_() { getIconClass_() {
return this.item.password ? 'icon-visibility-off' : 'icon-visibility'; return this.password ? 'icon-visibility-off' : 'icon-visibility';
}, },
/** /**
...@@ -66,12 +73,12 @@ export const ShowPasswordBehavior = { ...@@ -66,12 +73,12 @@ export const ShowPasswordBehavior = {
* @private * @private
*/ */
getPassword_() { getPassword_() {
if (!this.item) { if (!this.entry) {
return ''; return '';
} }
const NUM_PLACEHOLDERS = 10; const NUM_PLACEHOLDERS = 10;
return this.item.entry.federationText || this.item.password || return this.entry.federationText || this.password ||
' '.repeat(NUM_PLACEHOLDERS); ' '.repeat(NUM_PLACEHOLDERS);
}, },
...@@ -80,17 +87,16 @@ export const ShowPasswordBehavior = { ...@@ -80,17 +87,16 @@ export const ShowPasswordBehavior = {
* @private * @private
*/ */
onShowPasswordButtonTap_() { onShowPasswordButtonTap_() {
if (this.item.password) { if (this.password) {
this.set('item.password', ''); this.password = '';
return; return;
} }
PasswordManagerImpl.getInstance() PasswordManagerImpl.getInstance()
.requestPlaintextPassword( .requestPlaintextPassword(
this.item.entry.getAnyId(), this.entry.getAnyId(), chrome.passwordsPrivate.PlaintextReason.VIEW)
chrome.passwordsPrivate.PlaintextReason.VIEW)
.then( .then(
password => { password => {
this.set('item.password', password); this.password = password;
}, },
error => { error => {
// <if expr="chromeos"> // <if expr="chromeos">
......
...@@ -6,7 +6,7 @@ import './settings_ui/settings_ui.js'; ...@@ -6,7 +6,7 @@ import './settings_ui/settings_ui.js';
export {AboutPageBrowserProxy, AboutPageBrowserProxyImpl, PromoteUpdaterStatus, UpdateStatus} from './about_page/about_page_browser_proxy.m.js'; export {AboutPageBrowserProxy, AboutPageBrowserProxyImpl, PromoteUpdaterStatus, UpdateStatus} from './about_page/about_page_browser_proxy.m.js';
export {AppearanceBrowserProxy, AppearanceBrowserProxyImpl} from './appearance_page/appearance_browser_proxy.js'; export {AppearanceBrowserProxy, AppearanceBrowserProxyImpl} from './appearance_page/appearance_browser_proxy.js';
export {MultiStorePasswordUiEntry, MultiStorePasswordUiEntryWithPassword} from './autofill_page/multi_store_password_ui_entry.js'; export {MultiStorePasswordUiEntry} from './autofill_page/multi_store_password_ui_entry.js';
export {PasswordManagerImpl, PasswordManagerProxy} from './autofill_page/password_manager_proxy.js'; export {PasswordManagerImpl, PasswordManagerProxy} from './autofill_page/password_manager_proxy.js';
// <if expr="not chromeos"> // <if expr="not chromeos">
export {DefaultBrowserBrowserProxyImpl} from './default_browser_page/default_browser_browser_proxy.js'; export {DefaultBrowserBrowserProxyImpl} from './default_browser_page/default_browser_browser_proxy.js';
......
...@@ -186,10 +186,7 @@ suite('PasswordsAndForms', function() { ...@@ -186,10 +186,7 @@ suite('PasswordsAndForms', function() {
passwordManager.lastCallback.addSavedPasswordListChangedListener(list); passwordManager.lastCallback.addSavedPasswordListChangedListener(list);
flush(); flush();
assertDeepEquals( assertDeepEquals(list, element.$$('#passwordSection').savedPasswords);
list,
element.$$('#passwordSection')
.savedPasswords.map(entry => entry.entry));
// The callback is coming from the manager, so the element shouldn't // The callback is coming from the manager, so the element shouldn't
// have additional calls to the manager after the base expectations. // have additional calls to the manager after the base expectations.
......
...@@ -231,10 +231,8 @@ export class PasswordSectionElementFactory { ...@@ -231,10 +231,8 @@ export class PasswordSectionElementFactory {
*/ */
createPasswordListItem(passwordEntry) { createPasswordListItem(passwordEntry) {
const passwordListItem = this.document.createElement('password-list-item'); const passwordListItem = this.document.createElement('password-list-item');
passwordListItem.item = { passwordListItem.entry = new MultiStorePasswordUiEntry(passwordEntry);
entry: new MultiStorePasswordUiEntry(passwordEntry), passwordListItem.password = '';
password: ''
};
this.document.body.appendChild(passwordListItem); this.document.body.appendChild(passwordListItem);
flush(); flush();
return passwordListItem; return passwordListItem;
...@@ -247,10 +245,8 @@ export class PasswordSectionElementFactory { ...@@ -247,10 +245,8 @@ export class PasswordSectionElementFactory {
*/ */
createPasswordEditDialog(passwordEntry) { createPasswordEditDialog(passwordEntry) {
const passwordDialog = this.document.createElement('password-edit-dialog'); const passwordDialog = this.document.createElement('password-edit-dialog');
passwordDialog.item = { passwordDialog.entry = new MultiStorePasswordUiEntry(passwordEntry);
entry: new MultiStorePasswordUiEntry(passwordEntry), passwordDialog.password = '';
password: ''
};
this.document.body.appendChild(passwordDialog); this.document.body.appendChild(passwordDialog);
flush(); flush();
return passwordDialog; return passwordDialog;
......
...@@ -44,8 +44,7 @@ function validatePasswordList(passwordsSection, passwordList) { ...@@ -44,8 +44,7 @@ function validatePasswordList(passwordsSection, passwordList) {
assertEquals(passwordInfo.urls.link, node.$$('#originUrl').href); assertEquals(passwordInfo.urls.link, node.$$('#originUrl').href);
assertEquals(passwordInfo.username, node.$$('#username').value); assertEquals(passwordInfo.username, node.$$('#username').value);
assertDeepEquals( assertDeepEquals(
listElement.items[index].entry, listElement.items[index], new MultiStorePasswordUiEntry(passwordInfo));
new MultiStorePasswordUiEntry(passwordInfo));
} }
} }
...@@ -186,7 +185,7 @@ suite('PasswordsSection', function() { ...@@ -186,7 +185,7 @@ suite('PasswordsSection', function() {
// then other expectations will also fail. // then other expectations will also fail.
assertDeepEquals( assertDeepEquals(
passwordList.map(entry => new MultiStorePasswordUiEntry(entry)), passwordList.map(entry => new MultiStorePasswordUiEntry(entry)),
passwordsSection.$.passwordList.items.map(entry => entry.entry)); passwordsSection.$.passwordList.items);
validatePasswordList(passwordsSection, passwordList); validatePasswordList(passwordsSection, passwordList);
...@@ -212,9 +211,8 @@ suite('PasswordsSection', function() { ...@@ -212,9 +211,8 @@ suite('PasswordsSection', function() {
passwordList); passwordList);
flush(); flush();
assertFalse(listContainsUrl( assertFalse(
passwordsSection.savedPasswords.map(entry => entry.entry), listContainsUrl(passwordsSection.savedPasswords, 'longwebsite.com'));
'longwebsite.com'));
assertFalse(listContainsUrl(passwordList, 'longwebsite.com')); assertFalse(listContainsUrl(passwordList, 'longwebsite.com'));
validatePasswordList(passwordsSection, passwordList); validatePasswordList(passwordsSection, passwordList);
...@@ -590,7 +588,7 @@ suite('PasswordsSection', function() { ...@@ -590,7 +588,7 @@ suite('PasswordsSection', function() {
assertFalse(passwordDialog.$.showPasswordButton.hidden); assertFalse(passwordDialog.$.showPasswordButton.hidden);
passwordDialog.set('item.password', PASSWORD); passwordDialog.password = PASSWORD;
flush(); flush();
assertEquals(PASSWORD, passwordDialog.$.passwordInput.value); assertEquals(PASSWORD, passwordDialog.$.passwordInput.value);
...@@ -606,7 +604,7 @@ suite('PasswordsSection', function() { ...@@ -606,7 +604,7 @@ suite('PasswordsSection', function() {
// Hidden passwords should be disabled. // Hidden passwords should be disabled.
assertTrue(passwordListItem.$$('#password').disabled); assertTrue(passwordListItem.$$('#password').disabled);
passwordListItem.set('item.password', PASSWORD); passwordListItem.password = PASSWORD;
flush(); flush();
assertEquals(PASSWORD, passwordListItem.$$('#password').value); assertEquals(PASSWORD, passwordListItem.$$('#password').value);
...@@ -626,7 +624,7 @@ suite('PasswordsSection', function() { ...@@ -626,7 +624,7 @@ suite('PasswordsSection', function() {
const expectedItem = createPasswordEntry('goo.gl', 'bart', 1); const expectedItem = createPasswordEntry('goo.gl', 'bart', 1);
const passwordDialog = const passwordDialog =
elementFactory.createPasswordEditDialog(expectedItem); elementFactory.createPasswordEditDialog(expectedItem);
assertEquals('', passwordDialog.item.password); assertEquals('', passwordDialog.password);
passwordManager.setPlaintextPassword('password'); passwordManager.setPlaintextPassword('password');
passwordDialog.$.showPasswordButton.click(); passwordDialog.$.showPasswordButton.click();
...@@ -634,7 +632,7 @@ suite('PasswordsSection', function() { ...@@ -634,7 +632,7 @@ suite('PasswordsSection', function() {
.then(({id, reason}) => { .then(({id, reason}) => {
assertEquals(1, id); assertEquals(1, id);
assertEquals('VIEW', reason); assertEquals('VIEW', reason);
assertEquals('password', passwordDialog.item.password); assertEquals('password', passwordDialog.password);
}); });
}); });
...@@ -642,7 +640,7 @@ suite('PasswordsSection', function() { ...@@ -642,7 +640,7 @@ suite('PasswordsSection', function() {
const expectedItem = createPasswordEntry('goo.gl', 'bart', 1); const expectedItem = createPasswordEntry('goo.gl', 'bart', 1);
const passwordListItem = const passwordListItem =
elementFactory.createPasswordListItem(expectedItem); elementFactory.createPasswordListItem(expectedItem);
assertEquals('', passwordListItem.item.password); assertEquals('', passwordListItem.password);
passwordManager.setPlaintextPassword('password'); passwordManager.setPlaintextPassword('password');
passwordListItem.$$('#showPasswordButton').click(); passwordListItem.$$('#showPasswordButton').click();
...@@ -650,7 +648,7 @@ suite('PasswordsSection', function() { ...@@ -650,7 +648,7 @@ suite('PasswordsSection', function() {
.then(({id, reason}) => { .then(({id, reason}) => {
assertEquals(1, id); assertEquals(1, id);
assertEquals('VIEW', reason); assertEquals('VIEW', reason);
assertEquals('password', passwordListItem.item.password); assertEquals('password', passwordListItem.password);
}); });
}); });
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {BlockingRequestManager} from 'chrome://settings/lazy_load.js'; import {BlockingRequestManager} from 'chrome://settings/lazy_load.js';
import {MultiStorePasswordUiEntryWithPassword, PasswordManagerImpl} from 'chrome://settings/settings.js'; import {MultiStorePasswordUiEntry, PasswordManagerImpl} from 'chrome://settings/settings.js';
import {MockTimer} from 'chrome://test/mock_timer.m.js'; import {MockTimer} from 'chrome://test/mock_timer.m.js';
import {createPasswordEntry, PasswordSectionElementFactory} from 'chrome://test/settings/passwords_and_autofill_fake_data.js'; import {createPasswordEntry, PasswordSectionElementFactory} from 'chrome://test/settings/passwords_and_autofill_fake_data.js';
import {runCancelExportTest, runExportFlowErrorRetryTest, runExportFlowErrorTest, runExportFlowFastTest, runExportFlowSlowTest, runFireCloseEventAfterExportCompleteTest,runStartExportTest} from 'chrome://test/settings/passwords_export_test.js'; import {runCancelExportTest, runExportFlowErrorRetryTest, runExportFlowErrorTest, runExportFlowFastTest, runExportFlowSlowTest, runFireCloseEventAfterExportCompleteTest,runStartExportTest} from 'chrome://test/settings/passwords_export_test.js';
...@@ -49,8 +49,7 @@ suite('PasswordsSection_Cros', function() { ...@@ -49,8 +49,7 @@ suite('PasswordsSection_Cros', function() {
* Tests of the password-section element need to use the full * Tests of the password-section element need to use the full
* implementation, which is created by default when the element is * implementation, which is created by default when the element is
* attached. * attached.
* @param {MultiStorePasswordUiEntryWithPassword} passwordItem Wrapper * @param {MultiStorePasswordUiEntry} passwordItem
* for a PasswordUiEntry and the corresponding password.
*/ */
constructor(document, tokenRequestManager, passwordItem) { constructor(document, tokenRequestManager, passwordItem) {
super(document); super(document);
......
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