-
Notifications
You must be signed in to change notification settings - Fork 6.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[password manager] Extract credential field
Extract the password manager's credential fields (an input with a copy button attached to it) into their own polymer element. This allows reusing the code for the passkey card. Bug: 1432717 Change-Id: I0510f570554fe3c7dede61499407d1195f15a30d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4568597 Reviewed-by: Viktor Semeniuk <vsemeniuk@google.com> Commit-Queue: Nina Satragno <nsatragno@chromium.org> Cr-Commit-Position: refs/heads/main@{#1150779}
- Loading branch information
Showing
11 changed files
with
199 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
chrome/browser/resources/password_manager/credential_field.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<style include="cr-input-style cr-shared-style shared-style"></style> | ||
|
||
<cr-input value="[[value]]" id="inputValue" readonly class="input-field" | ||
label="[[label]]" aria-disabled="true"> | ||
<cr-icon-button id="copyButton" class="icon-copy-content" | ||
slot="inline-suffix" title="[[copyButtonLabel]]" | ||
on-click="onCopyValueClick_"> | ||
</cr-icon-button> | ||
</cr-input> | ||
|
||
<cr-toast id="toast" duration="5000"> | ||
<span>[[valueCopiedToastLabel]]</span> | ||
</cr-toast> |
93 changes: 93 additions & 0 deletions
93
chrome/browser/resources/password_manager/credential_field.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
import {CrToastElement} from '//resources/cr_elements/cr_toast/cr_toast.js'; | ||
import {CrIconButtonElement} from 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; | ||
import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js'; | ||
import {assert} from 'chrome://resources/js/assert_ts.js'; | ||
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; | ||
|
||
import {getTemplate} from './credential_field.html.js'; | ||
import {PasswordManagerImpl, PasswordViewPageInteractions} from './password_manager_proxy.js'; | ||
|
||
export interface CredentialFieldElement { | ||
$: { | ||
inputValue: CrInputElement, | ||
copyButton: CrIconButtonElement, | ||
toast: CrToastElement, | ||
}; | ||
} | ||
|
||
// An element that represents a credential field with a 'copy' button. | ||
export class CredentialFieldElement extends PolymerElement { | ||
static get is() { | ||
return 'credential-field'; | ||
} | ||
|
||
static get template() { | ||
return getTemplate(); | ||
} | ||
|
||
static get properties() { | ||
return { | ||
/** | ||
* The label on the actual input element. Required. | ||
*/ | ||
label: String, | ||
|
||
/** | ||
* The label on the copy button. Required. | ||
*/ | ||
copyButtonLabel: String, | ||
|
||
/** | ||
* Text that appears on the toast when clicking the copy button. | ||
* Required. | ||
*/ | ||
valueCopiedToastLabel: String, | ||
|
||
/** | ||
* Field value. | ||
*/ | ||
value: String, | ||
|
||
/** | ||
* If set, clicking the copy button will record this password view | ||
* interaction. | ||
*/ | ||
interactionId: PasswordViewPageInteractions, | ||
}; | ||
} | ||
|
||
label: string; | ||
copyButtonLabel: string; | ||
valueCopiedToastLabel: string; | ||
value: string; | ||
interactionId: PasswordViewPageInteractions; | ||
|
||
override connectedCallback() { | ||
super.connectedCallback(); | ||
assert(this.label); | ||
assert(this.copyButtonLabel); | ||
assert(this.valueCopiedToastLabel); | ||
} | ||
|
||
private onCopyValueClick_() { | ||
navigator.clipboard.writeText(this.value).catch(() => {}); | ||
this.$.toast.show(); | ||
PasswordManagerImpl.getInstance().extendAuthValidity(); | ||
if (this.interactionId) { | ||
PasswordManagerImpl.getInstance().recordPasswordViewInteraction( | ||
this.interactionId); | ||
} | ||
} | ||
} | ||
|
||
declare global { | ||
interface HTMLElementTagNameMap { | ||
'credential-field': CredentialFieldElement; | ||
} | ||
} | ||
|
||
customElements.define(CredentialFieldElement.is, CredentialFieldElement); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
chrome/test/data/webui/password_manager/credential_field_test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
import 'chrome://password-manager/password_manager.js'; | ||
|
||
import {CredentialFieldElement, Page, PasswordManagerImpl, PasswordViewPageInteractions, Router} from 'chrome://password-manager/password_manager.js'; | ||
import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; | ||
import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; | ||
|
||
import {TestPasswordManagerProxy} from './test_password_manager_proxy.js'; | ||
|
||
const LABEL = 'Username'; | ||
const COPY_BUTTON_LABEL = 'Copy username'; | ||
const VALUE_COPIED_TOAST_LABEL = 'Username copied!'; | ||
const VALUE = 'nadeshiko@example.com'; | ||
const INTERACTION_ID = | ||
PasswordViewPageInteractions.USERNAME_COPY_BUTTON_CLICKED; | ||
|
||
async function createCredentialFieldElement(): Promise<CredentialFieldElement> { | ||
const element = document.createElement('credential-field'); | ||
element.label = LABEL; | ||
element.copyButtonLabel = COPY_BUTTON_LABEL; | ||
element.valueCopiedToastLabel = VALUE_COPIED_TOAST_LABEL; | ||
element.value = VALUE; | ||
element.interactionId = INTERACTION_ID; | ||
document.body.appendChild(element); | ||
await flushTasks(); | ||
return element; | ||
} | ||
|
||
suite('CredentialFieldTest', function() { | ||
let passwordManager: TestPasswordManagerProxy; | ||
|
||
setup(function() { | ||
document.body.innerHTML = window.trustedTypes!.emptyHTML; | ||
passwordManager = new TestPasswordManagerProxy(); | ||
PasswordManagerImpl.setInstance(passwordManager); | ||
Router.getInstance().navigateTo(Page.PASSWORDS); | ||
return flushTasks(); | ||
}); | ||
|
||
test('element sets all the attributes', async function() { | ||
const element = await createCredentialFieldElement(); | ||
assertEquals(element.$.inputValue.value, VALUE); | ||
assertEquals(element.$.inputValue.label, LABEL); | ||
assertEquals(element.$.copyButton.title, COPY_BUTTON_LABEL); | ||
}); | ||
|
||
test('copy value', async function() { | ||
const element = await createCredentialFieldElement(); | ||
assertFalse(element.$.toast.open); | ||
|
||
element.$.copyButton.click(); | ||
await passwordManager.whenCalled('extendAuthValidity'); | ||
assertEquals( | ||
INTERACTION_ID, | ||
await passwordManager.whenCalled('recordPasswordViewInteraction')); | ||
|
||
assertTrue(element.$.toast.open); | ||
assertEquals(VALUE_COPIED_TOAST_LABEL, element.$.toast.textContent!.trim()); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters