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

[b4p/Settings] Factor out code in passwords settings usable by new page

This CL prepares for the introduction of the new "passwords on device"
WebUI page. It extracts the logic that is common with the existing page
into a new PasswordsListHandler Polymer component. This includes mostly
handling requests for copying a password, viewing its details (Edit
Dialog) and removing it. The new component does not own the list of
saved passwords, those are still retrieved by its embedder. The lists
with different subsets of saved passwords (all, device-only or
device+account) will be injected by the embedder as well.

Bug: 1049141
Change-Id: Iefb9e6bd7d58f43ff4ed57f74983f939b0e1eb40
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2224860
Commit-Queue: Victor Vianna <victorvianna@google.com>
Reviewed-by: default avatarFriedrich [CET] <fhorschig@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Cr-Commit-Position: refs/heads/master@{#774549}
parent f371a172
......@@ -27,6 +27,7 @@ js_type_check("closure_compile_module") {
":password_manager_proxy",
":password_remove_confirmation_dialog",
":passwords_export_dialog",
":passwords_list_handler",
":passwords_section",
":payments_list",
":payments_section",
......@@ -181,6 +182,22 @@ js_library("password_list_item") {
]
}
js_library("passwords_list_handler") {
deps = [
":blocking_request_manager",
":multi_store_password_ui_entry",
":password_edit_dialog",
":password_manager_proxy",
":remove_password_behavior",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
"//ui/webui/resources/cr_elements/cr_toast:cr_toast_manager.m",
"//ui/webui/resources/js:assert.m",
"//ui/webui/resources/js:i18n_behavior.m",
"//ui/webui/resources/js/cr/ui:focus_without_ink.m",
]
}
js_library("password_manager_proxy") {
deps = [ "//ui/webui/resources/js:cr.m" ]
externs_list = [ "$externs_path/passwords_private.js" ]
......@@ -196,10 +213,9 @@ js_library("passwords_export_dialog") {
js_library("passwords_section") {
deps = [
":multi_store_password_ui_entry",
":password_edit_dialog",
":password_list_item",
":password_manager_proxy",
":remove_password_behavior",
":passwords_list_handler",
"..:global_scroll_target_behavior.m",
"..:route",
"../people_page:sync_browser_proxy.m",
......@@ -207,7 +223,6 @@ js_library("passwords_section") {
"//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
"//third_party/polymer/v3_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
"//ui/webui/resources/cr_elements/cr_toast:cr_toast_manager.m",
"//ui/webui/resources/js:assert.m",
"//ui/webui/resources/js:i18n_behavior.m",
"//ui/webui/resources/js:list_property_update_behavior.m",
......@@ -276,6 +291,7 @@ html_to_js("web_components") {
"address_edit_dialog.js",
"autofill_page.js",
"autofill_section.js",
"passwords_list_handler.js",
"credit_card_edit_dialog.js",
"credit_card_list_entry.js",
"password_check_edit_dialog.js",
......
<style>
#undoLabel {
display: flex;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
<slot name="body"></slot>
<cr-action-menu id="menu" role-description="$i18n{menu}">
<template is="dom-if" if="[[enablePasswordCheck_]]">
<button id="menuCopyPassword" class="dropdown-item"
on-click="onMenuCopyPasswordButtonTap_"
hidden$="[[activePassword.entry.federationText]]">
$i18n{copyPassword}
</button>
</template>
<button id="menuEditPassword" class="dropdown-item"
on-click="onMenuEditPasswordTap_">$i18n{passwordViewDetails}</button>
<button id="menuRemovePassword" class="dropdown-item"
on-click="onMenuRemovePasswordTap_">$i18n{removePassword}</button>
</cr-action-menu>
<template is="dom-if" if="[[showPasswordEditDialog_]]" restamp>
<password-edit-dialog on-close="onPasswordEditDialogClosed_"
id="passwordEditDialog"
<if expr="chromeos">
token-request-manager="[[tokenRequestManager_]]"
</if>
entry="[[activePassword.entry]]"
password="{{activePassword.password}}"
should-show-storage-details=
"[[shouldShowStorageDetails]]">
</password-edit-dialog>
</template>
<cr-toast-manager duration="5000">
<cr-button aria-label="$i18n{undoDescription}"
on-click="onUndoButtonClick_">$i18n{undoRemovePassword}</cr-button>
</cr-toast-manager>
// 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 PasswordsListHandler is a container for a passwords list
* responsible for handling events such as copy, editing and removal.
*/
import './password_edit_dialog.js';
import './password_list_item.js';
import 'chrome://resources/cr_elements/shared_style_css.m.js';
import './password_edit_dialog.js';
import {getToastManager} from 'chrome://resources/cr_elements/cr_toast/cr_toast_manager.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 {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {loadTimeData} from '../i18n_setup.js';
// <if expr="chromeos">
import {BlockingRequestManager} from './blocking_request_manager.js';
// </if>
import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js';
import {PasswordManagerImpl} from './password_manager_proxy.js';
import {RemovalResult} from './remove_password_behavior.js';
Polymer({
is: 'passwords-list-handler',
_template: html`{__html_template__}`,
properties: {
/**
* The model for any active menus or dialogs. The value is reset to null
* whenever actions from the menus/dialogs are concluded.
* @private {?PasswordListItemElement}
*/
activePassword: {
type: Object,
value: null,
},
/**
* Whether the edit dialog and removal notification should show information
* about which location(s) a password is stored.
*/
shouldShowStorageDetails: {
type: Boolean,
value: false,
},
// <if expr="chromeos">
/** @type {BlockingRequestManager} */
tokenRequestManager: Object,
// </if>
/** @private */
enablePasswordCheck_: {
type: Boolean,
value() {
return loadTimeData.getBoolean('enablePasswordCheck');
}
},
/** @private */
showPasswordEditDialog_: {type: Boolean, value: false},
/**
* The element to return focus to, when the currently active dialog is
* closed.
* @private {?HTMLElement}
*/
activeDialogAnchorElement_: {type: Object, value: null},
},
behaviors: [
I18nBehavior,
],
listeners: {
'password-menu-tap': 'onPasswordMenuTap_',
},
/** @override */
detached() {
if (getToastManager().isToastOpen) {
getToastManager().hide();
}
},
/**
* Closes the toast manager.
*/
onSavedPasswordOrExceptionRemoved() {
getToastManager().hide();
},
/**
* Opens the password action menu.
* @param {!Event<!{target: !HTMLElement, listItem:
* !PasswordListItemElement}>} event
* @private
*/
onPasswordMenuTap_(event) {
const target = event.detail.target;
this.activePassword = event.detail.listItem;
this.$.menu.showAt(target);
this.activeDialogAnchor_ = target;
},
/**
* Shows the edit password dialog.
* @param {!Event} e
* @private
*/
onMenuEditPasswordTap_(e) {
e.preventDefault();
this.$.menu.close();
this.showPasswordEditDialog_ = true;
},
/** @private */
onPasswordEditDialogClosed_() {
this.showPasswordEditDialog_ = false;
focusWithoutInk(assert(this.activeDialogAnchor_));
this.activeDialogAnchor_ = null;
this.activePassword = null;
},
/**
* Copy selected password to clipboard.
* @private
*/
onMenuCopyPasswordButtonTap_() {
// Copy to clipboard occurs inside C++ and we don't expect getting
// result back to javascript.
PasswordManagerImpl.getInstance()
.requestPlaintextPassword(
this.activePassword.entry.getAnyId(),
chrome.passwordsPrivate.PlaintextReason.COPY)
.then(() => {
this.activePassword = null;
})
.catch(error => {
// <if expr="chromeos">
// If no password was found, refresh auth token and retry.
this.tokenRequestManager.request(
this.onMenuCopyPasswordButtonTap_.bind(this));
// </if>});
});
this.$.menu.close();
},
/**
* Fires an event that should delete the saved password.
* @private
*/
onMenuRemovePasswordTap_() {
// TODO(crbug.com/1049141): Open removal dialog if password is present in
// both locations. Add tests for when no password is selected in the dialog.
/** @type {!RemovalResult} */
const result = this.activePassword.requestRemove();
if (!result.removedFromDevice && !result.removedFromAccount) {
this.$.menu.close();
this.activePassword = null;
return;
}
let text = this.i18n('passwordDeleted');
if (this.shouldShowStorageDetails) {
if (result.removedFromAccount && result.removedFromDevice) {
text = this.i18n('passwordDeletedFromAccountAndDevice');
} else if (result.removedFromAccount) {
text = this.i18n('passwordDeletedFromAccount');
} else {
text = this.i18n('passwordDeletedFromDevice');
}
}
getToastManager().show(text);
this.fire('iron-announce', {text: this.i18n('undoDescription')});
this.$.menu.close();
this.activePassword = null;
},
onUndoButtonClick_() {
PasswordManagerImpl.getInstance().undoRemoveSavedPasswordOrException();
this.onSavedPasswordOrExceptionRemoved();
},
});
......@@ -8,14 +8,6 @@
var(--cr-icon-ripple-size) + var(--cr-icon-button-margin-start));
}
#undoLabel {
display: flex;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#exportImportMenuButtonContainer {
margin-inline-end: 0;
}
......@@ -151,54 +143,48 @@
aria-describedby="savedPasswordsHeading"></cr-icon-button>
</template>
</div>
<div class="list-frame">
<div id="savedPasswordsHeaders" class="list-item column-header"
hidden$="[[!hasSome_(savedPasswords, savedPasswords.splices)]]"
aria-hidden="true">
<div class="website-column">$i18n{editPasswordWebsiteLabel}</div>
<div class="username-column">
$i18n{editPasswordUsernameLabel}
</div>
<div class="password-column">
$i18n{editPasswordPasswordLabel}
<passwords-list-handler id="passwordsListHandler"
<if expr="chromeos">
token-request-manager="[[tokenRequestManager_]]"
</if>
should-show-storage-details="[[shouldShowStorageDetails_]]">
<div slot="body" class="list-frame">
<div id="savedPasswordsHeaders" class="list-item column-header"
hidden$="[[!hasSome_(savedPasswords, savedPasswords.splices)]]"
aria-hidden="true">
<div class="website-column">$i18n{editPasswordWebsiteLabel}</div>
<div class="username-column">
$i18n{editPasswordUsernameLabel}
</div>
<div class="password-column">
$i18n{editPasswordPasswordLabel}
</div>
</div>
</div>
<iron-list id="passwordList" preserve-focus
items="[[getFilteredPasswords_(filter,
savedPasswords.splices, isOptedInForAccountStorage_)]]"
class="cr-separators list-with-header"
scroll-target="[[subpageScrollTarget]]" risk-selection>
<template>
<!-- The entry property is shared by ShowPasswordBehavior and
RemovePasswordBehavior. -->
<password-list-item entry="[[item]]"
tabindex$="[[tabIndex]]" focus-row-index="[[index]]"
<iron-list id="passwordList" preserve-focus
items="[[getFilteredPasswords_(filter,
savedPasswords.splices, isOptedInForAccountStorage_)]]"
class="cr-separators list-with-header"
scroll-target="[[subpageScrollTarget]]" risk-selection>
<template>
<!-- The entry property is shared by ShowPasswordBehavior and
RemovePasswordBehavior. -->
<password-list-item entry="[[item]]"
tabindex$="[[tabIndex]]" focus-row-index="[[index]]"
<if expr="chromeos">
token-request-manager="[[tokenRequestManager_]]"
token-request-manager="[[tokenRequestManager_]]"
</if>
first$="[[!index]]" iron-list-tab-index="[[tabIndex]]"
last-focused="{{lastFocused_}}" list-blurred="{{listBlurred_}}">
</password-list-item>
</template>
</iron-list>
<div id="noPasswordsLabel" class="list-item"
hidden$="[[hasSome_(savedPasswords, savedPasswords.splices)]]">
$i18n{noPasswordsFound}
first$="[[!index]]" iron-list-tab-index="[[tabIndex]]"
last-focused="{{lastFocused_}}" list-blurred="{{listBlurred_}}">
</password-list-item>
</template>
</iron-list>
<div id="noPasswordsLabel" class="list-item"
hidden$="[[hasSome_(savedPasswords, savedPasswords.splices)]]">
$i18n{noPasswordsFound}
</div>
</div>
</div>
<cr-action-menu id="menu" role-description="$i18n{menu}">
<template is="dom-if" if="[[enablePasswordCheck_]]">
<button id="menuCopyPassword" class="dropdown-item"
on-click="onMenuCopyPasswordButtonTap_"
hidden$="[[activePassword.entry.federationText]]">
$i18n{copyPassword}
</button>
</template>
<button id="menuEditPassword" class="dropdown-item"
on-click="onMenuEditPasswordTap_">$i18n{passwordViewDetails}</button>
<button id="menuRemovePassword" class="dropdown-item"
on-click="onMenuRemovePasswordTap_">$i18n{removePassword}</button>
</cr-action-menu>
</passwords-list-handler>
<cr-action-menu id="exportImportMenu" role-description="$i18n{menu}">
<button id="menuImportPassword" class="dropdown-item"
on-click="onImportTap_" hidden="[[!showImportPasswords_]]">
......@@ -217,18 +203,6 @@
on-passwords-export-dialog-close="onPasswordsExportDialogClosed_">
</passwords-export-dialog>
</template>
<template is="dom-if" if="[[showPasswordEditDialog_]]" restamp>
<password-edit-dialog on-close="onPasswordEditDialogClosed_"
id="passwordEditDialog"
<if expr="chromeos">
token-request-manager="[[tokenRequestManager_]]"
</if>
entry="[[activePassword.entry]]"
password="{{activePassword.password}}"
should-show-storage-details=
"[[shouldShowStorageDetailsInEditDialog_]]">
</password-edit-dialog>
</template>
<if expr="chromeos">
<template is="dom-if" if="[[showPasswordPromptDialog_]]" restamp>
<settings-password-prompt-dialog on-token-obtained="onTokenObtained_"
......@@ -236,11 +210,6 @@
</settings-password-prompt-dialog>
</template>
</if>
<cr-toast-manager duration="5000">
<cr-button aria-label="$i18n{undoDescription}"
on-click="onUndoButtonClick_">$i18n{undoRemovePassword}</cr-button>
</cr-toast-manager>
<div class="cr-row first">
<h2 class="flex">$i18n{passwordExceptionsHeading}</h2>
</div>
......
......@@ -19,7 +19,6 @@ 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_icon_button/cr_icon_button.m.js';
import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.m.js';
import {getToastManager} from 'chrome://resources/cr_elements/cr_toast/cr_toast_manager.m.js';
import 'chrome://resources/cr_elements/icons.m.js';
import 'chrome://resources/cr_elements/shared_style_css.m.js';
import {assert} from 'chrome://resources/js/assert.m.js';
......@@ -36,7 +35,6 @@ import '../controls/extension_controlled_indicator.m.js';
import '../controls/settings_toggle_button.m.js';
import {GlobalScrollTargetBehavior} from '../global_scroll_target_behavior.m.js';
import {loadTimeData} from '../i18n_setup.js';
import {RemovalResult} from './remove_password_behavior.js';
import {SyncBrowserProxyImpl, SyncPrefs, SyncStatus} from '../people_page/sync_browser_proxy.m.js';
import '../prefs/prefs.m.js';
import {PrefsBehavior} from '../prefs/prefs_behavior.m.js';
......@@ -45,8 +43,8 @@ import {Router} from '../router.m.js';
import '../settings_shared_css.m.js';
import '../site_favicon.js';
import {PasswordCheckBehavior} from './password_check_behavior.js';
import './password_edit_dialog.js';
import './password_list_item.js';
import './passwords_list_handler.js';
import {PasswordManagerImpl, PasswordManagerProxy} from './password_manager_proxy.js';
import './passwords_export_dialog.js';
import './passwords_shared_css.js';
......@@ -55,7 +53,6 @@ import '../controls/password_prompt_dialog.m.js';
import {BlockingRequestManager} from './blocking_request_manager.js';
// </if>
/**
* Checks if an HTML element is an editable. An editable is either a text
* input or a text area.
......@@ -122,12 +119,6 @@ Polymer({
value: routes.PASSWORDS,
},
/**
* The model for any password related action menus or dialogs.
* @private {?PasswordListItemElement}
*/
activePassword: Object,
/** The target of the key bindings defined below. */
keyEventTarget: {
type: Object,
......@@ -174,10 +165,14 @@ Polymer({
'signedIn_, hasNeverCheckedPasswords_, hasStoredPasswords_)',
},
shouldShowStorageDetailsInEditDialog_: {
/**
* Whether the edit dialog and removal notification should show
* information about which location(s) a password is stored.
*/
shouldShowStorageDetails_: {
type: Boolean,
value: false,
computed: 'computeShouldShowStorageDetailsInEditDialog_(' +
computed: 'computeShouldShowStorageDetails_(' +
'eligibleForAccountStorage_, isOptedInForAccountStorage_)',
},
......@@ -216,9 +211,6 @@ Polymer({
}
},
/** @private */
showPasswordEditDialog_: Boolean,
/** @private */
isOptedInForAccountStorage_: Boolean,
......@@ -249,10 +241,6 @@ Polymer({
// </if>
},
listeners: {
'password-menu-tap': 'onPasswordMenuTap_',
},
keyBindings: {
// <if expr="is_macosx">
'meta+z': 'onUndoKeyBinding_',
......@@ -384,10 +372,6 @@ Polymer({
assert(this.setPasswordExceptionsListener_));
this.passwordManager_.removeAccountStorageOptInStateListener(
assert(this.setIsOptedInForAccountStorageListener_));
if (getToastManager().isToastOpen) {
getToastManager().hide();
}
},
/**
......@@ -433,23 +417,6 @@ Polymer({
},
// </if>
/**
* Shows the edit password dialog.
* @param {!Event} e
* @private
*/
onMenuEditPasswordTap_(e) {
e.preventDefault();
/** @type {CrActionMenuElement} */ (this.$.menu).close();
this.showPasswordEditDialog_ = true;
},
/** @private */
onPasswordEditDialogClosed_() {
this.showPasswordEditDialog_ = false;
focusWithoutInk(assert(this.activeDialogAnchorStack_.pop()));
},
/**
* @return {boolean}
* @private
......@@ -506,7 +473,7 @@ Polymer({
* @return {boolean}
* @private
*/
computeShouldShowStorageDetailsInEditDialog_() {
computeShouldShowStorageDetails_() {
return this.eligibleForAccountStorage_ && this.isOptedInForAccountStorage_;
},
......@@ -545,79 +512,25 @@ Polymer({
},
/**
* Fires an event that should delete the saved password.
* @private
*/
onMenuRemovePasswordTap_() {
// TODO(crbug.com/1049141): Open removal dialog if password is present in
// both locations. Add tests for when no password is selected in the dialog.
/** @type {!RemovalResult} */
const result = this.activePassword.requestRemove();
if (!result.removedFromDevice && !result.removedFromAccount) {
/** @type {CrActionMenuElement} */ (this.$.menu).close();
return;
}
let text = this.i18n('passwordDeleted');
if (this.eligibleForAccountStorage_ && this.isOptedInForAccountStorage_) {
if (result.removedFromAccount && result.removedFromDevice) {
text = this.i18n('passwordDeletedFromAccountAndDevice');
} else if (result.removedFromAccount) {
text = this.i18n('passwordDeletedFromAccount');
} else {
text = this.i18n('passwordDeletedFromDevice');
}
}
getToastManager().show(text);
this.fire('iron-announce', {text: this.i18n('undoDescription')});
/** @type {CrActionMenuElement} */ (this.$.menu).close();
},
/**
* Copy selected password to clipboard.
* @private
*/
onMenuCopyPasswordButtonTap_() {
// Copy to clipboard occurs inside C++ and we don't expect getting
// result back to javascript.
this.passwordManager_
.requestPlaintextPassword(
this.activePassword.entry.getAnyId(),
chrome.passwordsPrivate.PlaintextReason.COPY)
.catch(error => {
// <if expr="chromeos">
// If no password was found, refresh auth token and retry.
this.tokenRequestManager_.request(
this.onMenuCopyPasswordButtonTap_.bind(this));
// </if>});
});
(this.$.menu).close();
},
/**
* Handle the undo shortcut.
* Handle the shortcut to undo a removal of passwords/exceptions. This must
* be handled here and not at the PasswordsListHandler level because that
* component does not know about exception deletions.
* @param {!Event} event
* @private
*/
onUndoKeyBinding_(event) {
const activeElement = getDeepActiveElement();
// If the focused element is editable (e.g. search box) the undo event
// should be handled there and not here.
if (!activeElement || !isEditable(activeElement)) {
this.passwordManager_.undoRemoveSavedPasswordOrException();
getToastManager().hide();
this.$.passwordsListHandler.onSavedPasswordOrExceptionRemoved();
// Preventing the default is necessary to not conflict with a possible
// search action.
event.preventDefault();
}
},
/** @private */
onUndoButtonClick_() {
this.passwordManager_.undoRemoveSavedPasswordOrException();
getToastManager().hide();
},
/**
* Fires an event that should delete the password exception.
* @param {!ExceptionEntryEntryEvent} e The polymer event.
......@@ -627,21 +540,6 @@ Polymer({
this.passwordManager_.removeException(e.model.item.id);
},
/**
* Opens the password action menu.
* @param {!Event} event
* @private
*/
onPasswordMenuTap_(event) {
const menu = /** @type {!CrActionMenuElement} */ (this.$.menu);
const target = /** @type {!HTMLElement} */ (event.detail.target);
this.activePassword =
/** @type {!PasswordListItemElement} */ (event.detail.listItem);
menu.showAt(target);
this.activeDialogAnchorStack_.push(target);
},
/**
* Opens the export/import action menu.
* @private
......
......@@ -119,6 +119,11 @@
file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_list_item.js"
use_base_dir="false"
compress="false" type="BINDATA" />
<include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORDS_LIST_HANDLER_JS"
file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js"
use_base_dir="false"
compress="false" type="BINDATA"
preprocess="true"/>
<include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_MANAGER_PROXY_JS"
file="autofill_page/password_manager_proxy.js"
compress="false" type="BINDATA" />
......
......@@ -467,7 +467,7 @@ suite('PasswordsSection', function() {
// Click the remove button on the first password.
firstNode.$$('#passwordMenu').click();
passwordsSection.$.menuRemovePassword.click();
passwordsSection.$.passwordsListHandler.$.menuRemovePassword.click();
const ids = await passwordManager.whenCalled('removeSavedPasswords');
// Verify that the expected value was passed to the proxy.
......@@ -489,7 +489,8 @@ suite('PasswordsSection', function() {
flush();
getFirstPasswordListItem(passwordsSection).$$('#passwordMenu').click();
assertTrue(passwordsSection.$$('#menuCopyPassword').hidden);
assertTrue(
passwordsSection.$.passwordsListHandler.$$('#menuCopyPassword').hidden);
});
// Test verifies that 'Copy password' button is not hidden for common
......@@ -503,7 +504,8 @@ suite('PasswordsSection', function() {
flush();
getFirstPasswordListItem(passwordsSection).$$('#passwordMenu').click();
assertFalse(passwordsSection.$$('#menuCopyPassword').hidden);
assertFalse(
passwordsSection.$.passwordsListHandler.$$('#menuCopyPassword').hidden);
});
test('verifyFilterPasswords', function() {
......@@ -862,7 +864,7 @@ suite('PasswordsSection', function() {
passwordManager, [expectedItem], []);
getFirstPasswordListItem(passwordsSection).$$('#passwordMenu').click();
passwordsSection.$$('#menuCopyPassword').click();
passwordsSection.$.passwordsListHandler.$$('#menuCopyPassword').click();
return passwordManager.whenCalled('requestPlaintextPassword')
.then(({id, reason}) => {
......@@ -881,7 +883,7 @@ suite('PasswordsSection', function() {
// Click the remove button on the first password and assert that an undo
// toast is shown.
getFirstPasswordListItem(passwordsSection).$$('#passwordMenu').click();
passwordsSection.$.menuRemovePassword.click();
passwordsSection.$.passwordsListHandler.$.menuRemovePassword.click();
assertTrue(toastManager.isToastOpen);
// Remove the passwords section from the DOM and check that this closes
......@@ -1100,13 +1102,13 @@ suite('PasswordsSection', function() {
// No removal actually happens, so all passwords keep their position.
// The merged entry comes last.
passwordListItems[0].$$('#passwordMenu').click();
passwordsSection.$.menuRemovePassword.click();
passwordsSection.$.passwordsListHandler.$.menuRemovePassword.click();
assertEquals(
passwordsSection.i18n('passwordDeletedFromAccount'),
getToastManager().$.content.textContent);
passwordListItems[1].$$('#passwordMenu').click();
passwordsSection.$.menuRemovePassword.click();
passwordsSection.$.passwordsListHandler.$.menuRemovePassword.click();
assertEquals(
passwordsSection.i18n('passwordDeletedFromDevice'),
getToastManager().$.content.textContent);
......@@ -1114,7 +1116,7 @@ suite('PasswordsSection', function() {
// TODO(crbug.com/1049141): Update the test when the removal dialog
// is introduced.
passwordListItems[2].$$('#passwordMenu').click();
passwordsSection.$.menuRemovePassword.click();
passwordsSection.$.passwordsListHandler.$.menuRemovePassword.click();
assertEquals(
passwordsSection.i18n('passwordDeletedFromAccountAndDevice'),
getToastManager().$.content.textContent);
......
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