Skip to content

Commit

Permalink
personalization: Implement disabled UI for Google Photos collection.
Browse files Browse the repository at this point in the history
If the Google Photos collection is disabled by enterprise policy, that
should be represented visually to the user. The Google Photos collection
should not be able to be opened if disabled.

Populated (before): http://shortn/_OpgfcYQahw
Populated (after): http://shortn/_hcp3WrKZgd
Empty (before): http://shortn/_0NlgTNy5SD
Empty (after): http://shortn/_0x2BwVq45w
Disabled (before): http://shortn/_SK1i0aC9ol
Disabled (after): http://shortn/_911D23aPpA

Bug: b:225243368
Change-Id: I43532c8e68f18298dfbf671adc1d138d1f680c5a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3561738
Reviewed-by: Jeffrey Young <cowmoo@chromium.org>
Reviewed-by: Zufeng Wang <zufeng@google.com>
Commit-Queue: David Black <dmblack@google.com>
Cr-Commit-Position: refs/heads/main@{#988003}
  • Loading branch information
David Black authored and Chromium LUCI CQ committed Apr 1, 2022
1 parent e04a479 commit 1808de7
Show file tree
Hide file tree
Showing 12 changed files with 218 additions and 27 deletions.
1 change: 1 addition & 0 deletions ash/webui/personalization_app/personalization_app_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ void AddStrings(content::WebUIDataSource* source) {
{"zeroImages", IDS_PERSONALIZATION_APP_NO_IMAGES},
{"oneImage", IDS_PERSONALIZATION_APP_ONE_IMAGE},
{"multipleImages", IDS_PERSONALIZATION_APP_MULTIPLE_IMAGES},
{"managedSetting", IDS_PERSONALIZATION_APP_MANAGED_SETTING},

// User/avatar related strings.
{"avatarLabel", IDS_PERSONALIZATION_APP_AVATAR_LABEL},
Expand Down
19 changes: 13 additions & 6 deletions ash/webui/personalization_app/resources/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import {FilePath} from 'chrome://resources/mojo/mojo/public/mojom/base/file_path.mojom-webui.js';
import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js';

import {WallpaperCollection} from '../trusted/personalization_app.mojom-webui.js';
import {GooglePhotosEnablementState, WallpaperCollection} from '../trusted/personalization_app.mojom-webui.js';

export const trustedOrigin = 'chrome://personalization';

Expand All @@ -15,6 +15,7 @@ export const kMaximumLocalImagePreviews = 3;
export enum EventType {
SEND_COLLECTIONS = 'send_collections',
SEND_GOOGLE_PHOTOS_COUNT = 'send_google_photos_count',
SEND_GOOGLE_PHOTOS_ENABLED = 'send_google_photos_enabled',
SEND_GOOGLE_PHOTOS_PHOTOS = 'send_google_photos_photos',
SELECT_COLLECTION = 'select_collection',
SELECT_GOOGLE_PHOTOS_COLLECTION = 'select_google_photos_collection',
Expand All @@ -40,6 +41,11 @@ export type SendGooglePhotosCountEvent = {
count: number|null,
};

export type SendGooglePhotosEnabledEvent = {
type: EventType.SEND_GOOGLE_PHOTOS_ENABLED,
enabled: GooglePhotosEnablementState,
};

export type SendGooglePhotosPhotosEvent = {
type: EventType.SEND_GOOGLE_PHOTOS_PHOTOS,
photos: unknown[]|null,
Expand Down Expand Up @@ -115,8 +121,9 @@ export type SendVisibleEvent = {
};

export type Events = SendCollectionsEvent|SendGooglePhotosCountEvent|
SendGooglePhotosPhotosEvent|SelectCollectionEvent|
SelectGooglePhotosCollectionEvent|SelectLocalCollectionEvent|
SendImageCountsEvent|SendImageTilesEvent|SendLocalImagesEvent|
SendLocalImageDataEvent|SendCurrentWallpaperAssetIdEvent|
SendPendingWallpaperAssetIdEvent|SelectImageEvent|SendVisibleEvent;
SendGooglePhotosEnabledEvent|SendGooglePhotosPhotosEvent|
SelectCollectionEvent|SelectGooglePhotosCollectionEvent|
SelectLocalCollectionEvent|SendImageCountsEvent|SendImageTilesEvent|
SendLocalImagesEvent|SendLocalImageDataEvent|
SendCurrentWallpaperAssetIdEvent|SendPendingWallpaperAssetIdEvent|
SelectImageEvent|SendVisibleEvent;
4 changes: 4 additions & 0 deletions ash/webui/personalization_app/resources/common/icons.html
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@
<path d="M8.854 13.812L14.729 7.93801L13.5 6.72901L8.875 11.354L6.521 9.00001L5.292 10.229L8.854 13.812ZM10 18.333C8.84733 18.333 7.764 18.1143 6.75 17.677C5.736 17.2397 4.854 16.646 4.104 15.896C3.354 15.146 2.76033 14.264 2.323 13.25C1.88567 12.236 1.667 11.1527 1.667 10C1.667 8.84734 1.88567 7.76401 2.323 6.75001C2.76033 5.73601 3.354 4.85401 4.104 4.10401C4.854 3.35401 5.736 2.76034 6.75 2.32301C7.764 1.88567 8.84733 1.66701 10 1.66701C11.1527 1.66701 12.236 1.88567 13.25 2.32301C14.264 2.76034 15.146 3.35401 15.896 4.10401C16.646 4.85401 17.2397 5.73601 17.677 6.75001C18.1143 7.76401 18.333 8.84734 18.333 10C18.333 11.1527 18.1143 12.236 17.677 13.25C17.2397 14.264 16.646 15.146 15.896 15.896C15.146 16.646 14.264 17.2397 13.25 17.677C12.236 18.1143 11.1527 18.333 10 18.333ZM10 16.583C11.8193 16.583 13.3713 15.9407 14.656 14.656C15.9407 13.3713 16.583 11.8193 16.583 10C16.583 8.18067 15.9407 6.62867 14.656 5.34401C13.3713 4.05934 11.8193 3.41701 10 3.41701C8.18067 3.41701 6.62867 4.05934 5.344 5.34401C4.05933 6.62867 3.417 8.18067 3.417 10C3.417 11.8193 4.05933 13.3713 5.344 14.656C6.62867 15.9407 8.18067 16.583 10 16.583Z">
</path>
</g>
<g id="managed">
<path d="M2 17V3H12V7H18V17H2ZM8 9H10V11H8V9ZM12 11H14V13H12V15H16V9H12V11ZM8 13H10V15H8V13ZM6 13H4V15H6V13ZM6 9H4V11H6V9ZM8 5H10V7H8V5ZM6 5H4V7H6V5Z">
</path>
</g>
</defs>
</svg>
</iron-iconset-svg>
14 changes: 13 additions & 1 deletion ash/webui/personalization_app/resources/trusted/iframe_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {isNonEmptyArray} from '../common/utils.js';
import {CollectionsGrid} from '../untrusted/collections_grid.js';
import {ImagesGrid} from '../untrusted/images_grid.js';

import {WallpaperCollection, WallpaperImage} from './personalization_app.mojom-webui.js';
import {GooglePhotosEnablementState, WallpaperCollection, WallpaperImage} from './personalization_app.mojom-webui.js';

/**
* TODO(b:197023872) this class is deprecated and should be removed by more
Expand Down Expand Up @@ -47,6 +47,18 @@ export class IFrameApi {
target.onMessageReceived(event);
}

/**
* Sends whether the user is allowed to access Google Photos to untrusted.
*/
sendGooglePhotosEnabled(
target: CollectionsGrid, enabled: GooglePhotosEnablementState) {
const event: constants.SendGooglePhotosEnabledEvent = {
type: constants.EventType.SEND_GOOGLE_PHOTOS_ENABLED,
enabled
};
target.onMessageReceived(event);
}

/**
* Sends the list of Google Photos photos to untrusted.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {kMaximumGooglePhotosPreviews, kMaximumLocalImagePreviews} from '../../co
import {isNonEmptyArray, isNullOrArray, isNullOrNumber} from '../../common/utils.js';
import {CollectionsGrid} from '../../untrusted/collections_grid.js';
import {IFrameApi} from '../iframe_api.js';
import {GooglePhotosPhoto, WallpaperCollection, WallpaperImage, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js';
import {GooglePhotosEnablementState, GooglePhotosPhoto, WallpaperCollection, WallpaperImage, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js';
import {WithPersonalizationStore} from '../personalization_store.js';

import {getTemplate} from './wallpaper_collections_element.html.js';
Expand Down Expand Up @@ -69,6 +69,14 @@ export class WallpaperCollections extends WithPersonalizationStore {
*/
googlePhotosCountLoading_: Boolean,

/**
* Whether the user is allowed to access Google Photos.
*/
googlePhotosEnabled_: {
type: Number,
observer: 'onGooglePhotosEnabledChanged_',
},

/**
* Contains a mapping of collection id to an array of images.
*/
Expand Down Expand Up @@ -113,6 +121,7 @@ export class WallpaperCollections extends WithPersonalizationStore {
private googlePhotosLoading_: boolean;
private googlePhotosCount_: number|null;
private googlePhotosCountLoading_: boolean;
private googlePhotosEnabled_: GooglePhotosEnablementState;
private images_: Record<string, WallpaperImage[]>;
private imagesLoading_: Record<string, boolean>;
private localImages_: FilePath[];
Expand Down Expand Up @@ -156,6 +165,8 @@ export class WallpaperCollections extends WithPersonalizationStore {
this.watch(
'googlePhotosCountLoading_',
state => state.wallpaper.loading.googlePhotos.count);
this.watch(
'googlePhotosEnabled_', state => state.wallpaper.googlePhotos.enabled);
this.watch('images_', state => state.wallpaper.backdrop.images);
this.watch('imagesLoading_', state => state.wallpaper.loading.images);
this.watch('localImages_', state => state.wallpaper.local.images);
Expand Down Expand Up @@ -265,6 +276,15 @@ export class WallpaperCollections extends WithPersonalizationStore {
this.$.collectionsGrid, googlePhotosCount);
}

/**
* Invoked on changes to whether the user is allowed to access Google Photos.
*/
private onGooglePhotosEnabledChanged_(
googlePhotosEnabled: WallpaperCollections['googlePhotosEnabled_']) {
IFrameApi.getInstance().sendGooglePhotosEnabled(
this.$.collectionsGrid, googlePhotosEnabled);
}

/**
* Send updated local images list.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
opacity: 0.3;
}

.photo-inner-container.google-photos-empty:not([selectable]),
.photo-inner-container.photo-empty:not([selectable]) {
cursor: default;
}
Expand All @@ -20,10 +21,15 @@
}

.google-photos-empty .photo-images-container.photo-images-container-0 {
/* Google Photos tile's zero state should stay white even in dark mode. */
/* Background color should stay light even in dark mode. */
background-color: white;
}

.google-photos-empty[managed] .photo-images-container.photo-images-container-0 {
/* Background color should stay light even in dark mode. */
background-color: var(--google-grey-200);
}

.photo-images-container.photo-images-container-0 img {
flex: none;
height: 64px;
Expand All @@ -32,6 +38,16 @@
width: initial;
}

.google-photos-empty[managed] .photo-images-container.photo-images-container-0 img {
/* Background color should stay light even in dark mode. */
background-color: white;
border-radius: 100%;
box-sizing: border-box;
filter: grayscale(100%);
height: 54px;
padding: 4px;
}

.photo-images-container.photo-images-container-3 img {
height: 50%;
}
Expand All @@ -44,7 +60,32 @@
z-index: 2;
}

.photo-text-container > p {
.photo-text-container div {
align-items: center;
display: flex;
flex-direction: row;
justify-content: center;
}

.photo-text-container iron-icon[icon='personalization:managed'] {
--iron-icon-fill-color: var(--cros-icon-color-secondary);
--iron-icon-height: 16px;
--iron-icon-width: 16px;
display: none;
flex: 0 0 auto;
margin-inline-end: 8px;
}

.google-photos-empty[managed] iron-icon[icon='personalization:managed'] {
/* Icon color should stay light even in dark mode. */
--iron-icon-fill-color: var(--cros-icon-color-secondary-light);
}

.photo-inner-container[managed] iron-icon[icon='personalization:managed'] {
display: block;
}

.photo-text-container p {
color: white;
font: var(--cros-annotation-2-font);
margin: 0;
Expand All @@ -56,11 +97,18 @@
white-space: nowrap;
}

.photo-text-container > p:first-child {
.photo-text-container iron-icon[icon='personalization:managed']+p,
.photo-text-container p:first-child {
font: var(--cros-headline-1-font);
}

.photo-empty .photo-text-container > p {
.google-photos-empty[managed] .photo-text-container p {
/* Text color should stay light even in dark mode. */
color: var(--cros-text-color-secondary-light);
text-shadow: none;
}

.photo-empty .photo-text-container p {
color: var(--cros-button-label-color-secondary);
text-shadow: none;
}
Expand All @@ -77,6 +125,11 @@
width: 100%;
z-index: 1;
}

.google-photos-empty[managed] .photo-gradient-mask,
.photo-empty .photo-gradient-mask {
display: none;
}
</style>
<iron-list items="[[tiles_]]" grid>
<template>
Expand Down Expand Up @@ -108,17 +161,23 @@
<template is="dom-if" if="[[isEmptyTile_(item)]]">
<div tabindex$="[[tabIndex]]" role="button"
aria-disabled$="[[!isSelectableTile_(item)]]"
class$="[[getClassForEmptyTile_(item)]]" selectable$="[[isSelectableTile_(item)]]"
class$="[[getClassForEmptyTile_(item)]]"
managed$="[[isManagedTile_(item)]]"
selectable$="[[isSelectableTile_(item)]]"
on-click="onCollectionSelected_" on-keypress="onCollectionSelected_">
<div class$="[[getClassForImagesContainer_(item)]]">
<img is="cr-auto-img" auto-src="[[getImageUrlForEmptyTile_(item)]]"
aria-hidden="true" clear-src>
</div>
<div class="photo-text-container">
<p title$="[[item.name]]">[[item.name]]</p>
<div>
<iron-icon icon="personalization:managed" title$="[[geti18n_('managedSetting')]]">
</iron-icon>
<p title$="[[item.name]]">[[item.name]]</p>
</div>
<p title$="[[item.count]]">[[item.count]]</p>
</div>
<div class="photo-gradient-mask" hidden$="[[!isGooglePhotosTile_(item)]]"></div>
<div class="photo-gradient-mask"></div>
</div>
</template>
<template is="dom-if" if="[[isImageTile_(item)]]">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js';

import {Events, EventType, kMaximumGooglePhotosPreviews, kMaximumLocalImagePreviews} from '../common/constants.js';
import {getCountText, getLoadingPlaceholderAnimationDelay, getNumberOfGridItemsPerRow, isNonEmptyArray, isNullOrArray, isNullOrNumber, isSelectionEvent} from '../common/utils.js';
import {WallpaperCollection} from '../trusted/personalization_app.mojom-webui.js';
import {GooglePhotosEnablementState, WallpaperCollection} from '../trusted/personalization_app.mojom-webui.js';
import {selectCollection, selectGooglePhotosCollection, selectLocalCollection, validateReceivedData} from '../untrusted/iframe_api.js';

import {getTemplate} from './collections_grid.html.js';
Expand Down Expand Up @@ -162,6 +162,11 @@ export class CollectionsGrid extends PolymerElement {
*/
googlePhotosCount_: Number,

/**
* Whether the user is allowed to access Google Photos.
*/
googlePhotosEnabled_: Number,

/**
* Mapping of collection id to number of images. Loads in progressively
* after collections_.
Expand Down Expand Up @@ -194,6 +199,7 @@ export class CollectionsGrid extends PolymerElement {
private collections_: WallpaperCollection[];
private googlePhotos_: unknown[]|null;
private googlePhotosCount_: number|null;
private googlePhotosEnabled_: GooglePhotosEnablementState;
private imageCounts_: {[key: string]: number|null};
private localImages_: FilePath[];
private localImageData_: {[key: string]: string};
Expand Down Expand Up @@ -320,6 +326,14 @@ export class CollectionsGrid extends PolymerElement {
this.googlePhotosCount_ = null;
}
break;
case EventType.SEND_GOOGLE_PHOTOS_ENABLED:
if (isValid) {
this.googlePhotosEnabled_ = event.enabled;
} else {
this.googlePhotos_ = null;
this.googlePhotosCount_ = null;
}
break;
case EventType.SEND_GOOGLE_PHOTOS_PHOTOS:
if (isValid) {
this.googlePhotos_ = event.photos;
Expand Down Expand Up @@ -464,8 +478,14 @@ export class CollectionsGrid extends PolymerElement {
return this.isTileTypeImage_(item) && !this.isEmptyTile_(item);
}

private isManagedTile_(item: Tile|null): boolean {
return this.isGooglePhotosTile_(item) &&
this.googlePhotosEnabled_ === GooglePhotosEnablementState.kDisabled;
}

private isSelectableTile_(item: Tile|null): item is ImageTile|FailureTile {
return this.isGooglePhotosTile_(item) || this.isImageTile_(item);
return (this.isGooglePhotosTile_(item) && !this.isManagedTile_(item)) ||
this.isImageTile_(item);
}

/**
Expand Down
11 changes: 7 additions & 4 deletions ash/webui/personalization_app/resources/untrusted/iframe_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import * as constants from '../common/constants.js';
import {isNullOrArray, isNullOrNumber} from '../common/utils.js';
import {GooglePhotosEnablementState} from '../trusted/personalization_app.mojom-webui.js';
import {onMessageReceived} from '../trusted/wallpaper/untrusted_message_handler.js';

/**
Expand Down Expand Up @@ -63,12 +64,14 @@ export function validateReceivedData(event: constants.Events): boolean {
case constants.EventType.SEND_COLLECTIONS: {
return isNullOrArray(event.collections);
}
case constants.EventType.SEND_GOOGLE_PHOTOS_COUNT: {
case constants.EventType.SEND_GOOGLE_PHOTOS_COUNT:
return isNullOrNumber(event.count);
}
case constants.EventType.SEND_GOOGLE_PHOTOS_PHOTOS: {
case constants.EventType.SEND_GOOGLE_PHOTOS_ENABLED:
return typeof event.enabled === 'number' &&
event.enabled >= GooglePhotosEnablementState.MIN_VALUE &&
event.enabled <= GooglePhotosEnablementState.MAX_VALUE;
case constants.EventType.SEND_GOOGLE_PHOTOS_PHOTOS:
return isNullOrArray(event.photos);
}
case constants.EventType.SEND_IMAGE_COUNTS:
return typeof event.counts === 'object';
case constants.EventType.SEND_LOCAL_IMAGE_DATA: {
Expand Down

0 comments on commit 1808de7

Please sign in to comment.