Skip to content

Commit

Permalink
personalization: Move first Google Photos data fetch for albums.
Browse files Browse the repository at this point in the history
The first Google Photos data fetch for albums previously occurred on app
load. Now, the data fetch will occur only after the user has selected
the Google Photos collection.

A follow up CL will do the same for the first Google Photos photos data
fetch.

Bug: b:230635452
Change-Id: I065b63718731035217cb832c67ff5419e500b410
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3630838
Reviewed-by: Jeffrey Young <cowmoo@chromium.org>
Commit-Queue: David Black <dmblack@google.com>
Cr-Commit-Position: refs/heads/main@{#1001125}
  • Loading branch information
David Black authored and Chromium LUCI CQ committed May 9, 2022
1 parent 8c162c9 commit 7630679
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 62 deletions.
15 changes: 15 additions & 0 deletions ash/webui/personalization_app/resources/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@

import {loadTimeData} from '//resources/js/load_time_data.m.js';

/** A Promise<T> which can be externally |resolve()|-ed. */
export type ExternallyResolvablePromise<T> =
Promise<T>&{resolve: (result: T) => void};

/** Creates a Promise<T> which can be externally |resolve()|-ed. */
export function createExternallyResolvablePromise<T>():
ExternallyResolvablePromise<T> {
let externalResolver: (result: T) => void;
const promise = new Promise<T>(resolve => {
externalResolver = resolve;
}) as ExternallyResolvablePromise<T>;
promise.resolve = externalResolver!;
return promise;
}

/**
* Checks if argument is an array with zero length.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import '../../common/styles.js';

import {assertNotReached} from 'chrome://resources/js/assert_ts.js';

import {isEmptyArray, isNonEmptyArray} from '../../common/utils.js';
import {createExternallyResolvablePromise, ExternallyResolvablePromise, isEmptyArray, isNonEmptyArray} from '../../common/utils.js';
import {GooglePhotosAlbum, GooglePhotosEnablementState, GooglePhotosPhoto, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js';
import {Paths, PersonalizationRouter} from '../personalization_router_element.js';
import {WithPersonalizationStore} from '../personalization_store.js';

import {getTemplate} from './google_photos_collection_element.html.js';
import {initializeGooglePhotosData} from './wallpaper_controller.js';
import {fetchGooglePhotosAlbums, initializeGooglePhotosData} from './wallpaper_controller.js';
import {getWallpaperProvider} from './wallpaper_interface_provider.js';

/** Enumeration of supported tabs. */
Expand Down Expand Up @@ -59,6 +59,7 @@ export class GooglePhotosCollection extends WithPersonalizationStore {
path: String,

albums_: Array,
albumsLoading_: Boolean,
enabled_: Number,
photos_: Array,
photosByAlbumId_: Object,
Expand Down Expand Up @@ -86,9 +87,21 @@ export class GooglePhotosCollection extends WithPersonalizationStore {
/** The list of albums. */
private albums_: GooglePhotosAlbum[]|null|undefined;

/** Whether the list of albums is currently loading. */
private albumsLoading_: boolean|undefined;

/** Whether the user is allowed to access Google Photos. */
private enabled_: GooglePhotosEnablementState|undefined;

/**
* Promise which is resolved after initializing Google Photos data. Note that
* this promise is created early (instead of at data initialization request
* time) so that it can be waited on prior to the request.
*/
private initializeGooglePhotosDataPromise_:
ExternallyResolvablePromise<void> =
createExternallyResolvablePromise<void>();

/** The list of photos. */
private photos_: GooglePhotosPhoto[]|null|undefined;

Expand All @@ -108,6 +121,8 @@ export class GooglePhotosCollection extends WithPersonalizationStore {

this.watch<GooglePhotosCollection['albums_']>(
'albums_', state => state.wallpaper.googlePhotos.albums);
this.watch<GooglePhotosCollection['albumsLoading_']>(
'albumsLoading_', state => state.wallpaper.loading.googlePhotos.albums);
this.watch<GooglePhotosCollection['enabled_']>(
'enabled_', state => state.wallpaper.googlePhotos.enabled);
this.watch<GooglePhotosCollection['photos_']>(
Expand All @@ -118,7 +133,8 @@ export class GooglePhotosCollection extends WithPersonalizationStore {

this.updateFromStore();

initializeGooglePhotosData(this.wallpaperProvider_, this.getStore());
initializeGooglePhotosData(this.wallpaperProvider_, this.getStore())
.then(() => this.initializeGooglePhotosDataPromise_.resolve());
}

/** Invoked on changes to the currently selected |albumId|. */
Expand All @@ -134,6 +150,14 @@ export class GooglePhotosCollection extends WithPersonalizationStore {

document.title = this.i18n('googlePhotosLabel');
this.$.main.focus();

// When the user first selects the Google Photos collection it should result
// in a data fetch for the user's albums.
if (this.albums_ === undefined && !this.albumsLoading_) {
this.initializeGooglePhotosDataPromise_.then(() => {
fetchGooglePhotosAlbums(this.wallpaperProvider_, this.getStore());
});
}
}

/** Invoked on changes to either |path| or |enabled_|. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,19 @@ export async function fetchGooglePhotosAlbum(
export async function fetchGooglePhotosAlbums(
provider: WallpaperProviderInterface,
store: PersonalizationStore): Promise<void> {
// Albums should only be fetched after confirming access is allowed.
// Albums should only be fetched after determining whether access is allowed.
const enabled = store.data.wallpaper.googlePhotos.enabled;
assert(enabled === GooglePhotosEnablementState.kEnabled);
assert(enabled !== undefined);

store.dispatch(action.beginLoadGooglePhotosAlbumsAction());

// If access is *not* allowed, short-circuit the request.
if (enabled !== GooglePhotosEnablementState.kEnabled) {
store.dispatch(action.appendGooglePhotosAlbumsAction(
/*albums=*/ null, /*resumeToken=*/ null));
return;
}

let albums: Array<GooglePhotosAlbum>|null = [];
let resumeToken = store.data.wallpaper.googlePhotos.resumeTokens.albums;

Expand Down Expand Up @@ -417,17 +424,12 @@ export async function initializeGooglePhotosData(
// Only proceed to fetch Google Photos data if the user is allowed.
const enabled = store.data.wallpaper.googlePhotos.enabled;
if (enabled === GooglePhotosEnablementState.kEnabled) {
await Promise.all([
fetchGooglePhotosAlbums(provider, store),
fetchGooglePhotosPhotos(provider, store),
]);
await fetchGooglePhotosPhotos(provider, store);
} else {
const result = null;
const resumeToken = null;
store.beginBatchUpdate();
store.dispatch(action.beginLoadGooglePhotosAlbumsAction());
store.dispatch(action.beginLoadGooglePhotosPhotosAction());
store.dispatch(action.appendGooglePhotosAlbumsAction(result, resumeToken));
store.dispatch(action.appendGooglePhotosPhotosAction(result, resumeToken));
store.endBatchUpdate();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import 'chrome://personalization/strings.m.js';
import 'chrome://webui-test/mojo_webui_test_support.js';

import {getCountText, GooglePhotosAlbum, GooglePhotosAlbums, initializeGooglePhotosData, PersonalizationActionName, PersonalizationRouter, SetErrorAction, WallpaperGridItem} from 'chrome://personalization/trusted/personalization_app.js';
import {fetchGooglePhotosAlbums, getCountText, GooglePhotosAlbum, GooglePhotosAlbums, initializeGooglePhotosData, PersonalizationActionName, PersonalizationRouter, SetErrorAction, WallpaperGridItem} from 'chrome://personalization/trusted/personalization_app.js';
import {assertEquals, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
import {waitAfterNextRender} from 'chrome://webui-test/test_util.js';
Expand Down Expand Up @@ -85,6 +85,7 @@ suite('GooglePhotosAlbumsTest', function() {

// Initialize Google Photos data in the |personalizationStore|.
await initializeGooglePhotosData(wallpaperProvider, personalizationStore);
await fetchGooglePhotosAlbums(wallpaperProvider, personalizationStore);
await waitAfterNextRender(googlePhotosAlbumsElement);

// The wallpaper controller is expected to impose max resolution.
Expand Down Expand Up @@ -118,6 +119,8 @@ suite('GooglePhotosAlbumsTest', function() {
PersonalizationActionName.SET_ERROR);
await initializeGooglePhotosData(
wallpaperProvider, personalizationStore);
await fetchGooglePhotosAlbums(
wallpaperProvider, personalizationStore);
const {error} =
await personalizationStore.waitForAction(
PersonalizationActionName.SET_ERROR) as SetErrorAction;
Expand Down Expand Up @@ -236,6 +239,7 @@ suite('GooglePhotosAlbumsTest', function() {

// Initialize Google Photos data in |personalizationStore|.
await initializeGooglePhotosData(wallpaperProvider, personalizationStore);
await fetchGooglePhotosAlbums(wallpaperProvider, personalizationStore);
assertEquals(
await wallpaperProvider.whenCalled('fetchGooglePhotosAlbums'),
/*resumeToken=*/ null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,48 @@ suite('GooglePhotosCollectionTest', function() {
assertFalse(zeroState.hidden);
});

test('sets google photos aria label', async () => {
[true, false].forEach(
hidden => test('fetches albums on first show', async () => {
// Initialize |googlePhotosCollectionElement| in |hidden| state.
googlePhotosCollectionElement =
initElement(GooglePhotosCollection, {hidden});
await waitAfterNextRender(googlePhotosCollectionElement);

if (hidden) {
// Albums should *not* be fetched when hidden.
await new Promise<void>(resolve => setTimeout(resolve, 100));
assertEquals(
wallpaperProvider.getCallCount('fetchGooglePhotosAlbums'), 0);

// Show |googlePhotosCollectionElement|.
googlePhotosCollectionElement.hidden = false;
await waitAfterNextRender(googlePhotosCollectionElement);
}

// Albums *should* be fetched when shown.
await wallpaperProvider.whenCalled('fetchGooglePhotosAlbums');
wallpaperProvider.reset();

// Hide and re-show |googlePhotosCollectionElement|.
googlePhotosCollectionElement.hidden = true;
await waitAfterNextRender(googlePhotosCollectionElement);
googlePhotosCollectionElement.hidden = false;
await waitAfterNextRender(googlePhotosCollectionElement);

// Albums should *not* be fetched when re-shown.
await new Promise<void>(resolve => setTimeout(resolve, 100));
assertEquals(
wallpaperProvider.getCallCount('fetchGooglePhotosAlbums'), 0);
}));

test('sets aria label', async () => {
googlePhotosCollectionElement =
initElement(GooglePhotosCollection, {hidden: false});
await waitAfterNextRender(googlePhotosCollectionElement);

assertEquals(
loadTimeData.getString('googlePhotosLabel'),
googlePhotosCollectionElement.$.main.getAttribute('aria-label'),
'google photos main aria label is set');
googlePhotosCollectionElement.$.main.getAttribute('aria-label'));
});

[GooglePhotosEnablementState.kDisabled, GooglePhotosEnablementState.kEnabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import 'chrome://personalization/strings.m.js';
import 'chrome://webui-test/mojo_webui_test_support.js';

import {fetchGooglePhotosAlbum, GooglePhotosAlbum, GooglePhotosEnablementState, GooglePhotosPhoto, GooglePhotosPhotosByAlbumId, initializeGooglePhotosData, PersonalizationActionName, SetErrorAction, WallpaperGridItem, WallpaperLayout, WallpaperType} from 'chrome://personalization/trusted/personalization_app.js';
import {fetchGooglePhotosAlbum, fetchGooglePhotosAlbums, GooglePhotosAlbum, GooglePhotosEnablementState, GooglePhotosPhoto, GooglePhotosPhotosByAlbumId, initializeGooglePhotosData, PersonalizationActionName, SetErrorAction, WallpaperGridItem, WallpaperLayout, WallpaperType} from 'chrome://personalization/trusted/personalization_app.js';
import {assertDeepEquals, assertEquals, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
import {waitAfterNextRender} from 'chrome://webui-test/test_util.js';

Expand Down Expand Up @@ -66,6 +66,8 @@ suite('GooglePhotosPhotosByAlbumIdTest', function() {
// Initialize Google Photos data in the |personalizationStore|.
await initializeGooglePhotosData(
wallpaperProvider, personalizationStore);
await fetchGooglePhotosAlbums(
wallpaperProvider, personalizationStore);

// Initialize |googlePhotosPhotosByAlbumIdElement|.
googlePhotosPhotosByAlbumIdElement =
Expand Down Expand Up @@ -274,6 +276,7 @@ suite('GooglePhotosPhotosByAlbumIdTest', function() {

// Initialize Google Photos data in the |personalizationStore|.
await initializeGooglePhotosData(wallpaperProvider, personalizationStore);
await fetchGooglePhotosAlbums(wallpaperProvider, personalizationStore);

// The wallpaper controller is expected to impose max resolution.
album.preview.url += '=s512';
Expand Down Expand Up @@ -470,6 +473,7 @@ suite('GooglePhotosPhotosByAlbumIdTest', function() {

// Initialize Google Photos data in |personalizationStore|.
await initializeGooglePhotosData(wallpaperProvider, personalizationStore);
await fetchGooglePhotosAlbums(wallpaperProvider, personalizationStore);
assertDeepEquals(
await wallpaperProvider.whenCalled('fetchGooglePhotosPhotos'),
[/*itemId=*/ null, /*albumId=*/ null, /*resumeToken=*/ null]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import 'chrome://personalization/strings.m.js';
import 'chrome://webui-test/mojo_webui_test_support.js';

import {cancelPreviewWallpaper, DefaultImageSymbol, fetchCollections, fetchGooglePhotosAlbum, fetchLocalData, getDefaultImageThumbnail, getImageKey, getLocalImages, GooglePhotosAlbum, GooglePhotosEnablementState, GooglePhotosPhoto, initializeBackdropData, initializeGooglePhotosData, isFilePath, kDefaultImageSymbol, selectWallpaper, WallpaperImage} from 'chrome://personalization/trusted/personalization_app.js';
import {cancelPreviewWallpaper, DefaultImageSymbol, fetchCollections, fetchGooglePhotosAlbum, fetchGooglePhotosAlbums, fetchLocalData, getDefaultImageThumbnail, getImageKey, getLocalImages, GooglePhotosAlbum, GooglePhotosEnablementState, GooglePhotosPhoto, initializeBackdropData, initializeGooglePhotosData, isFilePath, kDefaultImageSymbol, selectWallpaper, WallpaperImage} from 'chrome://personalization/trusted/personalization_app.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {FilePath} from 'chrome://resources/mojo/mojo/public/mojom/base/file_path.mojom-webui.js';
import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
Expand Down Expand Up @@ -53,14 +53,12 @@ suite('Personalization app controller', () => {

await initializeGooglePhotosData(wallpaperProvider, personalizationStore);

let expectedEnabled, expectedAlbums, expectedPhotos;
let expectedEnabled, expectedPhotos;
if (isGooglePhotosIntegrationEnabled) {
expectedEnabled = GooglePhotosEnablementState.kEnabled;
expectedAlbums = [];
expectedPhotos = [];
} else {
expectedEnabled = GooglePhotosEnablementState.kError;
expectedAlbums = null;
expectedPhotos = null;
}

Expand All @@ -73,17 +71,9 @@ suite('Personalization app controller', () => {
name: 'set_google_photos_enabled',
enabled: expectedEnabled,
},
{
name: 'begin_load_google_photos_albums',
},
{
name: 'begin_load_google_photos_photos',
},
{
name: 'append_google_photos_albums',
albums: expectedAlbums,
resumeToken: null,
},
{
name: 'append_google_photos_photos',
photos: expectedPhotos,
Expand Down Expand Up @@ -126,39 +116,7 @@ suite('Personalization app controller', () => {
resumeTokens: {albums: null, photos: null, photosByAlbumId: {}},
},
},
// BEGIN_LOAD_GOOGLE_PHOTOS_ALBUMS.
{
'wallpaper.loading.googlePhotos': {
enabled: false,
albums: true,
photos: false,
photosByAlbumId: {},
},
'wallpaper.googlePhotos': {
enabled: expectedEnabled,
albums: undefined,
photos: undefined,
photosByAlbumId: {},
resumeTokens: {albums: null, photos: null, photosByAlbumId: {}},
},
},
// BEGIN_LOAD_GOOGLE_PHOTOS_PHOTOS.
{
'wallpaper.loading.googlePhotos': {
enabled: false,
albums: true,
photos: true,
photosByAlbumId: {},
},
'wallpaper.googlePhotos': {
enabled: expectedEnabled,
albums: undefined,
photos: undefined,
photosByAlbumId: {},
resumeTokens: {albums: null, photos: null, photosByAlbumId: {}},
},
},
// APPEND_GOOGLE_PHOTOS_ALBUMS.
{
'wallpaper.loading.googlePhotos': {
enabled: false,
Expand All @@ -168,7 +126,7 @@ suite('Personalization app controller', () => {
},
'wallpaper.googlePhotos': {
enabled: expectedEnabled,
albums: expectedAlbums,
albums: undefined,
photos: undefined,
photosByAlbumId: {},
resumeTokens: {albums: null, photos: null, photosByAlbumId: {}},
Expand All @@ -184,7 +142,7 @@ suite('Personalization app controller', () => {
},
'wallpaper.googlePhotos': {
enabled: expectedEnabled,
albums: expectedAlbums,
albums: undefined,
photos: expectedPhotos,
photosByAlbumId: {},
resumeTokens: {albums: null, photos: null, photosByAlbumId: {}},
Expand Down Expand Up @@ -218,6 +176,7 @@ suite('Personalization app controller', () => {
// Attempts to `fetchGooglePhotosAlbum()` will fail unless the entire list
// of Google Photos albums has already been fetched and saved to the store.
await initializeGooglePhotosData(wallpaperProvider, personalizationStore);
await fetchGooglePhotosAlbums(wallpaperProvider, personalizationStore);
personalizationStore.reset(personalizationStore.data);

await fetchGooglePhotosAlbum(
Expand Down

0 comments on commit 7630679

Please sign in to comment.