Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / wallpaper_manager / js / event_page.js
blobeba94a343e034ee748bf9ae6095796fde5995a08
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() {
15 /**
16  * Gets SurpriseWallpaper instance. In case it hasn't been initialized, a new
17  * instance is created.
18  * @return {SurpriseWallpaper} A SurpriseWallpaper instance.
19  */
20 SurpriseWallpaper.getInstance = function() {
21   if (!surpriseWallpaper)
22     surpriseWallpaper = new SurpriseWallpaper();
23   return surpriseWallpaper;
26 /**
27  * Tries to change wallpaper to a new one in the background. May fail due to a
28  * network issue.
29  */
30 SurpriseWallpaper.prototype.tryChangeWallpaper = function() {
31   var self = this;
32   var onFailure = function(status) {
33     if (status != 404)
34       self.fallbackToLocalRss_();
35     else
36       self.updateRandomWallpaper_();
37   };
38   // Try to fetch newest rss as document from server first. If the requested
39   // URL is not found (404 error), set a random wallpaper displayed in the
40   // wallpaper picker. If any other error occurs, proceed with local copy of
41   // rss.
42   WallpaperUtil.fetchURL(Constants.WallpaperRssURL, 'document', function(xhr) {
43     WallpaperUtil.saveToLocalStorage(Constants.AccessLocalRssKey,
44         new XMLSerializer().serializeToString(xhr.responseXML));
45     self.updateSurpriseWallpaper(xhr.responseXML);
46   }, onFailure);
49 /**
50  * Retries changing the wallpaper 1 hour later. This is called when fetching the
51  * rss or wallpaper from server fails.
52  * @private
53  */
54 SurpriseWallpaper.prototype.retryLater_ = function() {
55   chrome.alarms.create('RetryAlarm', {delayInMinutes: 60});
58 /**
59  * Fetches the cached rss feed from local storage in the event of being unable
60  * to download the online feed.
61  * @private
62  */
63 SurpriseWallpaper.prototype.fallbackToLocalRss_ = function() {
64   var self = this;
65   Constants.WallpaperLocalStorage.get(Constants.AccessLocalRssKey,
66       function(items) {
67     var rssString = items[Constants.AccessLocalRssKey];
68     if (rssString) {
69       self.updateSurpriseWallpaper(new DOMParser().parseFromString(rssString,
70                                                                    'text/xml'));
71     } else {
72       self.updateSurpriseWallpaper();
73     }
74   });
77 /**
78  * Starts to change wallpaper. Called after rss is fetched.
79  * @param {Document=} opt_rss The fetched rss document. If opt_rss is null, uses
80  *     a random wallpaper.
81  */
82 SurpriseWallpaper.prototype.updateSurpriseWallpaper = function(opt_rss) {
83   if (opt_rss) {
84     var items = opt_rss.querySelectorAll('item');
85     var date = new Date(new Date().toDateString()).getTime();
86     for (var i = 0; i < items.length; i++) {
87       item = items[i];
88       var disableDate = new Date(item.getElementsByTagNameNS(
89           Constants.WallpaperNameSpaceURI, 'disableDate')[0].textContent).
90               getTime();
91       var enableDate = new Date(item.getElementsByTagNameNS(
92           Constants.WallpaperNameSpaceURI, 'enableDate')[0].textContent).
93               getTime();
94       var regionsString = item.getElementsByTagNameNS(
95           Constants.WallpaperNameSpaceURI, 'regions')[0].textContent;
96       var regions = regionsString.split(', ');
97       if (enableDate <= date && disableDate > date &&
98           regions.indexOf(navigator.language) != -1) {
99         var self = this;
100         this.setWallpaperFromRssItem_(item,
101                                       function() {},
102                                       function(status) {
103                                         if (status != 404)
104                                           self.retryLater_();
105                                         else
106                                           self.updateRandomWallpaper_();
107                                       });
108         return;
109       }
110     }
111   }
112   // No surprise wallpaper for today at current locale or fetching rss feed
113   // fails. Fallback to use a random one from wallpaper server.
114   this.updateRandomWallpaper_();
118  * Sets a new random wallpaper if one has not already been set today.
119  * @private
120  */
121 SurpriseWallpaper.prototype.updateRandomWallpaper_ = function() {
122   var self = this;
123   var onSuccess = function(items) {
124     var dateString = new Date().toDateString();
125     // At most one random wallpaper per day.
126     if (items[Constants.AccessLastSurpriseWallpaperChangedDate] != dateString) {
127       self.setRandomWallpaper_(dateString);
128     }
129   };
130   WallpaperUtil.enabledSyncThemesCallback(function(syncEnabled) {
131     if (syncEnabled) {
132       Constants.WallpaperSyncStorage.get(
133           Constants.AccessLastSurpriseWallpaperChangedDate, onSuccess);
134     } else {
135       Constants.WallpaperLocalStorage.get(
136           Constants.AccessLastSurpriseWallpaperChangedDate, onSuccess);
137     }
138   });
142  * Sets wallpaper to one of the wallpapers displayed in wallpaper picker. If
143  * the wallpaper download fails, retry one hour later. Wallpapers that are
144  * disabled for surprise me are excluded.
145  * @param {string} dateString String representation of current local date.
146  * @private
147  */
148 SurpriseWallpaper.prototype.setRandomWallpaper_ = function(dateString) {
149   var self = this;
150   Constants.WallpaperLocalStorage.get(Constants.AccessLocalManifestKey,
151                                       function(items) {
152     var manifest = items[Constants.AccessLocalManifestKey];
153     if (manifest && manifest.wallpaper_list) {
154       var filtered = manifest.wallpaper_list.filter(function(element) {
155         // Older version manifest do not have available_for_surprise_me field.
156         // In this case, no wallpaper should be filtered out.
157         return element.available_for_surprise_me ||
158             element.available_for_surprise_me == undefined;
159       });
160       var index = Math.floor(Math.random() * filtered.length);
161       var wallpaper = filtered[index];
162       var wallpaperURL = wallpaper.base_url + Constants.HighResolutionSuffix;
163       var onSuccess = function() {
164         WallpaperUtil.saveWallpaperInfo(wallpaperURL, wallpaper.default_layout,
165             Constants.WallpaperSourceEnum.Online);
166         WallpaperUtil.saveToLocalStorage(
167             Constants.AccessLastSurpriseWallpaperChangedDate,
168             dateString, function() {
169               WallpaperUtil.saveToSyncStorage(
170                 Constants.AccessLastSurpriseWallpaperChangedDate,
171                 dateString);
172             });
173       };
174       WallpaperUtil.setOnlineWallpaper(wallpaperURL, wallpaper.default_layout,
175           onSuccess, self.retryLater_.bind(self));
176     }
177   });
181  * Sets wallpaper to the wallpaper specified by item from rss. If downloading
182  * the wallpaper fails, retry one hour later.
183  * @param {Element} item The wallpaper rss item element.
184  * @param {function} onSuccess Success callback.
185  * @param {function} onFailure Failure callback.
186  * @private
187  */
188 SurpriseWallpaper.prototype.setWallpaperFromRssItem_ = function(item,
189                                                                 onSuccess,
190                                                                 onFailure) {
191   var url = item.querySelector('link').textContent;
192   var layout = item.getElementsByTagNameNS(
193         Constants.WallpaperNameSpaceURI, 'layout')[0].textContent;
194   var self = this;
195   WallpaperUtil.fetchURL(url, 'arraybuffer', function(xhr) {
196     if (xhr.response != null) {
197       chrome.wallpaperPrivate.setCustomWallpaper(xhr.response, layout, false,
198                                                  'surprise_wallpaper',
199                                                  onSuccess);
200       WallpaperUtil.saveWallpaperInfo(url, layout,
201                                       Constants.WallpaperSourceEnum.Online);
202       var dateString = new Date().toDateString();
203       WallpaperUtil.saveToLocalStorage(
204           Constants.AccessLastSurpriseWallpaperChangedDate,
205           dateString, function() {
206             WallpaperUtil.saveToSyncStorage(
207               Constants.AccessLastSurpriseWallpaperChangedDate, dataString);
208           });
209     } else {
210       self.updateRandomWallpaper_();
211     }
212   }, onFailure);
216  * Disables the wallpaper surprise me feature. Clear all alarms and states.
217  */
218 SurpriseWallpaper.prototype.disable = function() {
219   chrome.alarms.clearAll();
220   // Makes last changed date invalid.
221   WallpaperUtil.saveToLocalStorage(
222       Constants.AccessLastSurpriseWallpaperChangedDate, '', function() {
223     WallpaperUtil.saveToSyncStorage(
224       Constants.AccessLastSurpriseWallpaperChangedDate, '');
225   });
229  * Changes current wallpaper and sets up an alarm to schedule next change around
230  * midnight.
231  */
232 SurpriseWallpaper.prototype.next = function() {
233   var nextUpdate = this.nextUpdateTime(new Date());
234   chrome.alarms.create({when: nextUpdate});
235   this.tryChangeWallpaper();
239  * Calculates when the next wallpaper change should be triggered.
240  * @param {Date} now Current time.
241  * @return {number} The time when next wallpaper change should happen.
242  */
243 SurpriseWallpaper.prototype.nextUpdateTime = function(now) {
244   var nextUpdate = new Date(now.setDate(now.getDate() + 1)).toDateString();
245   return new Date(nextUpdate).getTime();
248 chrome.app.runtime.onLaunched.addListener(function() {
249   if (wallpaperPickerWindow && !wallpaperPickerWindow.contentWindow.closed) {
250     wallpaperPickerWindow.focus();
251     chrome.wallpaperPrivate.minimizeInactiveWindows();
252     return;
253   }
255   chrome.app.window.create('main.html', {
256     frame: 'none',
257     width: WALLPAPER_PICKER_WIDTH,
258     height: WALLPAPER_PICKER_HEIGHT,
259     resizable: false,
260     alphaEnabled: true
261   }, function(w) {
262     wallpaperPickerWindow = w;
263     chrome.wallpaperPrivate.minimizeInactiveWindows();
264     w.onClosed.addListener(function() {
265       chrome.wallpaperPrivate.restoreMinimizedWindows();
266     });
267     WallpaperUtil.testSendMessage('wallpaper-window-created');
268   });
271 chrome.syncFileSystem.onFileStatusChanged.addListener(function(detail) {
272   WallpaperUtil.enabledSyncThemesCallback(function(syncEnabled) {
273     if (!syncEnabled)
274       return;
275     if (detail.status == 'synced') {
276       if (detail.direction == 'remote_to_local') {
277         if (detail.action == 'added') {
278           Constants.WallpaperLocalStorage.get(
279               Constants.AccessLocalWallpaperInfoKey,
280               function(items) {
281                 var localData = items[Constants.AccessLocalWallpaperInfoKey];
282                 if (localData && localData.url == detail.fileEntry.name &&
283                     localData.source == Constants.WallpaperSourceEnum.Custom) {
284                   WallpaperUtil.setCustomWallpaperFromSyncFS(localData.url,
285                                                              localData.layout);
286                 } else if (!localData || localData.url !=
287                            detail.fileEntry.name.replace(
288                                Constants.CustomWallpaperThumbnailSuffix, '')) {
289                   // localData might be null on a powerwashed device.
290                   WallpaperUtil.storeWallpaperFromSyncFSToLocalFS(
291                       detail.fileEntry);
292                 }
293              });
294         } else if (detail.action == 'deleted') {
295           var fileName = detail.fileEntry.name.replace(
296               Constants.CustomWallpaperThumbnailSuffix, '');
297           WallpaperUtil.deleteWallpaperFromLocalFS(fileName);
298         }
299       } else {  // detail.direction == 'local_to_remote'
300         if (detail.action == 'deleted') {
301           WallpaperUtil.deleteWallpaperFromSyncFS(detail.fileEntry.name);
302           WallpaperUtil.deleteWallpaperFromLocalFS(detail.fileEntry.name);
303         }
304       }
305     }
306   });
309 chrome.storage.onChanged.addListener(function(changes, namespace) {
310   WallpaperUtil.enabledSyncThemesCallback(function(syncEnabled) {
311     if (syncEnabled) {
312       // If sync theme is enabled, use values from chrome.storage.sync to sync
313       // wallpaper changes.
314       WallpaperUtil.requestSyncFS(function() {});
315       if (changes[Constants.AccessSyncSurpriseMeEnabledKey]) {
316         if (changes[Constants.AccessSyncSurpriseMeEnabledKey].newValue) {
317           SurpriseWallpaper.getInstance().next();
318         } else {
319           SurpriseWallpaper.getInstance().disable();
320         }
321       }
323       if (changes[Constants.AccessSyncWallpaperInfoKey]) {
324         var syncInfo = changes[Constants.AccessSyncWallpaperInfoKey].newValue;
326         Constants.WallpaperSyncStorage.get(
327             Constants.AccessSyncSurpriseMeEnabledKey, function(enabledItems) {
328           var syncSurpriseMeEnabled =
329               enabledItems[Constants.AccessSyncSurpriseMeEnabledKey];
331           Constants.WallpaperSyncStorage.get(
332               Constants.AccessLastSurpriseWallpaperChangedDate,
333               function(items) {
334             var syncLastSurpriseMeChangedDate =
335                 items[Constants.AccessLastSurpriseWallpaperChangedDate];
337             var today = new Date().toDateString();
338             // If SurpriseMe is enabled and surprise wallpaper hasn't been
339             // changed today, we should not sync the change, instead onAlarm()
340             // will be triggered to update a surprise me wallpaper.
341             if (!syncSurpriseMeEnabled ||
342                 (syncSurpriseMeEnabled &&
343                  syncLastSurpriseMeChangedDate == today)) {
344               Constants.WallpaperLocalStorage.get(
345                   Constants.AccessLocalWallpaperInfoKey, function(infoItems) {
346                 var localInfo =
347                     infoItems[Constants.AccessLocalWallpaperInfoKey];
348                 // Normally, the wallpaper info saved in local storage and sync
349                 // storage are the same. If the synced value changed by sync
350                 // service, they may different. In that case, change wallpaper
351                 // to the one saved in sync storage and update the local value.
352                 if (localInfo == undefined ||
353                     localInfo.url != syncInfo.url ||
354                     localInfo.layout != syncInfo.layout ||
355                     localInfo.source != syncInfo.source) {
356                   if (syncInfo.source == Constants.WallpaperSourceEnum.Online) {
357                     // TODO(bshe): Consider schedule an alarm to set online
358                     // wallpaper later when failed. Note that we need to cancel
359                     // the retry if user set another wallpaper before retry
360                     // alarm invoked.
361                     WallpaperUtil.setOnlineWallpaper(syncInfo.url,
362                         syncInfo.layout, function() {}, function() {});
363                   } else if (syncInfo.source ==
364                              Constants.WallpaperSourceEnum.Custom) {
365                     WallpaperUtil.setCustomWallpaperFromSyncFS(syncInfo.url,
366                                                                syncInfo.layout);
367                   } else if (syncInfo.source ==
368                               Constants.WallpaperSourceEnum.Default) {
369                     chrome.wallpaperPrivate.resetWallpaper();
370                   }
371                   WallpaperUtil.saveToLocalStorage(
372                       Constants.AccessLocalWallpaperInfoKey, syncInfo);
373                 }
374               });
375             }
376           });
377         });
378       }
379     } else {
380       // If sync theme is disabled, use values from chrome.storage.local to
381       // track wallpaper changes.
382       if (changes[Constants.AccessLocalSurpriseMeEnabledKey]) {
383         if (changes[Constants.AccessLocalSurpriseMeEnabledKey].newValue) {
384           SurpriseWallpaper.getInstance().next();
385         } else {
386           SurpriseWallpaper.getInstance().disable();
387         }
388       }
389     }
390   });
393 chrome.alarms.onAlarm.addListener(function() {
394   SurpriseWallpaper.getInstance().next();
397 chrome.wallpaperPrivate.onWallpaperChangedBy3rdParty.addListener(function() {
398   WallpaperUtil.saveToLocalStorage(
399       Constants.AccessLocalSurpriseMeEnabledKey, false, function() {
400     WallpaperUtil.saveToSyncStorage(Constants.AccessSyncSurpriseMeEnabledKey,
401                                     false);
402   });
403   SurpriseWallpaper.getInstance().disable();