Commit b7b13868 authored by Wenzhao Zang's avatar Wenzhao Zang Committed by Commit Bot

cros: Fetch daily refresh image from Backdrop service

1) The new wallpaper picker relies on the Backdrop server to select
   surprise me images, instead of selecting random images by ourseleves
   (the back-end was implemented by a prior CL).

2) The surprise me images are per-category, ie. each wallpaper category
   has a "daily refresh slider". At most one slider may be active at
   a time. Toggling one slider to active should deactivate others.

3) Use "daily refresh" instead of "surprise me" in the code to
   distinguish from the old picker. Although it's possible to share
   code path with the old picker, generally avoid it for clarity.

Test steps include:
1) Toggle daily refresh between enabled/disabled, during
   tablet/clamshell mode, and among different categories.
2) Enable surprise me on the old picker, then add switch
   --new-wallpaper-picker, and see the migration.
3) See the sync is working for two devices with the same account id.

Bug: 834998, 810169, 834994, 837338
Change-Id: I369ce57ac4bd07e91da31bb2971b6970501f9c3a
Reviewed-on: https://chromium-review.googlesource.com/1093742
Commit-Queue: Wenzhao (Colin) Zang <wzang@chromium.org>
Reviewed-by: default avatarXiaoqian Dai <xdai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568732}
parent 26d1c8e8
......@@ -623,6 +623,10 @@ body.v2 {
color: rgb(32, 33, 36);
}
.v2.daily-wallpaper .top-header-contents #wallpaper-description {
max-width: 226px;
}
.v2 .top-header-contents .more-options {
display: flex;
position: absolute;
......@@ -635,6 +639,7 @@ html[dir='rtl'] .v2 .top-header-contents .more-options {
}
.v2 .top-header-contents .more-options > div {
background-color: #fff;
border: 0.5px solid;
border-color: rgba(128, 134, 139, 0.6);
border-radius: 16px;
......@@ -699,8 +704,17 @@ html[dir='rtl'] .v2 .top-header-contents .more-options {
-webkit-margin-start: 96px;
}
.v2.daily-wallpaper .top-header-contents #confirm-preview-wallpaper {
-webkit-margin-start: 8px;
}
.v2 .top-header-contents #refresh-wallpaper {
-webkit-margin-start: 16px;
}
.v2.preview-mode.custom-wallpaper .more-options .custom-option,
.v2.preview-mode:not(.custom-wallpaper) .more-options :not(.custom-option) {
.v2.preview-mode.daily-wallpaper .more-options .daily-option,
.v2.preview-mode:not(.custom-wallpaper):not(.daily-option) .more-options :not(.custom-option):not(.daily-option) {
display: flex;
}
......
......@@ -25,7 +25,8 @@
AccessSyncWallpaperInfoKey: 'wallpaper-sync-info-key',
/**
* Key to access last changed date of a surprise wallpaper in
* Key to access last changed date of a surprise me wallpaper (on the old
* picker) or a daily refresh wallpaper (on the new picker) in
* chrome.storage.local or chrome.storage.sync.
*/
AccessLastSurpriseWallpaperChangedDate: 'wallpaper-last-changed-date-key',
......@@ -42,6 +43,18 @@
*/
AccessSyncSurpriseMeEnabledKey: 'sync-surprise-me-enabled-key',
/**
* Key to access the info related to daily refresh feature (on the new
* wallpaper picker) in chrome.storage.local.
*/
AccessLocalDailyRefreshInfoKey: 'daily-refresh-info-key',
/**
* Key to access the info related to daily refresh feature (on the new
* wallpaper picker) in chrome.storage.sync.
*/
AccessSyncDailyRefreshInfoKey: 'sync-daily-refresh-info-key',
/**
* URL to get latest wallpaper RSS feed.
*/
......
......@@ -207,45 +207,62 @@ SurpriseWallpaper.prototype.setRandomWallpaperFromManifest_ = function(
*/
SurpriseWallpaper.prototype.setRandomWallpaperFromServer_ = function(
onSuccess, suffix) {
// The first step is to get the list of wallpaper collections (ie. categories)
// and randomly select one.
chrome.wallpaperPrivate.getCollectionsInfo(collectionsInfo => {
if (chrome.runtime.lastError) {
this.retryLater_();
return;
}
if (collectionsInfo.length == 0) {
// Although the fetch succeeds, it's theoretically possible that the
// collection list is empty, in this case do nothing.
var onDailyRefreshInfoReturned = dailyRefreshInfo => {
var setRandomWallpaperFromServerImpl = dailyRefreshInfo => {
chrome.wallpaperPrivate.getSurpriseMeImage(
dailyRefreshInfo.collectionId, dailyRefreshInfo.resumeToken,
(imageInfo, nextResumeToken) => {
if (chrome.runtime.lastError) {
this.retryLater_();
return;
}
dailyRefreshInfo.resumeToken = nextResumeToken;
WallpaperUtil.saveDailyRefreshInfo(dailyRefreshInfo);
var wallpaperUrl = imageInfo['imageUrl'] + suffix;
var layout = Constants.WallpaperThumbnailDefaultLayout;
WallpaperUtil.setOnlineWallpaperWithoutPreview(
wallpaperUrl, layout,
onSuccess.bind(null, wallpaperUrl, layout),
this.retryLater_.bind(this));
});
};
if (dailyRefreshInfo) {
if (dailyRefreshInfo.enabled) {
setRandomWallpaperFromServerImpl(dailyRefreshInfo);
} else {
console.error(
'Daily refresh is disabled when the alarm goes off. ' +
'This should never happen!');
}
return;
}
var randomCollectionIndex =
Math.floor(Math.random() * collectionsInfo.length);
var collectionId = collectionsInfo[randomCollectionIndex]['collectionId'];
// The second step is to get the list of wallpapers that belong to the
// particular collection, and randomly select one.
chrome.wallpaperPrivate.getImagesInfo(collectionId, imagesInfo => {
// Migration: we reach here if the old picker set an alarm and by the time
// the alarm goes off, the new picker is already in use. We should ensure
// the user transitions to the daily refresh feature.
chrome.wallpaperPrivate.getCollectionsInfo(collectionsInfo => {
if (chrome.runtime.lastError) {
this.retryLater_();
return;
}
if (imagesInfo.length == 0) {
if (collectionsInfo.length == 0) {
// Although the fetch succeeds, it's theoretically possible that the
// image list is empty, in this case do nothing.
// TODO(crbug.com/800945): Consider fetching another collection.
// collection list is empty, in this case do nothing.
return;
}
var randomImageIndex = Math.floor(Math.random() * imagesInfo.length);
var wallpaperUrl = imagesInfo[randomImageIndex]['imageUrl'] + suffix;
// The backend service doesn't specify the desired layout. Use the default
// layout here.
var layout = Constants.WallpaperThumbnailDefaultLayout;
WallpaperUtil.setOnlineWallpaperWithoutPreview(
wallpaperUrl, layout, onSuccess.bind(null, wallpaperUrl, layout),
this.retryLater_.bind(this));
dailyRefreshInfo = {
enabled: true,
// Use the first collection (an arbitrary choice).
collectionId: collectionsInfo[0]['collectionId'],
resumeToken: null
};
setRandomWallpaperFromServerImpl(dailyRefreshInfo);
});
});
};
WallpaperUtil.getDailyRefreshInfo(onDailyRefreshInfoReturned.bind(null));
};
/**
......@@ -401,6 +418,30 @@ chrome.syncFileSystem.onFileStatusChanged.addListener(function(detail) {
chrome.storage.onChanged.addListener(function(changes, namespace) {
WallpaperUtil.enabledSyncThemesCallback(function(syncEnabled) {
// Daily refresh feature is on the new wallpaper picker only.
var updateDailyRefreshStates = key => {
if (!changes[key])
return;
var oldDailyRefreshInfo = JSON.parse(changes[key].oldValue);
var newDailyRefreshInfo = JSON.parse(changes[key].newValue);
// The resume token is expected to change after a new daily refresh
// wallpaper is set. Ignore it if it's the only change.
if (oldDailyRefreshInfo.enabled === newDailyRefreshInfo.enabled &&
oldDailyRefreshInfo.collectionId ===
newDailyRefreshInfo.collectionId) {
return;
}
// Although the old and new values may both have enabled == true, they can
// have different collection ids, so the old alarm should always be
// cleared.
chrome.alarms.clearAll();
if (newDailyRefreshInfo.enabled)
SurpriseWallpaper.getInstance().next();
};
updateDailyRefreshStates(
syncEnabled ? Constants.AccessSyncDailyRefreshInfoKey :
Constants.AccessLocalDailyRefreshInfoKey);
if (syncEnabled) {
// If sync theme is enabled, use values from chrome.storage.sync to sync
// wallpaper changes.
......@@ -462,12 +503,14 @@ chrome.storage.onChanged.addListener(function(changes, namespace) {
wpDocument.querySelector('.check').style.visibility =
'visible';
}
wpDocument.querySelector('#categories-list').disabled = enable;
chrome.commandLinePrivate.hasSwitch(
'new-wallpaper-picker', useNewWallpaperPicker => {
if (!useNewWallpaperPicker)
if (!useNewWallpaperPicker) {
wpDocument.querySelector('#wallpaper-grid').disabled =
enable;
wpDocument.querySelector('#categories-list').disabled =
enable;
}
});
});
}
......
......@@ -500,3 +500,71 @@ WallpaperUtil.testSendMessage = function(message) {
if (test)
test.sendMessage(message);
};
/**
* Gets the daily refresh info from sync storage, or local storage if the former
* is not available.
* @param {function} callback A callback that takes the value of the info, or
* null if the value is invalid.
*/
WallpaperUtil.getDailyRefreshInfo = function(callback) {
WallpaperUtil.enabledSyncThemesCallback(syncEnabled => {
var parseInfo = dailyRefreshInfoJson => {
if (!dailyRefreshInfoJson) {
callback(null);
return;
}
var dailyRefreshInfo = JSON.parse(dailyRefreshInfoJson);
if (!dailyRefreshInfo.hasOwnProperty('enabled') ||
!dailyRefreshInfo.hasOwnProperty('collectionId') ||
!dailyRefreshInfo.hasOwnProperty('resumeToken')) {
callback(null);
return;
}
callback(dailyRefreshInfo);
};
if (syncEnabled) {
Constants.WallpaperSyncStorage.get(
Constants.AccessSyncDailyRefreshInfoKey, items => {
var dailyRefreshInfoJson =
items[Constants.AccessSyncDailyRefreshInfoKey];
if (dailyRefreshInfoJson) {
parseInfo(dailyRefreshInfoJson);
} else {
Constants.WallpaperLocalStorage.get(
Constants.AccessLocalDailyRefreshInfoKey, items => {
dailyRefreshInfoJson =
items[Constants.AccessLocalDailyRefreshInfoKey];
parseInfo(dailyRefreshInfoJson);
if (dailyRefreshInfoJson) {
WallpaperUtil.saveToSyncStorage(
Constants.AccessSyncDailyRefreshInfoKey,
dailyRefreshInfoJson);
}
});
}
});
} else {
Constants.WallpaperLocalStorage.get(
Constants.AccessLocalDailyRefreshInfoKey, items => {
parseInfo(items[Constants.AccessLocalDailyRefreshInfoKey]);
});
}
});
};
/**
* Saves the daily refresh info to local and sync storage.
* @param {Object} dailyRefreshInfo The daily refresh info.
*/
WallpaperUtil.saveDailyRefreshInfo = function(dailyRefreshInfo) {
var dailyRefreshInfoJson = JSON.stringify(dailyRefreshInfo);
WallpaperUtil.saveToLocalStorage(
Constants.AccessLocalDailyRefreshInfoKey, dailyRefreshInfoJson,
null /*opt_callback=*/);
WallpaperUtil.saveToSyncStorage(
Constants.AccessSyncDailyRefreshInfoKey, dailyRefreshInfoJson,
null /*opt_callback=*/);
};
......@@ -387,6 +387,15 @@ cr.define('wallpapers', function() {
{};
},
/**
* The id of the collection that the wallpapers belong to, assuming all the
* wallpapers have the same id (enfored by the source of the data model).
* @type {string}
*/
get collectionId() {
return this.dataModel.item(this.dataModel.length - 1).collectionId;
},
/**
* A unique ID that assigned to each set dataModel operation. Note that this
* id wont increase if the new dataModel is null or empty.
......@@ -697,11 +706,9 @@ cr.define('wallpapers', function() {
if (!this.dailyRefreshItem.querySelector('.daily-refresh-banner')) {
var dailyRefreshBanner = document.querySelector('.daily-refresh-banner')
.cloneNode(true /*deep=*/);
dailyRefreshBanner.querySelector('.daily-refresh-slider')
.addEventListener(
'click',
WallpaperManager.prototype.toggleSurpriseMe.bind(
wallpaperManager));
wallpaperManager.decorateDailyRefreshSlider(
this.collectionId,
dailyRefreshBanner.querySelector('.daily-refresh-slider'));
this.dailyRefreshItem.appendChild(dailyRefreshBanner);
}
......
......@@ -181,6 +181,8 @@ found in the LICENSE file.
<div class="icon"></div>
<div class="text" i18n-content="centerCroppedLayout"></div>
</div>
<div id="refresh-wallpaper" class="daily-option"
i18n-content="refreshLabel"></div>
<div id="confirm-preview-wallpaper" class="preview-option"
i18n-content="confirmPreviewLabel"></div>
</div>
......
......@@ -286,6 +286,10 @@ var chrome = {
},
getImagesInfo: function(collectionId, callback) {
callback([{imageUrl: TestConstants.wallpaperUrl}]);
},
getSurpriseMeImage: function(collectionId, resumeToken, callback) {
callback(
{imageUrl: TestConstants.wallpaperUrl}, null /*nextResumeToken=*/);
}
},
runtime: {lastError: null},
......
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