Skip to content

Commit

Permalink
[Passwords] Disable share button according to policy
Browse files Browse the repository at this point in the history
Impl: https://screenshot.googleplex.com/868f9udimCAPLKu.png
Mock: https://screenshot.googleplex.com/9aVhHVGHn53dUKU.png

Bug: 1445526
Change-Id: I71d4e85e4dc3af2f4bf9daa98ccb7daace827784
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4976452
Reviewed-by: Viktor Semeniuk <vsemeniuk@google.com>
Auto-Submit: Andrii Natiahlyi <natiahlyi@google.com>
Reviewed-by: Vasilii Sukhanov <vasilii@chromium.org>
Commit-Queue: Vasilii Sukhanov <vasilii@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1216110}
  • Loading branch information
Andrii Natiahlyi authored and Chromium LUCI CQ committed Oct 27, 2023
1 parent 461752a commit d19f3d6
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 25 deletions.
3 changes: 3 additions & 0 deletions chrome/app/password_manager_ui_strings.grdp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@
<message name="IDS_PASSWORD_MANAGER_UI_SHARE_PASSWORD_MEMBER_UNAVAILABLE" desc="The text on the tooltip for password sharing recipient. It is shown when the recipient (Google Family member) is unable to receive passwords.">
Your family member can't receive passwords right now. Ask them to update Chrome and sync their passwords.
</message>
<message name="IDS_PASSWORD_MANAGER_UI_SHARING_IS_MANAGED_BY_ADMIN" desc="The text shown on the tooltip next to the disabled password share button.">
Password sharing is managed by your administrator
</message>
<message name="IDS_PASSWORD_MANAGER_UI_SHARE_PASSWORD_NOT_AVAILABLE" desc="The text on the password sharing recipient row. It is shown when the recipient (Google Family member) is unable to receive passwords.">
Not available
</message>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4d903ce823168ddab27f752e98de278210a31caf
2 changes: 2 additions & 0 deletions chrome/browser/extensions/api/settings_private/prefs_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetAllowlistedKeys() {
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_allowlist)[password_manager::prefs::kCredentialsEnableAutosignin] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_allowlist)[password_manager::prefs::kPasswordSharingEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_allowlist)[password_manager::prefs::kPasswordLeakDetectionEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_allowlist)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@
display: flex;
}

#shareButton {
.share-button-container {
margin-inline-start: auto;
display: flex;
}

cr-tooltip-icon {
margin-block: auto;
margin-inline-end: 16px;
}
</style>
<div class="card">
Expand Down Expand Up @@ -68,10 +74,17 @@
<cr-button id="deleteButton" on-click="onDeleteClick_">
$i18n{deletePassword}
</cr-button>
<cr-button id="shareButton" on-click="onShareButtonClick_"
hidden="[[!showShareButton_]]">
$i18n{share}
</cr-button>
<div class="share-button-container" hidden="[[!showShareButton_]]">
<cr-tooltip-icon icon-class="cr20:domain"
hidden="[[!passwordSharingDisabled_]]"
tooltip-text="$i18n{sharePasswordManagedByAdmin}"
icon-aria-label="$i18n{sharePasswordManagedByAdmin}">
</cr-tooltip-icon>
<cr-button id="shareButton" on-click="onShareButtonClick_"
disabled="[[passwordSharingDisabled_]]">
$i18n{share}
</cr-button>
</div>
<template is="dom-if" if="[[showShareFlow_]]" restamp>
<share-password-flow password-name="[[groupName]]" icon-url="[[iconUrl]]"
password="[[password]]" on-share-flow-done="onShareFlowDone_">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'chrome://resources/cr_elements/cr_icons.css.js';
import 'chrome://resources/cr_elements/cr_input/cr_input.js';
import 'chrome://resources/cr_elements/cr_shared_style.css.js';
import 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
import 'chrome://resources/cr_elements/policy/cr_tooltip_icon.js';
import '../shared_style.css.js';
import './credential_details_card.css.js';
import '../dialogs/edit_password_dialog.js';
Expand All @@ -17,6 +18,7 @@ import '../sharing/metrics_utils.js';

import {CrToastElement} from '//resources/cr_elements/cr_toast/cr_toast.js';
import {HelpBubbleMixin} from 'chrome://resources/cr_components/help_bubble/help_bubble_mixin.js';
import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.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';
Expand Down Expand Up @@ -57,12 +59,12 @@ export interface PasswordDetailsCardElement {
showPasswordButton: CrIconButtonElement,
toast: CrToastElement,
usernameValue: CredentialFieldElement,
shareButton: HTMLButtonElement,
shareButton: CrButtonElement,
};
}

const PasswordDetailsCardElementBase = HelpBubbleMixin(
UserUtilMixin(ShowPasswordMixin(I18nMixin(PolymerElement))));
const PasswordDetailsCardElementBase = PrefsMixin(HelpBubbleMixin(
UserUtilMixin(ShowPasswordMixin(I18nMixin(PolymerElement)))));

export class PasswordDetailsCardElement extends PasswordDetailsCardElementBase {
static get is() {
Expand Down Expand Up @@ -95,6 +97,13 @@ export class PasswordDetailsCardElement extends PasswordDetailsCardElementBase {
'isOptedInForAccountStorage, isSyncingPasswords)',
},

passwordSharingDisabled_: {
type: Boolean,
computed: 'computePasswordSharingDisabled_(' +
'prefs.password_manager.password_sharing_enabled.enforcement, ' +
'prefs.password_manager.password_sharing_enabled.value)',
},

showShareFlow_: {
type: Boolean,
value: false,
Expand All @@ -114,6 +123,7 @@ export class PasswordDetailsCardElement extends PasswordDetailsCardElementBase {
iconUrl: string;
private toastMessage_: string;
private showEditPasswordDialog_: boolean;
private passwordSharingDisabled_: boolean;
private showDeletePasswordDialog_: boolean;
private showShareFlow_: boolean;
private showShareButton_: boolean;
Expand Down Expand Up @@ -229,8 +239,14 @@ export class PasswordDetailsCardElement extends PasswordDetailsCardElementBase {
(this.isSyncingPasswords || this.isOptedInForAccountStorage);
}

private computePasswordSharingDisabled_(): boolean {
const pref = this.getPref('password_manager.password_sharing_enabled');
return pref.enforcement === chrome.settingsPrivate.Enforcement.ENFORCED &&
!pref.value;
}

maybeRegisterSharingHelpBubble(): void {
if (!this.showShareButton_) {
if (!this.showShareButton_ && !this.passwordSharingDisabled_) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@
<h2 id="title" class="page-title text-elide">[[selectedGroup_.name]]</h2>
</div>
<template is="dom-if" if="[[selectedGroup_.name]]">
<template is="dom-repeat" initial-count="10"
<template is="dom-repeat" initial-count="10"
items="[[selectedGroup_.entries]]">
<template is="dom-if" if="[[item.isPasskey]]">
<passkey-details-card passkey="[[item]]"></passkey-details-card>
</template>
<template is="dom-if" if="[[!item.isPasskey]]">
<password-details-card password="[[item]]"
<password-details-card password="[[item]]" prefs="{{prefs}}"
group-name="[[selectedGroup_.name]]"
icon-url="[[selectedGroup_.iconUrl]]">
</password-details-card>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import './site_favicon.js';
import './credential_details/password_details_card.js';
import './credential_details/passkey_details_card.js';

import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js';
import {CrIconButtonElement} from 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
import {assert} from 'chrome://resources/js/assert.js';
import {afterNextRender, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
Expand All @@ -24,7 +25,8 @@ export interface PasswordDetailsSectionElement {
};
}

const PasswordDetailsSectionElementBase = RouteObserverMixin(PolymerElement);
const PasswordDetailsSectionElementBase =
PrefsMixin(RouteObserverMixin(PolymerElement));

export class PasswordDetailsSectionElement extends
PasswordDetailsSectionElementBase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
<template is="dom-if" restamp
if="[[showPage(selectedPage_, pagesValueEnum_.PASSWORD_DETAILS)]]">
<password-details-section class="cr-centered-card-container"
on-password-removed="onPasswordRemoved_"
on-password-removed="onPasswordRemoved_" prefs="{{prefs_}}"
on-passkey-removed="onPasskeyRemoved_">
</password-details-section>
</template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ content::WebUIDataSource* CreateAndAddPasswordsUIHTMLSource(
IDS_PASSWORD_MANAGER_UI_SHARE_PASSWORD_VIEW_FAMILY},
{"sharePasswordMemeberUnavailable",
IDS_PASSWORD_MANAGER_UI_SHARE_PASSWORD_MEMBER_UNAVAILABLE},
{"sharePasswordManagedByAdmin",
IDS_PASSWORD_MANAGER_UI_SHARING_IS_MANAGED_BY_ADMIN},
{"sharePasswordNotAvailable",
IDS_PASSWORD_MANAGER_UI_SHARE_PASSWORD_NOT_AVAILABLE},
{"sharePasswordErrorDescription",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js';

import {TestPasswordManagerProxy} from './test_password_manager_proxy.js';
import {TestSyncBrowserProxy} from './test_sync_browser_proxy.js';
import {createAffiliatedDomain, createPasswordEntry} from './test_util.js';
import {createAffiliatedDomain, createPasswordEntry, makePasswordManagerPrefs} from './test_util.js';

async function createCardElement(
password: chrome.passwordsPrivate.PasswordUiEntry|null =
Expand All @@ -24,6 +24,7 @@ async function createCardElement(

const card = document.createElement('password-details-card');
card.password = password;
card.prefs = makePasswordManagerPrefs();
document.body.appendChild(card);
await flushTasks();
return card;
Expand Down Expand Up @@ -357,16 +358,13 @@ suite('PasswordDetailsCardTest', function() {

const card = await createCardElement();

const shareButton =
card.shadowRoot!.querySelector<HTMLElement>('#shareButton');
assertTrue(!!shareButton);
assertTrue(isVisible(shareButton));
assertEquals(shareButton.textContent!.trim(), card.i18n('share'));
assertTrue(isVisible(card.$.shareButton));
assertEquals(card.$.shareButton.textContent!.trim(), card.i18n('share'));

assertFalse(!!card.shadowRoot!.querySelector('share-password-flow'));

// Share flow should become available after the button click.
shareButton.click();
card.$.shareButton.click();
await passwordManager.whenCalled('fetchFamilyMembers');
await flushTasks();

Expand All @@ -388,9 +386,31 @@ suite('PasswordDetailsCardTest', function() {

assertFalse(card.$.shareButton.hidden);
assertTrue(isVisible(card.$.shareButton));
assertFalse(card.$.shareButton.disabled);
assertEquals(card.$.shareButton.textContent!.trim(), card.i18n('share'));
});

test('sharing disabled by policy', async function() {
loadTimeData.overrideValues({enableSendPasswords: true});

syncProxy.syncInfo = {
isEligibleForAccountStorage: false,
isSyncingPasswords: true,
};

const card = document.createElement('password-details-card');
card.password = createPasswordEntry();
card.prefs = makePasswordManagerPrefs();
card.prefs.password_manager.password_sharing_enabled.value = false;
card.prefs.password_manager.password_sharing_enabled.enforcement =
chrome.settingsPrivate.Enforcement.ENFORCED;
document.body.appendChild(card);
await flushTasks();

assertTrue(isVisible(card.$.shareButton));
assertTrue(card.$.shareButton.disabled);
});

test('sharing unavailable for federated credentials', async function() {
loadTimeData.overrideValues({enableSendPasswords: true});

Expand All @@ -402,7 +422,7 @@ suite('PasswordDetailsCardTest', function() {
const card =
await createCardElement(createPasswordEntry({federationText: 'text'}));

assertTrue(card.$.shareButton.hidden);
assertFalse(isVisible(card.$.shareButton));

const sharePasswordFlow =
card.shadowRoot!.querySelector('share-password-flow');
Expand All @@ -419,7 +439,7 @@ suite('PasswordDetailsCardTest', function() {

const card = await createCardElement();

assertTrue(card.$.shareButton.hidden);
assertFalse(isVisible(card.$.shareButton));

const sharePasswordFlow =
card.shadowRoot!.querySelector('share-password-flow');
Expand All @@ -436,7 +456,7 @@ suite('PasswordDetailsCardTest', function() {

const card = await createCardElement();

assertTrue(card.$.shareButton.hidden);
assertFalse(isVisible(card.$.shareButton));

const sharePasswordFlow =
card.shadowRoot!.querySelector('share-password-flow');
Expand Down
9 changes: 7 additions & 2 deletions chrome/test/data/webui/password_manager/test_util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,15 +157,20 @@ export function makePasswordManagerPrefs() {
value: true,
},
},
// <if expr="is_win or is_macosx">
password_manager: {
// <if expr="is_win or is_macosx">
biometric_authentication_filling: {
key: 'password_manager.biometric_authentication_filling',
type: chrome.settingsPrivate.PrefType.BOOLEAN,
value: true,
},
// </if>
password_sharing_enabled: {
key: 'password_manager.password_sharing_enabled',
type: chrome.settingsPrivate.PrefType.BOOLEAN,
value: true,
},
},
// </if>
};
}

Expand Down

0 comments on commit d19f3d6

Please sign in to comment.