1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 var WALLPAPER_PICKER_WIDTH = 574;
6 var WALLPAPER_PICKER_HEIGHT = 420;
8 var wallpaperPickerWindow;
10 var surpriseWallpaper = null;
12 function SurpriseWallpaper() {
16 * Gets SurpriseWallpaper instance. In case it hasn't been initialized, a new
17 * instance is created.
18 * @return {SurpriseWallpaper} A SurpriseWallpaper instance.
20 SurpriseWallpaper.getInstance = function() {
21 if (!surpriseWallpaper)
22 surpriseWallpaper = new SurpriseWallpaper();
23 return surpriseWallpaper;
27 * Tries to change wallpaper to a new one in the background. May fail due to a
30 SurpriseWallpaper.prototype.tryChangeWallpaper = function() {
32 var onFailure = function() {
34 self.fallbackToLocalRss_();
36 // Try to fetch newest rss as document from server first. If any error occurs,
37 // proceed with local copy of rss.
38 WallpaperUtil.fetchURL(Constants.WallpaperRssURL, 'document', function(xhr) {
39 WallpaperUtil.saveToStorage(Constants.AccessRssKey,
40 new XMLSerializer().serializeToString(xhr.responseXML), false);
41 self.updateSurpriseWallpaper(xhr.responseXML);
46 * Retries changing the wallpaper 1 hour later. This is called when fetching the
47 * rss or wallpaper from server fails.
50 SurpriseWallpaper.prototype.retryLater_ = function() {
51 chrome.alarms.create('RetryAlarm', {delayInMinutes: 60});
55 * Fetches the cached rss feed from local storage in the event of being unable
56 * to download the online feed.
59 SurpriseWallpaper.prototype.fallbackToLocalRss_ = function() {
61 Constants.WallpaperLocalStorage.get(Constants.AccessRssKey, function(items) {
62 var rssString = items[Constants.AccessRssKey];
64 self.updateSurpriseWallpaper(new DOMParser().parseFromString(rssString,
67 self.updateSurpriseWallpaper();
73 * Starts to change wallpaper. Called after rss is fetched.
74 * @param {Document=} opt_rss The fetched rss document. If opt_rss is null, uses
77 SurpriseWallpaper.prototype.updateSurpriseWallpaper = function(opt_rss) {
79 var items = opt_rss.querySelectorAll('item');
80 var date = new Date(new Date().toDateString()).getTime();
81 for (var i = 0; i < items.length; i++) {
83 var disableDate = new Date(item.getElementsByTagNameNS(
84 Constants.WallpaperNameSpaceURI, 'disableDate')[0].textContent).
86 var enableDate = new Date(item.getElementsByTagNameNS(
87 Constants.WallpaperNameSpaceURI, 'enableDate')[0].textContent).
89 var regionsString = item.getElementsByTagNameNS(
90 Constants.WallpaperNameSpaceURI, 'regions')[0].textContent;
91 var regions = regionsString.split(', ');
92 if (enableDate <= date && disableDate > date &&
93 regions.indexOf(navigator.language) != -1) {
95 this.setWallpaperFromRssItem_(item,
99 self.updateRandomWallpaper_();
105 // No surprise wallpaper for today at current locale or fetching rss feed
106 // fails. Fallback to use a random one from wallpaper server.
107 this.updateRandomWallpaper_();
111 * Sets a new random wallpaper if one has not already been set today.
114 SurpriseWallpaper.prototype.updateRandomWallpaper_ = function() {
116 Constants.WallpaperLocalStorage.get(
117 Constants.AccessLastSurpriseWallpaperChangedDate, function(items) {
118 var dateString = new Date().toDateString();
119 // At most one random wallpaper per day.
120 if (items[Constants.AccessLastSurpriseWallpaperChangedDate] != dateString) {
121 self.setRandomWallpaper_(dateString);
127 * Sets wallpaper to one of the wallpapers displayed in wallpaper picker. If
128 * the wallpaper download fails, retry one hour later. Wallpapers that are
129 * disabled for surprise me are excluded.
130 * @param {string} dateString String representation of current local date.
133 SurpriseWallpaper.prototype.setRandomWallpaper_ = function(dateString) {
135 Constants.WallpaperLocalStorage.get(Constants.AccessManifestKey,
137 var manifest = items[Constants.AccessManifestKey];
138 if (manifest && manifest.wallpaper_list) {
139 var filtered = manifest.wallpaper_list.filter(function(element) {
140 // Older version manifest do not have available_for_surprise_me field.
141 // In this case, no wallpaper should be filtered out.
142 return element.available_for_surprise_me ||
143 element.available_for_surprise_me == undefined;
145 var index = Math.floor(Math.random() * filtered.length);
146 var wallpaper = filtered[index];
147 var wallpaperURL = wallpaper.base_url + Constants.HighResolutionSuffix;
148 var onSuccess = function() {
149 WallpaperUtil.saveToStorage(
150 Constants.AccessLastSurpriseWallpaperChangedDate,
154 WallpaperUtil.setOnlineWallpaper(wallpaperURL, wallpaper.default_layout,
155 onSuccess, self.retryLater_.bind(self));
161 * Sets wallpaper to the wallpaper specified by item from rss. If downloading
162 * the wallpaper fails, retry one hour later.
163 * @param {Element} item The wallpaper rss item element.
164 * @param {function} onSuccess Success callback.
165 * @param {function} onFailure Failure callback.
168 SurpriseWallpaper.prototype.setWallpaperFromRssItem_ = function(item,
171 var url = item.querySelector('link').textContent;
172 var layout = item.getElementsByTagNameNS(
173 Constants.WallpaperNameSpaceURI, 'layout')[0].textContent;
175 WallpaperUtil.fetchURL(url, 'arraybuffer', function(xhr) {
176 if (xhr.response != null) {
177 chrome.wallpaperPrivate.setCustomWallpaper(xhr.response, layout, false,
178 'surprise_wallpaper',
187 * Disables the wallpaper surprise me feature. Clear all alarms and states.
189 SurpriseWallpaper.prototype.disable = function() {
190 chrome.alarms.clearAll();
191 // Makes last changed date invalid.
192 WallpaperUtil.saveToStorage(Constants.AccessLastSurpriseWallpaperChangedDate,
197 * Changes current wallpaper and sets up an alarm to schedule next change around
200 SurpriseWallpaper.prototype.next = function() {
201 var nextUpdate = this.nextUpdateTime(new Date());
202 chrome.alarms.create({when: nextUpdate});
203 this.tryChangeWallpaper();
207 * Calculates when the next wallpaper change should be triggered.
208 * @param {Date} now Current time.
209 * @return {number} The time when next wallpaper change should happen.
211 SurpriseWallpaper.prototype.nextUpdateTime = function(now) {
212 var nextUpdate = new Date(now.setDate(now.getDate() + 1)).toDateString();
213 return new Date(nextUpdate).getTime();
216 chrome.app.runtime.onLaunched.addListener(function() {
217 if (wallpaperPickerWindow && !wallpaperPickerWindow.contentWindow.closed) {
218 wallpaperPickerWindow.focus();
219 chrome.wallpaperPrivate.minimizeInactiveWindows();
223 chrome.app.window.create('main.html', {
225 width: WALLPAPER_PICKER_WIDTH,
226 height: WALLPAPER_PICKER_HEIGHT,
227 minWidth: WALLPAPER_PICKER_WIDTH,
228 maxWidth: WALLPAPER_PICKER_WIDTH,
229 minHeight: WALLPAPER_PICKER_HEIGHT,
230 maxHeight: WALLPAPER_PICKER_HEIGHT,
231 transparentBackground: true
233 wallpaperPickerWindow = w;
234 chrome.wallpaperPrivate.minimizeInactiveWindows();
235 w.onClosed.addListener(function() {
236 chrome.wallpaperPrivate.restoreMinimizedWindows();
241 chrome.storage.onChanged.addListener(function(changes, namespace) {
242 if (changes[Constants.AccessSurpriseMeEnabledKey]) {
243 if (changes[Constants.AccessSurpriseMeEnabledKey].newValue) {
244 SurpriseWallpaper.getInstance().next();
246 SurpriseWallpaper.getInstance().disable();
250 if (changes[Constants.AccessSyncWallpaperInfoKey]) {
251 var newValue = changes[Constants.AccessSyncWallpaperInfoKey].newValue;
252 Constants.WallpaperLocalStorage.get(Constants.AccessLocalWallpaperInfoKey,
254 // Normally, the wallpaper info saved in local storage and sync storage
255 // are the same. If the synced value changed by sync service, they may
256 // different. In that case, change wallpaper to the one saved in sync
257 // storage and update the local value.
258 var localValue = items[Constants.AccessLocalWallpaperInfoKey];
259 if (localValue == undefined ||
260 localValue.url != newValue.url ||
261 localValue.layout != newValue.layout ||
262 localValue.source != newValue.source) {
263 if (newValue.source == Constants.WallpaperSourceEnum.Online) {
264 // TODO(bshe): Consider schedule an alarm to set online wallpaper
265 // later when failed. Note that we need to cancel the retry if user
266 // set another wallpaper before retry alarm invoked.
267 WallpaperUtil.setOnlineWallpaper(newValue.url, newValue.layout,
268 function() {}, function() {});
270 WallpaperUtil.saveToStorage(Constants.AccessLocalWallpaperInfoKey,
277 chrome.alarms.onAlarm.addListener(function() {
278 SurpriseWallpaper.getInstance().next();