Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js

Issue 2944703004: Run clang-format on .js files in c/b/r/chromeos (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_images_grid.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * WallpaperManager constructor. 6 * WallpaperManager constructor.
7 * 7 *
8 * WallpaperManager objects encapsulate the functionality of the wallpaper 8 * WallpaperManager objects encapsulate the functionality of the wallpaper
9 * manager extension. 9 * manager extension.
10 * 10 *
(...skipping 13 matching lines...) Expand all
24 this.wallpaperRequest_ = null; 24 this.wallpaperRequest_ = null;
25 this.wallpaperDirs_ = WallpaperDirectories.getInstance(); 25 this.wallpaperDirs_ = WallpaperDirectories.getInstance();
26 this.preManifestDomInit_(); 26 this.preManifestDomInit_();
27 this.fetchManifest_(); 27 this.fetchManifest_();
28 } 28 }
29 29
30 // Anonymous 'namespace'. 30 // Anonymous 'namespace'.
31 // TODO(bshe): Get rid of anonymous namespace. 31 // TODO(bshe): Get rid of anonymous namespace.
32 (function() { 32 (function() {
33 33
34 /** 34 /**
35 * URL of the learn more page for wallpaper picker. 35 * URL of the learn more page for wallpaper picker.
36 */ 36 */
37 /** @const */ var LearnMoreURL = 37 /** @const */ var LearnMoreURL =
38 'https://support.google.com/chromebook/?p=wallpaper_fileerror&hl=' + 38 'https://support.google.com/chromebook/?p=wallpaper_fileerror&hl=' +
39 navigator.language; 39 navigator.language;
40 40
41 /** 41 /**
42 * Index of the All category. It is the first category in wallpaper picker. 42 * Index of the All category. It is the first category in wallpaper picker.
43 */ 43 */
44 /** @const */ var AllCategoryIndex = 0; 44 /** @const */ var AllCategoryIndex = 0;
45 45
46 /** 46 /**
47 * Index offset of categories parsed from manifest. The All category is added 47 * Index offset of categories parsed from manifest. The All category is added
48 * before them. So the offset is 1. 48 * before them. So the offset is 1.
49 */ 49 */
50 /** @const */ var OnlineCategoriesOffset = 1; 50 /** @const */ var OnlineCategoriesOffset = 1;
51 51
52 /** 52 /**
53 * Returns a translated string. 53 * Returns a translated string.
54 * 54 *
55 * Wrapper function to make dealing with translated strings more concise. 55 * Wrapper function to make dealing with translated strings more concise.
56 * 56 *
57 * @param {string} id The id of the string to return. 57 * @param {string} id The id of the string to return.
58 * @return {string} The translated string. 58 * @return {string} The translated string.
59 */ 59 */
60 function str(id) { 60 function str(id) {
61 return loadTimeData.getString(id); 61 return loadTimeData.getString(id);
62 } 62 }
63 63
64 /** 64 /**
65 * Returns the base name for |file_path|. 65 * Returns the base name for |file_path|.
66 * @param {string} file_path The path of the file. 66 * @param {string} file_path The path of the file.
67 * @return {string} The base name of the file. 67 * @return {string} The base name of the file.
68 */ 68 */
69 function getBaseName(file_path) { 69 function getBaseName(file_path) {
70 return file_path.substring(file_path.lastIndexOf('/') + 1); 70 return file_path.substring(file_path.lastIndexOf('/') + 1);
71 } 71 }
72 72
73 /** 73 /**
74 * Retruns the current selected layout. 74 * Retruns the current selected layout.
75 * @return {string} The selected layout. 75 * @return {string} The selected layout.
76 */ 76 */
77 function getSelectedLayout() { 77 function getSelectedLayout() {
78 var setWallpaperLayout = $('set-wallpaper-layout'); 78 var setWallpaperLayout = $('set-wallpaper-layout');
79 return setWallpaperLayout.options[setWallpaperLayout.selectedIndex].value; 79 return setWallpaperLayout.options[setWallpaperLayout.selectedIndex].value;
80 } 80 }
81 81
82 /** 82 /**
83 * Loads translated strings. 83 * Loads translated strings.
84 */ 84 */
85 WallpaperManager.initStrings = function(callback) { 85 WallpaperManager.initStrings = function(callback) {
86 chrome.wallpaperPrivate.getStrings(function(strings) { 86 chrome.wallpaperPrivate.getStrings(function(strings) {
87 loadTimeData.data = strings; 87 loadTimeData.data = strings;
88 if (callback) 88 if (callback)
89 callback(); 89 callback();
90 }); 90 });
91 }; 91 };
92 92
93 /** 93 /**
94 * Requests wallpaper manifest file from server. 94 * Requests wallpaper manifest file from server.
95 */ 95 */
96 WallpaperManager.prototype.fetchManifest_ = function() { 96 WallpaperManager.prototype.fetchManifest_ = function() {
97 var locale = navigator.language; 97 var locale = navigator.language;
98 if (!this.enableOnlineWallpaper_) { 98 if (!this.enableOnlineWallpaper_) {
99 this.postManifestDomInit_(); 99 this.postManifestDomInit_();
100 return; 100 return;
101 } 101 }
102 102
103 var urls = [ 103 var urls = [
104 str('manifestBaseURL') + locale + '.json', 104 str('manifestBaseURL') + locale + '.json',
105 // Fallback url. Use 'en' locale by default. 105 // Fallback url. Use 'en' locale by default.
106 str('manifestBaseURL') + 'en.json']; 106 str('manifestBaseURL') + 'en.json'
107 107 ];
108 var asyncFetchManifestFromUrls = function(urls, func, successCallback, 108
109 failureCallback) { 109 var asyncFetchManifestFromUrls = function(
110 var index = 0; 110 urls, func, successCallback, failureCallback) {
111 var loop = { 111 var index = 0;
112 next: function() { 112 var loop = {
113 if (index < urls.length) { 113 next: function() {
114 func(loop, urls[index]); 114 if (index < urls.length) {
115 index++; 115 func(loop, urls[index]);
116 } else { 116 index++;
117 failureCallback(); 117 } else {
118 }
119 },
120
121 success: function(response) {
122 successCallback(response);
123 },
124
125 failure: function() {
126 failureCallback(); 118 failureCallback();
127 } 119 }
128 }; 120 },
129 loop.next(); 121
130 }; 122 success: function(response) {
131 123 successCallback(response);
132 var fetchManifestAsync = function(loop, url) { 124 },
133 var xhr = new XMLHttpRequest(); 125
134 try { 126 failure: function() {
135 xhr.addEventListener('loadend', function(e) { 127 failureCallback();
136 if (this.status == 200 && this.responseText != null) {
137 try {
138 var manifest = JSON.parse(this.responseText);
139 loop.success(manifest);
140 } catch (e) {
141 loop.failure();
142 }
143 } else {
144 loop.next();
145 }
146 });
147 xhr.open('GET', url, true);
148 xhr.send(null);
149 } catch (e) {
150 loop.failure();
151 } 128 }
152 }; 129 };
153 130 loop.next();
154 if (navigator.onLine) { 131 };
155 asyncFetchManifestFromUrls(urls, fetchManifestAsync, 132
156 this.onLoadManifestSuccess_.bind(this), 133 var fetchManifestAsync = function(loop, url) {
157 this.onLoadManifestFailed_.bind(this)); 134 var xhr = new XMLHttpRequest();
158 } else { 135 try {
159 // If device is offline, fetches manifest from local storage. 136 xhr.addEventListener('loadend', function(e) {
160 // TODO(bshe): Always loading the offline manifest first and replacing 137 if (this.status == 200 && this.responseText != null) {
161 // with the online one when available. 138 try {
162 this.onLoadManifestFailed_(); 139 var manifest = JSON.parse(this.responseText);
140 loop.success(manifest);
141 } catch (e) {
142 loop.failure();
143 }
144 } else {
145 loop.next();
146 }
147 });
148 xhr.open('GET', url, true);
149 xhr.send(null);
150 } catch (e) {
151 loop.failure();
163 } 152 }
164 }; 153 };
165 154
166 /** 155 if (navigator.onLine) {
167 * Shows error message in a centered dialog. 156 asyncFetchManifestFromUrls(
168 * @private 157 urls, fetchManifestAsync, this.onLoadManifestSuccess_.bind(this),
169 * @param {string} errroMessage The string to show in the error dialog. 158 this.onLoadManifestFailed_.bind(this));
170 */ 159 } else {
171 WallpaperManager.prototype.showError_ = function(errorMessage) { 160 // If device is offline, fetches manifest from local storage.
172 document.querySelector('.error-message').textContent = errorMessage; 161 // TODO(bshe): Always loading the offline manifest first and replacing
173 $('error-container').hidden = false; 162 // with the online one when available.
163 this.onLoadManifestFailed_();
164 }
165 };
166
167 /**
168 * Shows error message in a centered dialog.
169 * @private
170 * @param {string} errroMessage The string to show in the error dialog.
171 */
172 WallpaperManager.prototype.showError_ = function(errorMessage) {
173 document.querySelector('.error-message').textContent = errorMessage;
174 $('error-container').hidden = false;
175 };
176
177 /**
178 * Sets manifest loaded from server. Called after manifest is successfully
179 * loaded.
180 * @param {object} manifest The parsed manifest file.
181 */
182 WallpaperManager.prototype.onLoadManifestSuccess_ = function(manifest) {
183 this.manifest_ = manifest;
184 WallpaperUtil.saveToLocalStorage(Constants.AccessLocalManifestKey, manifest);
185 this.postManifestDomInit_();
186 };
187
188 // Sets manifest to previously saved object if any and shows connection error.
189 // Called after manifest failed to load.
190 WallpaperManager.prototype.onLoadManifestFailed_ = function() {
191 var accessManifestKey = Constants.AccessLocalManifestKey;
192 var self = this;
193 Constants.WallpaperLocalStorage.get(accessManifestKey, function(items) {
194 self.manifest_ = items[accessManifestKey] ? items[accessManifestKey] : null;
195 self.showError_(str('connectionFailed'));
196 self.postManifestDomInit_();
197 $('wallpaper-grid').classList.add('image-picker-offline');
198 });
199 };
200
201 /**
202 * Toggle surprise me feature of wallpaper picker. It fires an storage
203 * onChanged event. Event handler for that event is in event_page.js.
204 * @private
205 */
206 WallpaperManager.prototype.toggleSurpriseMe_ = function() {
207 var self = this;
208 var checkbox = $('surprise-me').querySelector('#checkbox');
209 var shouldEnable = !checkbox.classList.contains('checked');
210 var onSuccess = function() {
211 if (chrome.runtime.lastError == null) {
212 if (shouldEnable) {
213 self.document_.body.removeAttribute('surprise-me-disabled');
214 checkbox.classList.add('checked');
215 // Hides the wallpaper set by message if there is any.
216 $('wallpaper-set-by-message').textContent = '';
217 } else {
218 // Unchecking the "Surprise me" checkbox falls back to the previous
219 // wallpaper before "Surprise me" was turned on.
220 if (self.wallpaperGrid_.activeItem) {
221 self.setSelectedWallpaper_(self.wallpaperGrid_.activeItem);
222 self.onWallpaperChanged_(
223 self.wallpaperGrid_.activeItem, self.currentWallpaper_);
224 }
225 checkbox.classList.remove('checked');
226 self.document_.body.setAttribute('surprise-me-disabled', '');
227 }
228 $('categories-list').disabled = shouldEnable;
229 $('wallpaper-grid').disabled = shouldEnable;
230 } else {
231 // TODO(bshe): show error message to user.
232 console.error('Failed to save surprise me option to chrome storage.');
233 }
174 }; 234 };
175 235
176 /** 236 // To prevent the onChanged event being fired twice, we only save the value
177 * Sets manifest loaded from server. Called after manifest is successfully 237 // to sync storage if the sync theme is enabled, otherwise save it to local
178 * loaded. 238 // storage.
179 * @param {object} manifest The parsed manifest file. 239 WallpaperUtil.enabledSyncThemesCallback(function(syncEnabled) {
180 */ 240 if (syncEnabled)
181 WallpaperManager.prototype.onLoadManifestSuccess_ = function(manifest) { 241 WallpaperUtil.saveToSyncStorage(
182 this.manifest_ = manifest; 242 Constants.AccessSyncSurpriseMeEnabledKey, shouldEnable, onSuccess);
183 WallpaperUtil.saveToLocalStorage(Constants.AccessLocalManifestKey, 243 else
184 manifest); 244 WallpaperUtil.saveToLocalStorage(
185 this.postManifestDomInit_(); 245 Constants.AccessLocalSurpriseMeEnabledKey, shouldEnable, onSuccess);
246 });
247 };
248
249 /**
250 * One-time initialization of various DOM nodes. Fetching manifest may take a
251 * long time due to slow connection. Dom nodes that do not depend on manifest
252 * should be initialized here to unblock from manifest fetching.
253 */
254 WallpaperManager.prototype.preManifestDomInit_ = function() {
255 $('window-close-button').addEventListener('click', function() {
256 window.close();
257 });
258 this.document_.defaultView.addEventListener(
259 'resize', this.onResize_.bind(this));
260 this.document_.defaultView.addEventListener(
261 'keydown', this.onKeyDown_.bind(this));
262 $('learn-more').href = LearnMoreURL;
263 $('close-error').addEventListener('click', function() {
264 $('error-container').hidden = true;
265 });
266 $('close-wallpaper-selection').addEventListener('click', function() {
267 $('wallpaper-selection-container').hidden = true;
268 $('set-wallpaper-layout').disabled = true;
269 });
270 };
271
272 /**
273 * One-time initialization of various DOM nodes. Dom nodes that do depend on
274 * manifest should be initialized here.
275 */
276 WallpaperManager.prototype.postManifestDomInit_ = function() {
277 i18nTemplate.process(this.document_, loadTimeData);
278 this.initCategoriesList_();
279 this.initThumbnailsGrid_();
280 this.presetCategory_();
281
282 $('file-selector')
283 .addEventListener('change', this.onFileSelectorChanged_.bind(this));
284 $('set-wallpaper-layout')
285 .addEventListener('change', this.onWallpaperLayoutChanged_.bind(this));
286
287 // Always prefer the value from local filesystem to avoid the time window
288 // of setting the third party app name and the third party wallpaper.
289 var getThirdPartyAppName = function(callback) {
290 Constants.WallpaperLocalStorage.get(
291 Constants.AccessLocalWallpaperInfoKey, function(items) {
292 var localInfo = items[Constants.AccessLocalWallpaperInfoKey];
293 if (localInfo && localInfo.hasOwnProperty('appName'))
294 callback(localInfo.appName);
295 else if (loadTimeData.valueExists('wallpaperAppName'))
296 callback(str('wallpaperAppName'));
297 else
298 callback('');
299 });
186 }; 300 };
187 301
188 // Sets manifest to previously saved object if any and shows connection error. 302 getThirdPartyAppName(function(appName) {
189 // Called after manifest failed to load. 303 if (!!appName) {
190 WallpaperManager.prototype.onLoadManifestFailed_ = function() { 304 $('wallpaper-set-by-message').textContent =
191 var accessManifestKey = Constants.AccessLocalManifestKey; 305 loadTimeData.getStringF('currentWallpaperSetByMessage', appName);
306 $('wallpaper-grid').classList.add('small');
307 } else {
308 $('wallpaper-grid').classList.remove('small');
309 }
310 });
311
312 if (this.enableOnlineWallpaper_) {
192 var self = this; 313 var self = this;
193 Constants.WallpaperLocalStorage.get(accessManifestKey, function(items) { 314 self.document_.body.setAttribute('surprise-me-disabled', '');
194 self.manifest_ = items[accessManifestKey] ? 315 $('surprise-me').hidden = false;
195 items[accessManifestKey] : null; 316 $('surprise-me')
196 self.showError_(str('connectionFailed')); 317 .addEventListener('click', this.toggleSurpriseMe_.bind(this));
197 self.postManifestDomInit_(); 318 var onSurpriseMeEnabled = function() {
319 $('surprise-me').querySelector('#checkbox').classList.add('checked');
320 $('categories-list').disabled = true;
321 $('wallpaper-grid').disabled = true;
322 self.document_.body.removeAttribute('surprise-me-disabled');
323 };
324
325 WallpaperUtil.enabledSyncThemesCallback(function(syncEnabled) {
326 // Surprise me has been moved from local to sync storage, prefer
327 // values from sync, but if unset check local and update synced pref
328 // if applicable.
329 if (syncEnabled) {
330 Constants.WallpaperSyncStorage.get(
331 Constants.AccessSyncSurpriseMeEnabledKey, function(items) {
332 if (items.hasOwnProperty(
333 Constants.AccessSyncSurpriseMeEnabledKey)) {
334 if (items[Constants.AccessSyncSurpriseMeEnabledKey]) {
335 onSurpriseMeEnabled();
336 }
337 } else {
338 Constants.WallpaperLocalStorage.get(
339 Constants.AccessLocalSurpriseMeEnabledKey, function(items) {
340 if (items.hasOwnProperty(
341 Constants.AccessLocalSurpriseMeEnabledKey)) {
342 WallpaperUtil.saveToSyncStorage(
343 Constants.AccessSyncSurpriseMeEnabledKey,
344 items[Constants.AccessLocalSurpriseMeEnabledKey]);
345 if (items[Constants.AccessLocalSurpriseMeEnabledKey]) {
346 onSurpriseMeEnabled();
347 }
348 }
349 });
350 }
351 });
352 } else {
353 Constants.WallpaperLocalStorage.get(
354 Constants.AccessLocalSurpriseMeEnabledKey, function(items) {
355 if (items.hasOwnProperty(
356 Constants.AccessLocalSurpriseMeEnabledKey)) {
357 if (items[Constants.AccessLocalSurpriseMeEnabledKey]) {
358 onSurpriseMeEnabled();
359 }
360 }
361 });
362 }
363 });
364
365 window.addEventListener('offline', function() {
366 chrome.wallpaperPrivate.getOfflineWallpaperList(function(lists) {
367 if (!self.downloadedListMap_)
368 self.downloadedListMap_ = {};
369 for (var i = 0; i < lists.length; i++) {
370 self.downloadedListMap_[lists[i]] = true;
371 }
372 var thumbnails = self.document_.querySelectorAll('.thumbnail');
373 for (var i = 0; i < thumbnails.length; i++) {
374 var thumbnail = thumbnails[i];
375 var url = self.wallpaperGrid_.dataModel.item(i).baseURL;
376 var fileName = getBaseName(url) + Constants.HighResolutionSuffix;
377 if (self.downloadedListMap_ &&
378 self.downloadedListMap_.hasOwnProperty(encodeURI(fileName))) {
379 thumbnail.offline = true;
380 }
381 }
382 });
198 $('wallpaper-grid').classList.add('image-picker-offline'); 383 $('wallpaper-grid').classList.add('image-picker-offline');
199 }); 384 });
200 }; 385 window.addEventListener('online', function() {
201 386 self.downloadedListMap_ = null;
202 /** 387 $('wallpaper-grid').classList.remove('image-picker-offline');
203 * Toggle surprise me feature of wallpaper picker. It fires an storage
204 * onChanged event. Event handler for that event is in event_page.js.
205 * @private
206 */
207 WallpaperManager.prototype.toggleSurpriseMe_ = function() {
208 var self = this;
209 var checkbox = $('surprise-me').querySelector('#checkbox');
210 var shouldEnable = !checkbox.classList.contains('checked');
211 var onSuccess = function() {
212 if (chrome.runtime.lastError == null) {
213 if (shouldEnable) {
214 self.document_.body.removeAttribute('surprise-me-disabled');
215 checkbox.classList.add('checked');
216 // Hides the wallpaper set by message if there is any.
217 $('wallpaper-set-by-message').textContent = '';
218 } else {
219 // Unchecking the "Surprise me" checkbox falls back to the previous
220 // wallpaper before "Surprise me" was turned on.
221 if (self.wallpaperGrid_.activeItem) {
222 self.setSelectedWallpaper_(self.wallpaperGrid_.activeItem);
223 self.onWallpaperChanged_(self.wallpaperGrid_.activeItem,
224 self.currentWallpaper_);
225 }
226 checkbox.classList.remove('checked');
227 self.document_.body.setAttribute('surprise-me-disabled', '');
228 }
229 $('categories-list').disabled = shouldEnable;
230 $('wallpaper-grid').disabled = shouldEnable;
231 } else {
232 // TODO(bshe): show error message to user.
233 console.error('Failed to save surprise me option to chrome storage.');
234 }
235 };
236
237 // To prevent the onChanged event being fired twice, we only save the value
238 // to sync storage if the sync theme is enabled, otherwise save it to local
239 // storage.
240 WallpaperUtil.enabledSyncThemesCallback(function(syncEnabled) {
241 if (syncEnabled)
242 WallpaperUtil.saveToSyncStorage(
243 Constants.AccessSyncSurpriseMeEnabledKey, shouldEnable, onSuccess);
244 else
245 WallpaperUtil.saveToLocalStorage(
246 Constants.AccessLocalSurpriseMeEnabledKey, shouldEnable, onSuccess);
247 }); 388 });
248 }; 389 }
249 390
250 /** 391 this.onResize_();
251 * One-time initialization of various DOM nodes. Fetching manifest may take a 392 this.initContextMenuAndCommand_();
252 * long time due to slow connection. Dom nodes that do not depend on manifest 393 WallpaperUtil.testSendMessage('launched');
253 * should be initialized here to unblock from manifest fetching. 394 };
254 */ 395
255 WallpaperManager.prototype.preManifestDomInit_ = function() { 396 /**
256 $('window-close-button').addEventListener('click', function() { 397 * One-time initialization of context menu and command.
257 window.close(); 398 */
258 }); 399 WallpaperManager.prototype.initContextMenuAndCommand_ = function() {
259 this.document_.defaultView.addEventListener( 400 this.wallpaperContextMenu_ = $('wallpaper-context-menu');
260 'resize', this.onResize_.bind(this)); 401 cr.ui.Menu.decorate(this.wallpaperContextMenu_);
261 this.document_.defaultView.addEventListener( 402 cr.ui.contextMenuHandler.setContextMenu(
262 'keydown', this.onKeyDown_.bind(this)); 403 this.wallpaperGrid_, this.wallpaperContextMenu_);
263 $('learn-more').href = LearnMoreURL; 404 var commands = this.dialogDom_.querySelectorAll('command');
264 $('close-error').addEventListener('click', function() { 405 for (var i = 0; i < commands.length; i++)
265 $('error-container').hidden = true; 406 cr.ui.Command.decorate(commands[i]);
266 }); 407
267 $('close-wallpaper-selection').addEventListener('click', function() { 408 var doc = this.document_;
268 $('wallpaper-selection-container').hidden = true; 409 doc.addEventListener('command', this.onCommand_.bind(this));
269 $('set-wallpaper-layout').disabled = true; 410 doc.addEventListener('canExecute', this.onCommandCanExecute_.bind(this));
270 }); 411 };
271 }; 412
272 413 /**
273 /** 414 * Handles a command being executed.
274 * One-time initialization of various DOM nodes. Dom nodes that do depend on 415 * @param {Event} event A command event.
275 * manifest should be initialized here. 416 */
276 */ 417 WallpaperManager.prototype.onCommand_ = function(event) {
277 WallpaperManager.prototype.postManifestDomInit_ = function() { 418 if (event.command.id == 'delete') {
278 i18nTemplate.process(this.document_, loadTimeData); 419 var wallpaperGrid = this.wallpaperGrid_;
279 this.initCategoriesList_(); 420 var selectedIndex = wallpaperGrid.selectionModel.selectedIndex;
280 this.initThumbnailsGrid_(); 421 var item = wallpaperGrid.dataModel.item(selectedIndex);
281 this.presetCategory_(); 422 if (!item || item.source != Constants.WallpaperSourceEnum.Custom)
282 423 return;
283 $('file-selector').addEventListener( 424 this.removeCustomWallpaper(item.baseURL);
284 'change', this.onFileSelectorChanged_.bind(this)); 425 wallpaperGrid.dataModel.splice(selectedIndex, 1);
285 $('set-wallpaper-layout').addEventListener( 426 // Calculate the number of remaining custom wallpapers. The add new button
286 'change', this.onWallpaperLayoutChanged_.bind(this)); 427 // in data model needs to be excluded.
287 428 var customWallpaperCount = wallpaperGrid.dataModel.length - 1;
288 // Always prefer the value from local filesystem to avoid the time window 429 if (customWallpaperCount == 0) {
289 // of setting the third party app name and the third party wallpaper. 430 // Active custom wallpaper is also copied in chronos data dir. It needs
290 var getThirdPartyAppName = function(callback) { 431 // to be deleted.
291 Constants.WallpaperLocalStorage.get( 432 chrome.wallpaperPrivate.resetWallpaper();
292 Constants.AccessLocalWallpaperInfoKey, function(items) { 433 this.onWallpaperChanged_(null, null);
293 var localInfo = items[Constants.AccessLocalWallpaperInfoKey]; 434 } else {
294 if (localInfo && localInfo.hasOwnProperty('appName')) 435 selectedIndex = Math.min(selectedIndex, customWallpaperCount - 1);
295 callback(localInfo.appName); 436 wallpaperGrid.selectionModel.selectedIndex = selectedIndex;
296 else if (loadTimeData.valueExists('wallpaperAppName'))
297 callback(str('wallpaperAppName'));
298 else
299 callback('');
300 });
301 };
302
303 getThirdPartyAppName(function(appName) {
304 if (!!appName) {
305 $('wallpaper-set-by-message').textContent = loadTimeData.getStringF(
306 'currentWallpaperSetByMessage', appName);
307 $('wallpaper-grid').classList.add('small');
308 } else {
309 $('wallpaper-grid').classList.remove('small');
310 }
311 });
312
313 if (this.enableOnlineWallpaper_) {
314 var self = this;
315 self.document_.body.setAttribute('surprise-me-disabled', '');
316 $('surprise-me').hidden = false;
317 $('surprise-me').addEventListener('click',
318 this.toggleSurpriseMe_.bind(this));
319 var onSurpriseMeEnabled = function() {
320 $('surprise-me').querySelector('#checkbox').classList.add('checked');
321 $('categories-list').disabled = true;
322 $('wallpaper-grid').disabled = true;
323 self.document_.body.removeAttribute('surprise-me-disabled');
324 };
325
326 WallpaperUtil.enabledSyncThemesCallback(function(syncEnabled) {
327 // Surprise me has been moved from local to sync storage, prefer
328 // values from sync, but if unset check local and update synced pref
329 // if applicable.
330 if (syncEnabled) {
331 Constants.WallpaperSyncStorage.get(
332 Constants.AccessSyncSurpriseMeEnabledKey, function(items) {
333 if (items.hasOwnProperty(
334 Constants.AccessSyncSurpriseMeEnabledKey)) {
335 if (items[Constants.AccessSyncSurpriseMeEnabledKey]) {
336 onSurpriseMeEnabled();
337 }
338 } else {
339 Constants.WallpaperLocalStorage.get(
340 Constants.AccessLocalSurpriseMeEnabledKey, function(items) {
341 if (items.hasOwnProperty(
342 Constants.AccessLocalSurpriseMeEnabledKey)) {
343 WallpaperUtil.saveToSyncStorage(
344 Constants.AccessSyncSurpriseMeEnabledKey,
345 items[Constants.AccessLocalSurpriseMeEnabledKey]);
346 if (items[Constants.AccessLocalSurpriseMeEnabledKey]) {
347 onSurpriseMeEnabled();
348 }
349 }
350 });
351 }
352 });
353 } else {
354 Constants.WallpaperLocalStorage.get(
355 Constants.AccessLocalSurpriseMeEnabledKey, function(items) {
356 if (items.hasOwnProperty(
357 Constants.AccessLocalSurpriseMeEnabledKey)) {
358 if (items[Constants.AccessLocalSurpriseMeEnabledKey]) {
359 onSurpriseMeEnabled();
360 }
361 }
362 });
363 }
364 });
365
366 window.addEventListener('offline', function() {
367 chrome.wallpaperPrivate.getOfflineWallpaperList(function(lists) {
368 if (!self.downloadedListMap_)
369 self.downloadedListMap_ = {};
370 for (var i = 0; i < lists.length; i++) {
371 self.downloadedListMap_[lists[i]] = true;
372 }
373 var thumbnails = self.document_.querySelectorAll('.thumbnail');
374 for (var i = 0; i < thumbnails.length; i++) {
375 var thumbnail = thumbnails[i];
376 var url = self.wallpaperGrid_.dataModel.item(i).baseURL;
377 var fileName = getBaseName(url) + Constants.HighResolutionSuffix;
378 if (self.downloadedListMap_ &&
379 self.downloadedListMap_.hasOwnProperty(encodeURI(fileName))) {
380 thumbnail.offline = true;
381 }
382 }
383 });
384 $('wallpaper-grid').classList.add('image-picker-offline');
385 });
386 window.addEventListener('online', function() {
387 self.downloadedListMap_ = null;
388 $('wallpaper-grid').classList.remove('image-picker-offline');
389 });
390 } 437 }
391 438 event.cancelBubble = true;
392 this.onResize_(); 439 }
393 this.initContextMenuAndCommand_(); 440 };
394 WallpaperUtil.testSendMessage('launched'); 441
395 }; 442 /**
396 443 * Decides if a command can be executed on current target.
397 /** 444 * @param {Event} event A command event.
398 * One-time initialization of context menu and command. 445 */
399 */ 446 WallpaperManager.prototype.onCommandCanExecute_ = function(event) {
400 WallpaperManager.prototype.initContextMenuAndCommand_ = function() { 447 switch (event.command.id) {
401 this.wallpaperContextMenu_ = $('wallpaper-context-menu'); 448 case 'delete':
402 cr.ui.Menu.decorate(this.wallpaperContextMenu_);
403 cr.ui.contextMenuHandler.setContextMenu(this.wallpaperGrid_,
404 this.wallpaperContextMenu_);
405 var commands = this.dialogDom_.querySelectorAll('command');
406 for (var i = 0; i < commands.length; i++)
407 cr.ui.Command.decorate(commands[i]);
408
409 var doc = this.document_;
410 doc.addEventListener('command', this.onCommand_.bind(this));
411 doc.addEventListener('canExecute', this.onCommandCanExecute_.bind(this));
412 };
413
414 /**
415 * Handles a command being executed.
416 * @param {Event} event A command event.
417 */
418 WallpaperManager.prototype.onCommand_ = function(event) {
419 if (event.command.id == 'delete') {
420 var wallpaperGrid = this.wallpaperGrid_; 449 var wallpaperGrid = this.wallpaperGrid_;
421 var selectedIndex = wallpaperGrid.selectionModel.selectedIndex; 450 var selectedIndex = wallpaperGrid.selectionModel.selectedIndex;
422 var item = wallpaperGrid.dataModel.item(selectedIndex); 451 var item = wallpaperGrid.dataModel.item(selectedIndex);
423 if (!item || item.source != Constants.WallpaperSourceEnum.Custom) 452 if (selectedIndex != this.wallpaperGrid_.dataModel.length - 1 && item &&
424 return; 453 item.source == Constants.WallpaperSourceEnum.Custom) {
425 this.removeCustomWallpaper(item.baseURL); 454 event.canExecute = true;
426 wallpaperGrid.dataModel.splice(selectedIndex, 1); 455 break;
427 // Calculate the number of remaining custom wallpapers. The add new button
428 // in data model needs to be excluded.
429 var customWallpaperCount = wallpaperGrid.dataModel.length - 1;
430 if (customWallpaperCount == 0) {
431 // Active custom wallpaper is also copied in chronos data dir. It needs
432 // to be deleted.
433 chrome.wallpaperPrivate.resetWallpaper();
434 this.onWallpaperChanged_(null, null);
435 } else {
436 selectedIndex = Math.min(selectedIndex, customWallpaperCount - 1);
437 wallpaperGrid.selectionModel.selectedIndex = selectedIndex;
438 } 456 }
439 event.cancelBubble = true; 457 default:
440 } 458 event.canExecute = false;
441 }; 459 }
442 460 };
443 /** 461
444 * Decides if a command can be executed on current target. 462 /**
445 * @param {Event} event A command event. 463 * Preset to the category which contains current wallpaper.
446 */ 464 */
447 WallpaperManager.prototype.onCommandCanExecute_ = function(event) { 465 WallpaperManager.prototype.presetCategory_ = function() {
448 switch (event.command.id) { 466 this.currentWallpaper_ = str('currentWallpaper');
449 case 'delete': 467 // The currentWallpaper_ is either a url contains HightResolutionSuffix or a
450 var wallpaperGrid = this.wallpaperGrid_; 468 // custom wallpaper file name converted from an integer value represent
451 var selectedIndex = wallpaperGrid.selectionModel.selectedIndex; 469 // time (e.g., 13006377367586070).
452 var item = wallpaperGrid.dataModel.item(selectedIndex); 470 if (!this.enableOnlineWallpaper_ ||
453 if (selectedIndex != this.wallpaperGrid_.dataModel.length - 1 && 471 (this.currentWallpaper_ &&
454 item && item.source == Constants.WallpaperSourceEnum.Custom) { 472 this.currentWallpaper_.indexOf(Constants.HighResolutionSuffix) == -1)) {
455 event.canExecute = true; 473 // Custom is the last one in the categories list.
474 this.categoriesList_.selectionModel.selectedIndex =
475 this.categoriesList_.dataModel.length - 1;
476 return;
477 }
478 var self = this;
479 var presetCategoryInner = function() {
480 // Selects the first category in the categories list of current
481 // wallpaper as the default selected category when showing wallpaper
482 // picker UI.
483 var presetCategory = AllCategoryIndex;
484 if (self.currentWallpaper_) {
485 for (var key in self.manifest_.wallpaper_list) {
486 var url = self.manifest_.wallpaper_list[key].base_url +
487 Constants.HighResolutionSuffix;
488 if (url.indexOf(self.currentWallpaper_) != -1 &&
489 self.manifest_.wallpaper_list[key].categories.length > 0) {
490 presetCategory = self.manifest_.wallpaper_list[key].categories[0] +
491 OnlineCategoriesOffset;
456 break; 492 break;
457 } 493 }
458 default: 494 }
459 event.canExecute = false;
460 } 495 }
496 self.categoriesList_.selectionModel.selectedIndex = presetCategory;
461 }; 497 };
462 498 if (navigator.onLine) {
463 /** 499 presetCategoryInner();
464 * Preset to the category which contains current wallpaper. 500 } else {
465 */ 501 // If device is offline, gets the available offline wallpaper list first.
466 WallpaperManager.prototype.presetCategory_ = function() { 502 // Wallpapers which are not in the list will display a grayscaled
467 this.currentWallpaper_ = str('currentWallpaper'); 503 // thumbnail.
468 // The currentWallpaper_ is either a url contains HightResolutionSuffix or a 504 chrome.wallpaperPrivate.getOfflineWallpaperList(function(lists) {
469 // custom wallpaper file name converted from an integer value represent 505 if (!self.downloadedListMap_)
470 // time (e.g., 13006377367586070). 506 self.downloadedListMap_ = {};
471 if (!this.enableOnlineWallpaper_ || (this.currentWallpaper_ && 507 for (var i = 0; i < lists.length; i++)
472 this.currentWallpaper_.indexOf(Constants.HighResolutionSuffix) == -1)) { 508 self.downloadedListMap_[lists[i]] = true;
473 // Custom is the last one in the categories list.
474 this.categoriesList_.selectionModel.selectedIndex =
475 this.categoriesList_.dataModel.length - 1;
476 return;
477 }
478 var self = this;
479 var presetCategoryInner = function() {
480 // Selects the first category in the categories list of current
481 // wallpaper as the default selected category when showing wallpaper
482 // picker UI.
483 var presetCategory = AllCategoryIndex;
484 if (self.currentWallpaper_) {
485 for (var key in self.manifest_.wallpaper_list) {
486 var url = self.manifest_.wallpaper_list[key].base_url +
487 Constants.HighResolutionSuffix;
488 if (url.indexOf(self.currentWallpaper_) != -1 &&
489 self.manifest_.wallpaper_list[key].categories.length > 0) {
490 presetCategory = self.manifest_.wallpaper_list[key].categories[0] +
491 OnlineCategoriesOffset;
492 break;
493 }
494 }
495 }
496 self.categoriesList_.selectionModel.selectedIndex = presetCategory;
497 };
498 if (navigator.onLine) {
499 presetCategoryInner(); 509 presetCategoryInner();
500 } else { 510 });
501 // If device is offline, gets the available offline wallpaper list first. 511 }
502 // Wallpapers which are not in the list will display a grayscaled 512 };
503 // thumbnail. 513
504 chrome.wallpaperPrivate.getOfflineWallpaperList(function(lists) { 514 /**
505 if (!self.downloadedListMap_) 515 * Constructs the thumbnails grid.
506 self.downloadedListMap_ = {}; 516 */
507 for (var i = 0; i < lists.length; i++) 517 WallpaperManager.prototype.initThumbnailsGrid_ = function() {
508 self.downloadedListMap_[lists[i]] = true; 518 this.wallpaperGrid_ = $('wallpaper-grid');
509 presetCategoryInner(); 519 wallpapers.WallpaperThumbnailsGrid.decorate(this.wallpaperGrid_);
510 }); 520
511 } 521 this.wallpaperGrid_.addEventListener('change', this.onChange_.bind(this));
512 }; 522 this.wallpaperGrid_.addEventListener('dblclick', this.onClose_.bind(this));
513 523 };
514 /** 524
515 * Constructs the thumbnails grid. 525 /**
516 */ 526 * Handles change event dispatched by wallpaper grid.
517 WallpaperManager.prototype.initThumbnailsGrid_ = function() { 527 */
518 this.wallpaperGrid_ = $('wallpaper-grid'); 528 WallpaperManager.prototype.onChange_ = function() {
519 wallpapers.WallpaperThumbnailsGrid.decorate(this.wallpaperGrid_); 529 // splice may dispatch a change event because the position of selected
520 530 // element changing. But the actual selected element may not change after
521 this.wallpaperGrid_.addEventListener('change', this.onChange_.bind(this)); 531 // splice. Check if the new selected element equals to the previous selected
522 this.wallpaperGrid_.addEventListener('dblclick', this.onClose_.bind(this)); 532 // element before continuing. Otherwise, wallpaper may reset to previous one
523 }; 533 // as described in http://crbug.com/229036.
524 534 if (this.selectedItem_ == this.wallpaperGrid_.selectedItem)
525 /** 535 return;
526 * Handles change event dispatched by wallpaper grid. 536 this.selectedItem_ = this.wallpaperGrid_.selectedItem;
527 */ 537 this.onSelectedItemChanged_();
528 WallpaperManager.prototype.onChange_ = function() { 538 };
529 // splice may dispatch a change event because the position of selected 539
530 // element changing. But the actual selected element may not change after 540 /**
531 // splice. Check if the new selected element equals to the previous selected 541 * Closes window if no pending wallpaper request.
532 // element before continuing. Otherwise, wallpaper may reset to previous one 542 */
533 // as described in http://crbug.com/229036. 543 WallpaperManager.prototype.onClose_ = function() {
534 if (this.selectedItem_ == this.wallpaperGrid_.selectedItem) 544 if (this.wallpaperRequest_) {
535 return; 545 this.wallpaperRequest_.addEventListener('loadend', function() {
536 this.selectedItem_ = this.wallpaperGrid_.selectedItem; 546 // Close window on wallpaper loading finished.
537 this.onSelectedItemChanged_(); 547 window.close();
538 }; 548 });
539 549 } else {
540 /** 550 window.close();
541 * Closes window if no pending wallpaper request. 551 }
542 */ 552 };
543 WallpaperManager.prototype.onClose_ = function() { 553
544 if (this.wallpaperRequest_) { 554 /**
545 this.wallpaperRequest_.addEventListener('loadend', function() { 555 * Moves the check mark to |activeItem| and hides the wallpaper set by third
546 // Close window on wallpaper loading finished. 556 * party message if any. And saves the wallpaper's information to local & sync
547 window.close(); 557 * storage. Called when wallpaper changed successfully.
558 * @param {?Object} activeItem The active item in WallpaperThumbnailsGrid's
559 * data model.
560 * @param {?string} currentWallpaperURL The URL or filename of current
561 * wallpaper.
562 */
563 WallpaperManager.prototype.onWallpaperChanged_ = function(
564 activeItem, currentWallpaperURL) {
565 this.wallpaperGrid_.activeItem = activeItem;
566 this.currentWallpaper_ = currentWallpaperURL;
567 // Hides the wallpaper set by message.
568 $('wallpaper-set-by-message').textContent = '';
569 $('wallpaper-grid').classList.remove('small');
570
571 if (activeItem) {
572 WallpaperUtil.saveWallpaperInfo(
573 currentWallpaperURL, activeItem.layout, activeItem.source, '');
574 } else {
575 WallpaperUtil.saveWallpaperInfo(
576 '', '', Constants.WallpaperSourceEnum.Default, '');
577 }
578 };
579
580 /**
581 * Sets wallpaper to the corresponding wallpaper of selected thumbnail.
582 * @param {{baseURL: string, layout: string, source: string,
583 * availableOffline: boolean, opt_dynamicURL: string,
584 * opt_author: string, opt_authorWebsite: string}}
585 * selectedItem the selected item in WallpaperThumbnailsGrid's data
586 * model.
587 */
588 WallpaperManager.prototype.setSelectedWallpaper_ = function(selectedItem) {
589 var self = this;
590 switch (selectedItem.source) {
591 case Constants.WallpaperSourceEnum.Custom:
592 var errorHandler = this.onFileSystemError_.bind(this);
593 var success = function(dirEntry) {
594 dirEntry.getFile(
595 selectedItem.baseURL, {create: false}, function(fileEntry) {
596 fileEntry.file(function(file) {
597 var reader = new FileReader();
598 reader.readAsArrayBuffer(file);
599 reader.addEventListener('error', errorHandler);
600 reader.addEventListener('load', function(e) {
601 self.setCustomWallpaper(
602 e.target.result, selectedItem.layout, false,
603 selectedItem.baseURL, function(thumbnailData) {
604 self.onWallpaperChanged_(
605 selectedItem, selectedItem.baseURL);
606 WallpaperUtil.storeWallpaperToSyncFS(
607 selectedItem.baseURL, e.target.result);
608 WallpaperUtil.storeWallpaperToSyncFS(
609 selectedItem.baseURL +
610 Constants.CustomWallpaperThumbnailSuffix,
611 thumbnailData);
612 }, errorHandler);
613 });
614 }, errorHandler);
615 }, errorHandler);
616 };
617 this.wallpaperDirs_.getDirectory(
618 Constants.WallpaperDirNameEnum.ORIGINAL, success, errorHandler);
619 break;
620 case Constants.WallpaperSourceEnum.OEM:
621 // Resets back to default wallpaper.
622 chrome.wallpaperPrivate.resetWallpaper();
623 this.onWallpaperChanged_(selectedItem, selectedItem.baseURL);
624 break;
625 case Constants.WallpaperSourceEnum.Online:
626 var wallpaperURL = selectedItem.baseURL + Constants.HighResolutionSuffix;
627 var selectedGridItem = this.wallpaperGrid_.getListItem(selectedItem);
628
629 chrome.wallpaperPrivate.setWallpaperIfExists(
630 wallpaperURL, selectedItem.layout, function(exists) {
631 if (exists) {
632 self.onWallpaperChanged_(selectedItem, wallpaperURL);
633 return;
634 }
635
636 // Falls back to request wallpaper from server.
637 if (self.wallpaperRequest_)
638 self.wallpaperRequest_.abort();
639
640 self.wallpaperRequest_ = new XMLHttpRequest();
641 self.progressManager_.reset(
642 self.wallpaperRequest_, selectedGridItem);
643
644 var onSuccess = function(xhr) {
645 var image = xhr.response;
646 chrome.wallpaperPrivate.setWallpaper(
647 image, selectedItem.layout, wallpaperURL, function() {
648 self.progressManager_.hideProgressBar(selectedGridItem);
649
650 if (chrome.runtime.lastError != undefined &&
651 chrome.runtime.lastError.message !=
652 str('canceledWallpaper')) {
653 self.showError_(chrome.runtime.lastError.message);
654 } else {
655 self.onWallpaperChanged_(selectedItem, wallpaperURL);
656 }
657 });
658 self.wallpaperRequest_ = null;
659 };
660 var onFailure = function(status) {
661 self.progressManager_.hideProgressBar(selectedGridItem);
662 self.showError_(str('downloadFailed'));
663 self.wallpaperRequest_ = null;
664 };
665 WallpaperUtil.fetchURL(
666 wallpaperURL, 'arraybuffer', onSuccess, onFailure,
667 self.wallpaperRequest_);
668 });
669 break;
670 case Constants.WallpaperSourceEnum.Daily:
671 case Constants.WallpaperSourceEnum.ThirdParty:
672 default:
673 console.error('Unsupported wallpaper source.');
674 }
675 };
676
677 /*
678 * Removes the oldest custom wallpaper. If the oldest one is set as current
679 * wallpaper, removes the second oldest one to free some space. This should
680 * only be called when exceeding wallpaper quota.
681 */
682 WallpaperManager.prototype.removeOldestWallpaper_ = function() {
683 // Custom wallpapers should already sorted when put to the data model. The
684 // last element is the add new button, need to exclude it as well.
685 var oldestIndex = this.wallpaperGrid_.dataModel.length - 2;
686 var item = this.wallpaperGrid_.dataModel.item(oldestIndex);
687 if (!item || item.source != Constants.WallpaperSourceEnum.Custom)
688 return;
689 if (item.baseURL == this.currentWallpaper_)
690 item = this.wallpaperGrid_.dataModel.item(--oldestIndex);
691 if (item) {
692 this.removeCustomWallpaper(item.baseURL);
693 this.wallpaperGrid_.dataModel.splice(oldestIndex, 1);
694 }
695 };
696
697 /*
698 * Shows an error message to user and log the failed reason in console.
699 */
700 WallpaperManager.prototype.onFileSystemError_ = function(e) {
701 var msg = '';
702 switch (e.code) {
703 case FileError.QUOTA_EXCEEDED_ERR:
704 msg = 'QUOTA_EXCEEDED_ERR';
705 // Instead of simply remove oldest wallpaper, we should consider a
706 // better way to handle this situation. See crbug.com/180890.
707 this.removeOldestWallpaper_();
708 break;
709 case FileError.NOT_FOUND_ERR:
710 msg = 'NOT_FOUND_ERR';
711 break;
712 case FileError.SECURITY_ERR:
713 msg = 'SECURITY_ERR';
714 break;
715 case FileError.INVALID_MODIFICATION_ERR:
716 msg = 'INVALID_MODIFICATION_ERR';
717 break;
718 case FileError.INVALID_STATE_ERR:
719 msg = 'INVALID_STATE_ERR';
720 break;
721 default:
722 msg = 'Unknown Error';
723 break;
724 }
725 console.error('Error: ' + msg);
726 this.showError_(str('accessFileFailure'));
727 };
728
729 /**
730 * Handles changing of selectedItem in wallpaper manager.
731 */
732 WallpaperManager.prototype.onSelectedItemChanged_ = function() {
733 this.setWallpaperAttribution_(this.selectedItem_);
734
735 if (!this.selectedItem_ || this.selectedItem_.source == 'ADDNEW')
736 return;
737
738 if (this.selectedItem_.baseURL && !this.wallpaperGrid_.inProgramSelection) {
739 if (this.selectedItem_.source == Constants.WallpaperSourceEnum.Custom) {
740 var items = {};
741 var key = this.selectedItem_.baseURL;
742 var self = this;
743 Constants.WallpaperLocalStorage.get(key, function(items) {
744 self.selectedItem_.layout = items[key] ? items[key] : 'CENTER_CROPPED';
745 self.setSelectedWallpaper_(self.selectedItem_);
548 }); 746 });
549 } else { 747 } else {
550 window.close(); 748 this.setSelectedWallpaper_(this.selectedItem_);
551 } 749 }
552 }; 750 }
553 751 };
554 /** 752
555 * Moves the check mark to |activeItem| and hides the wallpaper set by third 753 /**
556 * party message if any. And saves the wallpaper's information to local & sync 754 * Set attributions of wallpaper with given URL. If URL is not valid, clear
557 * storage. Called when wallpaper changed successfully. 755 * the attributions.
558 * @param {?Object} activeItem The active item in WallpaperThumbnailsGrid's 756 * @param {{baseURL: string, dynamicURL: string, layout: string,
559 * data model. 757 * author: string, authorWebsite: string, availableOffline: boolean}}
560 * @param {?string} currentWallpaperURL The URL or filename of current 758 * selectedItem selected wallpaper item in grid.
561 * wallpaper. 759 * @private
562 */ 760 */
563 WallpaperManager.prototype.onWallpaperChanged_ = function( 761 WallpaperManager.prototype.setWallpaperAttribution_ = function(selectedItem) {
564 activeItem, currentWallpaperURL) { 762 // Only online wallpapers have author and website attributes. All other type
565 this.wallpaperGrid_.activeItem = activeItem; 763 // of wallpapers should not show attributions.
566 this.currentWallpaper_ = currentWallpaperURL; 764 if (selectedItem &&
567 // Hides the wallpaper set by message. 765 selectedItem.source == Constants.WallpaperSourceEnum.Online) {
568 $('wallpaper-set-by-message').textContent = ''; 766 $('author-name').textContent = selectedItem.author;
569 $('wallpaper-grid').classList.remove('small'); 767 $('author-website').textContent = $('author-website').href =
570 768 selectedItem.authorWebsite;
571 if (activeItem) { 769 chrome.wallpaperPrivate.getThumbnail(
572 WallpaperUtil.saveWallpaperInfo( 770 selectedItem.baseURL, selectedItem.source, function(data) {
573 currentWallpaperURL, activeItem.layout, activeItem.source, ''); 771 var img = $('attribute-image');
772 if (data) {
773 var blob = new Blob([new Int8Array(data)], {'type': 'image\/png'});
774 img.src = window.URL.createObjectURL(blob);
775 img.addEventListener('load', function(e) {
776 window.URL.revokeObjectURL(this.src);
777 });
778 } else {
779 img.src = '';
780 }
781 });
782 $('wallpaper-attribute').hidden = false;
783 $('attribute-image').hidden = false;
784 return;
785 }
786 $('wallpaper-attribute').hidden = true;
787 $('attribute-image').hidden = true;
788 $('author-name').textContent = '';
789 $('author-website').textContent = $('author-website').href = '';
790 $('attribute-image').src = '';
791 };
792
793 /**
794 * Resize thumbnails grid and categories list to fit the new window size.
795 */
796 WallpaperManager.prototype.onResize_ = function() {
797 this.wallpaperGrid_.redraw();
798 this.categoriesList_.redraw();
799 };
800
801 /**
802 * Close the last opened overlay or app window on pressing the Escape key.
803 * @param {Event} event A keydown event.
804 */
805 WallpaperManager.prototype.onKeyDown_ = function(event) {
806 if (event.keyCode == 27) {
807 // The last opened overlay coincides with the first match of querySelector
808 // because the Error Container is declared in the DOM before the Wallpaper
809 // Selection Container.
810 // TODO(bshe): Make the overlay selection not dependent on the DOM.
811 var closeButtonSelector = '.overlay-container:not([hidden]) .close';
812 var closeButton = this.document_.querySelector(closeButtonSelector);
813 if (closeButton) {
814 closeButton.click();
815 event.preventDefault();
574 } else { 816 } else {
575 WallpaperUtil.saveWallpaperInfo( 817 this.onClose_();
576 '', '', Constants.WallpaperSourceEnum.Default, '');
577 } 818 }
578 }; 819 }
579 820 };
580 /** 821
581 * Sets wallpaper to the corresponding wallpaper of selected thumbnail. 822 /**
582 * @param {{baseURL: string, layout: string, source: string, 823 * Constructs the categories list.
583 * availableOffline: boolean, opt_dynamicURL: string, 824 */
584 * opt_author: string, opt_authorWebsite: string}} 825 WallpaperManager.prototype.initCategoriesList_ = function() {
585 * selectedItem the selected item in WallpaperThumbnailsGrid's data 826 this.categoriesList_ = $('categories-list');
586 * model. 827 wallpapers.WallpaperCategoriesList.decorate(this.categoriesList_);
587 */ 828
588 WallpaperManager.prototype.setSelectedWallpaper_ = function(selectedItem) { 829 this.categoriesList_.selectionModel.addEventListener(
589 var self = this; 830 'change', this.onCategoriesChange_.bind(this));
590 switch (selectedItem.source) { 831
591 case Constants.WallpaperSourceEnum.Custom: 832 if (this.enableOnlineWallpaper_ && this.manifest_) {
592 var errorHandler = this.onFileSystemError_.bind(this); 833 // Adds all category as first category.
593 var success = function(dirEntry) { 834 this.categoriesList_.dataModel.push(str('allCategoryLabel'));
594 dirEntry.getFile(selectedItem.baseURL, {create: false}, 835 for (var key in this.manifest_.categories) {
595 function(fileEntry) { 836 this.categoriesList_.dataModel.push(this.manifest_.categories[key]);
596 fileEntry.file(function(file) {
597 var reader = new FileReader();
598 reader.readAsArrayBuffer(file);
599 reader.addEventListener('error', errorHandler);
600 reader.addEventListener('load', function(e) {
601 self.setCustomWallpaper(e.target.result, selectedItem.layout,
602 false, selectedItem.baseURL,
603 function(thumbnailData) {
604 self.onWallpaperChanged_(selectedItem,
605 selectedItem.baseURL);
606 WallpaperUtil.storeWallpaperToSyncFS(
607 selectedItem.baseURL, e.target.result);
608 WallpaperUtil.storeWallpaperToSyncFS(
609 selectedItem.baseURL +
610 Constants.CustomWallpaperThumbnailSuffix,
611 thumbnailData);
612 },
613 errorHandler);
614 });
615 }, errorHandler);
616 }, errorHandler);
617 };
618 this.wallpaperDirs_.getDirectory(
619 Constants.WallpaperDirNameEnum.ORIGINAL, success, errorHandler);
620 break;
621 case Constants.WallpaperSourceEnum.OEM:
622 // Resets back to default wallpaper.
623 chrome.wallpaperPrivate.resetWallpaper();
624 this.onWallpaperChanged_(selectedItem, selectedItem.baseURL);
625 break;
626 case Constants.WallpaperSourceEnum.Online:
627 var wallpaperURL = selectedItem.baseURL +
628 Constants.HighResolutionSuffix;
629 var selectedGridItem = this.wallpaperGrid_.getListItem(selectedItem);
630
631 chrome.wallpaperPrivate.setWallpaperIfExists(wallpaperURL,
632 selectedItem.layout,
633 function(exists) {
634 if (exists) {
635 self.onWallpaperChanged_(selectedItem, wallpaperURL);
636 return;
637 }
638
639 // Falls back to request wallpaper from server.
640 if (self.wallpaperRequest_)
641 self.wallpaperRequest_.abort();
642
643 self.wallpaperRequest_ = new XMLHttpRequest();
644 self.progressManager_.reset(self.wallpaperRequest_, selectedGridItem);
645
646 var onSuccess = function(xhr) {
647 var image = xhr.response;
648 chrome.wallpaperPrivate.setWallpaper(image, selectedItem.layout,
649 wallpaperURL,
650 function() {
651 self.progressManager_.hideProgressBar(selectedGridItem);
652
653 if (chrome.runtime.lastError != undefined &&
654 chrome.runtime.lastError.message !=
655 str('canceledWallpaper')) {
656 self.showError_(chrome.runtime.lastError.message);
657 } else {
658 self.onWallpaperChanged_(selectedItem, wallpaperURL);
659 }
660 });
661 self.wallpaperRequest_ = null;
662 };
663 var onFailure = function(status) {
664 self.progressManager_.hideProgressBar(selectedGridItem);
665 self.showError_(str('downloadFailed'));
666 self.wallpaperRequest_ = null;
667 };
668 WallpaperUtil.fetchURL(wallpaperURL, 'arraybuffer', onSuccess,
669 onFailure, self.wallpaperRequest_);
670 });
671 break;
672 case Constants.WallpaperSourceEnum.Daily:
673 case Constants.WallpaperSourceEnum.ThirdParty:
674 default:
675 console.error('Unsupported wallpaper source.');
676 } 837 }
677 }; 838 }
678 839 // Adds custom category as last category.
679 /* 840 this.categoriesList_.dataModel.push(str('customCategoryLabel'));
680 * Removes the oldest custom wallpaper. If the oldest one is set as current 841 };
681 * wallpaper, removes the second oldest one to free some space. This should 842
682 * only be called when exceeding wallpaper quota. 843 /**
683 */ 844 * Handles the custom wallpaper which user selected from file manager. Called
684 WallpaperManager.prototype.removeOldestWallpaper_ = function() { 845 * when users select a file.
685 // Custom wallpapers should already sorted when put to the data model. The 846 */
686 // last element is the add new button, need to exclude it as well. 847 WallpaperManager.prototype.onFileSelectorChanged_ = function() {
687 var oldestIndex = this.wallpaperGrid_.dataModel.length - 2; 848 var files = $('file-selector').files;
688 var item = this.wallpaperGrid_.dataModel.item(oldestIndex); 849 if (files.length != 1)
689 if (!item || item.source != Constants.WallpaperSourceEnum.Custom) 850 console.error('More than one files are selected or no file selected');
690 return; 851 if (!files[0].type.match('image/jpeg') && !files[0].type.match('image/png')) {
691 if (item.baseURL == this.currentWallpaper_) 852 this.showError_(str('invalidWallpaper'));
692 item = this.wallpaperGrid_.dataModel.item(--oldestIndex); 853 return;
693 if (item) { 854 }
694 this.removeCustomWallpaper(item.baseURL); 855 var layout = getSelectedLayout();
695 this.wallpaperGrid_.dataModel.splice(oldestIndex, 1); 856 var self = this;
696 } 857 var errorHandler = this.onFileSystemError_.bind(this);
697 }; 858 var setSelectedFile = function(file, layout, fileName) {
698 859 var saveThumbnail = function(thumbnail) {
699 /*
700 * Shows an error message to user and log the failed reason in console.
701 */
702 WallpaperManager.prototype.onFileSystemError_ = function(e) {
703 var msg = '';
704 switch (e.code) {
705 case FileError.QUOTA_EXCEEDED_ERR:
706 msg = 'QUOTA_EXCEEDED_ERR';
707 // Instead of simply remove oldest wallpaper, we should consider a
708 // better way to handle this situation. See crbug.com/180890.
709 this.removeOldestWallpaper_();
710 break;
711 case FileError.NOT_FOUND_ERR:
712 msg = 'NOT_FOUND_ERR';
713 break;
714 case FileError.SECURITY_ERR:
715 msg = 'SECURITY_ERR';
716 break;
717 case FileError.INVALID_MODIFICATION_ERR:
718 msg = 'INVALID_MODIFICATION_ERR';
719 break;
720 case FileError.INVALID_STATE_ERR:
721 msg = 'INVALID_STATE_ERR';
722 break;
723 default:
724 msg = 'Unknown Error';
725 break;
726 }
727 console.error('Error: ' + msg);
728 this.showError_(str('accessFileFailure'));
729 };
730
731 /**
732 * Handles changing of selectedItem in wallpaper manager.
733 */
734 WallpaperManager.prototype.onSelectedItemChanged_ = function() {
735 this.setWallpaperAttribution_(this.selectedItem_);
736
737 if (!this.selectedItem_ || this.selectedItem_.source == 'ADDNEW')
738 return;
739
740 if (this.selectedItem_.baseURL && !this.wallpaperGrid_.inProgramSelection) {
741 if (this.selectedItem_.source == Constants.WallpaperSourceEnum.Custom) {
742 var items = {};
743 var key = this.selectedItem_.baseURL;
744 var self = this;
745 Constants.WallpaperLocalStorage.get(key, function(items) {
746 self.selectedItem_.layout =
747 items[key] ? items[key] : 'CENTER_CROPPED';
748 self.setSelectedWallpaper_(self.selectedItem_);
749 });
750 } else {
751 this.setSelectedWallpaper_(this.selectedItem_);
752 }
753 }
754 };
755
756 /**
757 * Set attributions of wallpaper with given URL. If URL is not valid, clear
758 * the attributions.
759 * @param {{baseURL: string, dynamicURL: string, layout: string,
760 * author: string, authorWebsite: string, availableOffline: boolean}}
761 * selectedItem selected wallpaper item in grid.
762 * @private
763 */
764 WallpaperManager.prototype.setWallpaperAttribution_ = function(selectedItem) {
765 // Only online wallpapers have author and website attributes. All other type
766 // of wallpapers should not show attributions.
767 if (selectedItem &&
768 selectedItem.source == Constants.WallpaperSourceEnum.Online) {
769 $('author-name').textContent = selectedItem.author;
770 $('author-website').textContent = $('author-website').href =
771 selectedItem.authorWebsite;
772 chrome.wallpaperPrivate.getThumbnail(selectedItem.baseURL,
773 selectedItem.source,
774 function(data) {
775 var img = $('attribute-image');
776 if (data) {
777 var blob = new Blob([new Int8Array(data)], {'type' : 'image\/png'});
778 img.src = window.URL.createObjectURL(blob);
779 img.addEventListener('load', function(e) {
780 window.URL.revokeObjectURL(this.src);
781 });
782 } else {
783 img.src = '';
784 }
785 });
786 $('wallpaper-attribute').hidden = false;
787 $('attribute-image').hidden = false;
788 return;
789 }
790 $('wallpaper-attribute').hidden = true;
791 $('attribute-image').hidden = true;
792 $('author-name').textContent = '';
793 $('author-website').textContent = $('author-website').href = '';
794 $('attribute-image').src = '';
795 };
796
797 /**
798 * Resize thumbnails grid and categories list to fit the new window size.
799 */
800 WallpaperManager.prototype.onResize_ = function() {
801 this.wallpaperGrid_.redraw();
802 this.categoriesList_.redraw();
803 };
804
805 /**
806 * Close the last opened overlay or app window on pressing the Escape key.
807 * @param {Event} event A keydown event.
808 */
809 WallpaperManager.prototype.onKeyDown_ = function(event) {
810 if (event.keyCode == 27) {
811 // The last opened overlay coincides with the first match of querySelector
812 // because the Error Container is declared in the DOM before the Wallpaper
813 // Selection Container.
814 // TODO(bshe): Make the overlay selection not dependent on the DOM.
815 var closeButtonSelector = '.overlay-container:not([hidden]) .close';
816 var closeButton = this.document_.querySelector(closeButtonSelector);
817 if (closeButton) {
818 closeButton.click();
819 event.preventDefault();
820 } else {
821 this.onClose_();
822 }
823 }
824 };
825
826 /**
827 * Constructs the categories list.
828 */
829 WallpaperManager.prototype.initCategoriesList_ = function() {
830 this.categoriesList_ = $('categories-list');
831 wallpapers.WallpaperCategoriesList.decorate(this.categoriesList_);
832
833 this.categoriesList_.selectionModel.addEventListener(
834 'change', this.onCategoriesChange_.bind(this));
835
836 if (this.enableOnlineWallpaper_ && this.manifest_) {
837 // Adds all category as first category.
838 this.categoriesList_.dataModel.push(str('allCategoryLabel'));
839 for (var key in this.manifest_.categories) {
840 this.categoriesList_.dataModel.push(this.manifest_.categories[key]);
841 }
842 }
843 // Adds custom category as last category.
844 this.categoriesList_.dataModel.push(str('customCategoryLabel'));
845 };
846
847 /**
848 * Handles the custom wallpaper which user selected from file manager. Called
849 * when users select a file.
850 */
851 WallpaperManager.prototype.onFileSelectorChanged_ = function() {
852 var files = $('file-selector').files;
853 if (files.length != 1)
854 console.error('More than one files are selected or no file selected');
855 if (!files[0].type.match('image/jpeg') &&
856 !files[0].type.match('image/png')) {
857 this.showError_(str('invalidWallpaper'));
858 return;
859 }
860 var layout = getSelectedLayout();
861 var self = this;
862 var errorHandler = this.onFileSystemError_.bind(this);
863 var setSelectedFile = function(file, layout, fileName) {
864 var saveThumbnail = function(thumbnail) {
865 var success = function(dirEntry) {
866 dirEntry.getFile(fileName, {create: true}, function(fileEntry) {
867 fileEntry.createWriter(function(fileWriter) {
868 fileWriter.onwriteend = function(e) {
869 $('set-wallpaper-layout').disabled = false;
870 var wallpaperInfo = {
871 baseURL: fileName,
872 layout: layout,
873 source: Constants.WallpaperSourceEnum.Custom,
874 availableOffline: true
875 };
876 self.wallpaperGrid_.dataModel.splice(0, 0, wallpaperInfo);
877 self.wallpaperGrid_.selectedItem = wallpaperInfo;
878 self.onWallpaperChanged_(wallpaperInfo, fileName);
879 WallpaperUtil.saveToLocalStorage(self.currentWallpaper_,
880 layout);
881 };
882
883 fileWriter.onerror = errorHandler;
884
885 var blob = new Blob([new Int8Array(thumbnail)],
886 {'type' : 'image\/jpeg'});
887 fileWriter.write(blob);
888 }, errorHandler);
889 }, errorHandler);
890 };
891 self.wallpaperDirs_.getDirectory(
892 Constants.WallpaperDirNameEnum.THUMBNAIL, success, errorHandler);
893 };
894 var onCustomWallpaperSuccess = function(thumbnailData, wallpaperData) {
895 WallpaperUtil.storeWallpaperToSyncFS(fileName, wallpaperData);
896 WallpaperUtil.storeWallpaperToSyncFS(
897 fileName + Constants.CustomWallpaperThumbnailSuffix,
898 thumbnailData);
899 saveThumbnail(thumbnailData);
900 };
901 var success = function(dirEntry) { 860 var success = function(dirEntry) {
902 dirEntry.getFile(fileName, {create: true}, function(fileEntry) { 861 dirEntry.getFile(fileName, {create: true}, function(fileEntry) {
903 fileEntry.createWriter(function(fileWriter) { 862 fileEntry.createWriter(function(fileWriter) {
904 fileWriter.addEventListener('writeend', function(e) { 863 fileWriter.onwriteend = function(e) {
905 var reader = new FileReader(); 864 $('set-wallpaper-layout').disabled = false;
906 reader.readAsArrayBuffer(file); 865 var wallpaperInfo = {
907 reader.addEventListener('error', errorHandler); 866 baseURL: fileName,
908 reader.addEventListener('load', function(e) { 867 layout: layout,
909 self.setCustomWallpaper(e.target.result, layout, true, fileName, 868 source: Constants.WallpaperSourceEnum.Custom,
910 function(thumbnail) { 869 availableOffline: true
911 onCustomWallpaperSuccess(thumbnail, e.target.result); 870 };
912 }, 871 self.wallpaperGrid_.dataModel.splice(0, 0, wallpaperInfo);
913 function() { 872 self.wallpaperGrid_.selectedItem = wallpaperInfo;
914 self.removeCustomWallpaper(fileName); 873 self.onWallpaperChanged_(wallpaperInfo, fileName);
915 errorHandler(); 874 WallpaperUtil.saveToLocalStorage(self.currentWallpaper_, layout);
916 }); 875 };
917 }); 876
918 }); 877 fileWriter.onerror = errorHandler;
919 fileWriter.addEventListener('error', errorHandler); 878
920 fileWriter.write(file); 879 var blob =
880 new Blob([new Int8Array(thumbnail)], {'type': 'image\/jpeg'});
881 fileWriter.write(blob);
921 }, errorHandler); 882 }, errorHandler);
922 }, errorHandler); 883 }, errorHandler);
923 }; 884 };
924 self.wallpaperDirs_.getDirectory(Constants.WallpaperDirNameEnum.ORIGINAL, 885 self.wallpaperDirs_.getDirectory(
925 success, 886 Constants.WallpaperDirNameEnum.THUMBNAIL, success, errorHandler);
926 errorHandler);
927 }; 887 };
928 setSelectedFile(files[0], layout, new Date().getTime().toString()); 888 var onCustomWallpaperSuccess = function(thumbnailData, wallpaperData) {
889 WallpaperUtil.storeWallpaperToSyncFS(fileName, wallpaperData);
890 WallpaperUtil.storeWallpaperToSyncFS(
891 fileName + Constants.CustomWallpaperThumbnailSuffix, thumbnailData);
892 saveThumbnail(thumbnailData);
893 };
894 var success = function(dirEntry) {
895 dirEntry.getFile(fileName, {create: true}, function(fileEntry) {
896 fileEntry.createWriter(function(fileWriter) {
897 fileWriter.addEventListener('writeend', function(e) {
898 var reader = new FileReader();
899 reader.readAsArrayBuffer(file);
900 reader.addEventListener('error', errorHandler);
901 reader.addEventListener('load', function(e) {
902 self.setCustomWallpaper(
903 e.target.result, layout, true, fileName,
904 function(thumbnail) {
905 onCustomWallpaperSuccess(thumbnail, e.target.result);
906 },
907 function() {
908 self.removeCustomWallpaper(fileName);
909 errorHandler();
910 });
911 });
912 });
913 fileWriter.addEventListener('error', errorHandler);
914 fileWriter.write(file);
915 }, errorHandler);
916 }, errorHandler);
917 };
918 self.wallpaperDirs_.getDirectory(
919 Constants.WallpaperDirNameEnum.ORIGINAL, success, errorHandler);
929 }; 920 };
930 921 setSelectedFile(files[0], layout, new Date().getTime().toString());
931 /** 922 };
932 * Removes wallpaper and thumbnail with fileName from FileSystem. 923
933 * @param {string} fileName The file name of wallpaper and thumbnail to be 924 /**
934 * removed. 925 * Removes wallpaper and thumbnail with fileName from FileSystem.
935 */ 926 * @param {string} fileName The file name of wallpaper and thumbnail to be
936 WallpaperManager.prototype.removeCustomWallpaper = function(fileName) { 927 * removed.
928 */
929 WallpaperManager.prototype.removeCustomWallpaper = function(fileName) {
930 var errorHandler = this.onFileSystemError_.bind(this);
931 var self = this;
932 var removeFile = function(fileName) {
933 var success = function(dirEntry) {
934 dirEntry.getFile(fileName, {create: false}, function(fileEntry) {
935 fileEntry.remove(function() {
936 WallpaperUtil.deleteWallpaperFromSyncFS(fileName);
937 }, errorHandler);
938 }, errorHandler);
939 };
940
941 // Removes copy of original.
942 self.wallpaperDirs_.getDirectory(
943 Constants.WallpaperDirNameEnum.ORIGINAL, success, errorHandler);
944
945 // Removes generated thumbnail.
946 self.wallpaperDirs_.getDirectory(
947 Constants.WallpaperDirNameEnum.THUMBNAIL, success, errorHandler);
948 };
949 removeFile(fileName);
950 };
951
952 /**
953 * Sets current wallpaper and generate thumbnail if generateThumbnail is true.
954 * @param {ArrayBuffer} wallpaper The binary representation of wallpaper.
955 * @param {string} layout The user selected wallpaper layout.
956 * @param {boolean} generateThumbnail True if need to generate thumbnail.
957 * @param {string} fileName The unique file name of wallpaper.
958 * @param {function(thumbnail):void} success Success callback. If
959 * generateThumbnail is true, the callback parameter should have the
960 * generated thumbnail.
961 * @param {function(e):void} failure Failure callback. Called when there is an
962 * error from FileSystem.
963 */
964 WallpaperManager.prototype.setCustomWallpaper = function(
965 wallpaper, layout, generateThumbnail, fileName, success, failure) {
966 var self = this;
967 var onFinished = function(opt_thumbnail) {
968 if (chrome.runtime.lastError != undefined &&
969 chrome.runtime.lastError.message != str('canceledWallpaper')) {
970 self.showError_(chrome.runtime.lastError.message);
971 $('set-wallpaper-layout').disabled = true;
972 failure();
973 } else {
974 success(opt_thumbnail);
975 }
976 };
977
978 chrome.wallpaperPrivate.setCustomWallpaper(
979 wallpaper, layout, generateThumbnail, fileName, onFinished);
980 };
981
982 /**
983 * Handles the layout setting change of custom wallpaper.
984 */
985 WallpaperManager.prototype.onWallpaperLayoutChanged_ = function() {
986 var layout = getSelectedLayout();
987 var self = this;
988 chrome.wallpaperPrivate.setCustomWallpaperLayout(layout, function() {
989 if (chrome.runtime.lastError != undefined &&
990 chrome.runtime.lastError.message != str('canceledWallpaper')) {
991 self.showError_(chrome.runtime.lastError.message);
992 self.removeCustomWallpaper(fileName);
993 $('set-wallpaper-layout').disabled = true;
994 } else {
995 WallpaperUtil.saveToLocalStorage(self.currentWallpaper_, layout);
996 self.onWallpaperChanged_(
997 self.wallpaperGrid_.activeItem, self.currentWallpaper_);
998 }
999 });
1000 };
1001
1002 /**
1003 * Handles user clicking on a different category.
1004 */
1005 WallpaperManager.prototype.onCategoriesChange_ = function() {
1006 var categoriesList = this.categoriesList_;
1007 var selectedIndex = categoriesList.selectionModel.selectedIndex;
1008 if (selectedIndex == -1)
1009 return;
1010 var selectedListItem = categoriesList.getListItemByIndex(selectedIndex);
1011 var bar = $('bar');
1012 bar.style.left = selectedListItem.offsetLeft + 'px';
1013 bar.style.width = selectedListItem.offsetWidth + 'px';
1014
1015 var wallpapersDataModel = new cr.ui.ArrayDataModel([]);
1016 var selectedItem = null;
1017 if (selectedListItem.custom) {
1018 this.document_.body.setAttribute('custom', '');
937 var errorHandler = this.onFileSystemError_.bind(this); 1019 var errorHandler = this.onFileSystemError_.bind(this);
1020 var toArray = function(list) {
1021 return Array.prototype.slice.call(list || [], 0);
1022 };
1023
938 var self = this; 1024 var self = this;
939 var removeFile = function(fileName) { 1025 var processResults = function(entries) {
940 var success = function(dirEntry) { 1026 for (var i = 0; i < entries.length; i++) {
941 dirEntry.getFile(fileName, {create: false}, function(fileEntry) { 1027 var entry = entries[i];
942 fileEntry.remove(function() { 1028 var wallpaperInfo = {
943 WallpaperUtil.deleteWallpaperFromSyncFS(fileName); 1029 // Set wallpaperId to null to avoid duplicate thumbnail images,
944 }, errorHandler); 1030 // see crbug.com/506135 for details.
1031 wallpaperId: null,
1032 baseURL: entry.name,
1033 // The layout will be replaced by the actual value saved in
1034 // local storage when requested later. Layout is not important
1035 // for constructing thumbnails grid, we use CENTER_CROPPED here
1036 // to speed up the process of constructing. So we do not need to
1037 // wait for fetching correct layout.
1038 layout: 'CENTER_CROPPED',
1039 source: Constants.WallpaperSourceEnum.Custom,
1040 availableOffline: true
1041 };
1042 wallpapersDataModel.push(wallpaperInfo);
1043 }
1044 if (loadTimeData.getBoolean('isOEMDefaultWallpaper')) {
1045 var oemDefaultWallpaperElement = {
1046 wallpaperId: null,
1047 baseURL: 'OemDefaultWallpaper',
1048 layout: 'CENTER_CROPPED',
1049 source: Constants.WallpaperSourceEnum.OEM,
1050 availableOffline: true
1051 };
1052 wallpapersDataModel.push(oemDefaultWallpaperElement);
1053 }
1054 for (var i = 0; i < wallpapersDataModel.length; i++) {
1055 // For custom wallpapers, the file name of |currentWallpaper_|
1056 // includes the first directory level (corresponding to user id hash).
1057 if (getBaseName(self.currentWallpaper_) ==
1058 wallpapersDataModel.item(i).baseURL) {
1059 selectedItem = wallpapersDataModel.item(i);
1060 }
1061 }
1062 var lastElement = {
1063 baseURL: '',
1064 layout: '',
1065 source: Constants.WallpaperSourceEnum.AddNew,
1066 availableOffline: true
1067 };
1068 wallpapersDataModel.push(lastElement);
1069 self.wallpaperGrid_.dataModel = wallpapersDataModel;
1070 if (selectedItem) {
1071 self.wallpaperGrid_.selectedItem = selectedItem;
1072 self.wallpaperGrid_.activeItem = selectedItem;
1073 }
1074 };
1075
1076 var success = function(dirEntry) {
1077 var dirReader = dirEntry.createReader();
1078 var entries = [];
1079 // All of a directory's entries are not guaranteed to return in a single
1080 // call.
1081 var readEntries = function() {
1082 dirReader.readEntries(function(results) {
1083 if (!results.length) {
1084 processResults(entries.sort());
1085 } else {
1086 entries = entries.concat(toArray(results));
1087 readEntries();
1088 }
945 }, errorHandler); 1089 }, errorHandler);
946 }; 1090 };
947 1091 readEntries(); // Start reading dirs.
948 // Removes copy of original.
949 self.wallpaperDirs_.getDirectory(Constants.WallpaperDirNameEnum.ORIGINAL,
950 success,
951 errorHandler);
952
953 // Removes generated thumbnail.
954 self.wallpaperDirs_.getDirectory(Constants.WallpaperDirNameEnum.THUMBNAIL,
955 success,
956 errorHandler);
957 }; 1092 };
958 removeFile(fileName); 1093 this.wallpaperDirs_.getDirectory(
959 }; 1094 Constants.WallpaperDirNameEnum.ORIGINAL, success, errorHandler);
960 1095 } else {
961 /** 1096 this.document_.body.removeAttribute('custom');
962 * Sets current wallpaper and generate thumbnail if generateThumbnail is true. 1097 // Need this check for test purpose.
963 * @param {ArrayBuffer} wallpaper The binary representation of wallpaper. 1098 var numOnlineWallpaper = (this.enableOnlineWallpaper_ && this.manifest_) ?
964 * @param {string} layout The user selected wallpaper layout. 1099 this.manifest_.wallpaper_list.length :
965 * @param {boolean} generateThumbnail True if need to generate thumbnail. 1100 0;
966 * @param {string} fileName The unique file name of wallpaper. 1101 for (var i = 0; i < numOnlineWallpaper; i++) {
967 * @param {function(thumbnail):void} success Success callback. If 1102 if (selectedIndex == AllCategoryIndex ||
968 * generateThumbnail is true, the callback parameter should have the 1103 this.manifest_.wallpaper_list[i].categories.indexOf(
969 * generated thumbnail. 1104 selectedIndex - OnlineCategoriesOffset) != -1) {
970 * @param {function(e):void} failure Failure callback. Called when there is an 1105 var wallpaperInfo = {
971 * error from FileSystem. 1106 wallpaperId: i,
972 */ 1107 baseURL: this.manifest_.wallpaper_list[i].base_url,
973 WallpaperManager.prototype.setCustomWallpaper = function(wallpaper, 1108 layout: this.manifest_.wallpaper_list[i].default_layout,
974 layout, 1109 source: Constants.WallpaperSourceEnum.Online,
975 generateThumbnail, 1110 availableOffline: false,
976 fileName, 1111 author: this.manifest_.wallpaper_list[i].author,
977 success, 1112 authorWebsite: this.manifest_.wallpaper_list[i].author_website,
978 failure) { 1113 dynamicURL: this.manifest_.wallpaper_list[i].dynamic_url
979 var self = this; 1114 };
980 var onFinished = function(opt_thumbnail) { 1115 var fileName =
981 if (chrome.runtime.lastError != undefined && 1116 getBaseName(wallpaperInfo.baseURL) + Constants.HighResolutionSuffix;
982 chrome.runtime.lastError.message != str('canceledWallpaper')) { 1117 if (this.downloadedListMap_ &&
983 self.showError_(chrome.runtime.lastError.message); 1118 this.downloadedListMap_.hasOwnProperty(encodeURI(fileName))) {
984 $('set-wallpaper-layout').disabled = true; 1119 wallpaperInfo.availableOffline = true;
985 failure();
986 } else {
987 success(opt_thumbnail);
988 }
989 };
990
991 chrome.wallpaperPrivate.setCustomWallpaper(wallpaper, layout,
992 generateThumbnail,
993 fileName, onFinished);
994 };
995
996 /**
997 * Handles the layout setting change of custom wallpaper.
998 */
999 WallpaperManager.prototype.onWallpaperLayoutChanged_ = function() {
1000 var layout = getSelectedLayout();
1001 var self = this;
1002 chrome.wallpaperPrivate.setCustomWallpaperLayout(layout, function() {
1003 if (chrome.runtime.lastError != undefined &&
1004 chrome.runtime.lastError.message != str('canceledWallpaper')) {
1005 self.showError_(chrome.runtime.lastError.message);
1006 self.removeCustomWallpaper(fileName);
1007 $('set-wallpaper-layout').disabled = true;
1008 } else {
1009 WallpaperUtil.saveToLocalStorage(self.currentWallpaper_, layout);
1010 self.onWallpaperChanged_(self.wallpaperGrid_.activeItem,
1011 self.currentWallpaper_);
1012 }
1013 });
1014 };
1015
1016 /**
1017 * Handles user clicking on a different category.
1018 */
1019 WallpaperManager.prototype.onCategoriesChange_ = function() {
1020 var categoriesList = this.categoriesList_;
1021 var selectedIndex = categoriesList.selectionModel.selectedIndex;
1022 if (selectedIndex == -1)
1023 return;
1024 var selectedListItem = categoriesList.getListItemByIndex(selectedIndex);
1025 var bar = $('bar');
1026 bar.style.left = selectedListItem.offsetLeft + 'px';
1027 bar.style.width = selectedListItem.offsetWidth + 'px';
1028
1029 var wallpapersDataModel = new cr.ui.ArrayDataModel([]);
1030 var selectedItem = null;
1031 if (selectedListItem.custom) {
1032 this.document_.body.setAttribute('custom', '');
1033 var errorHandler = this.onFileSystemError_.bind(this);
1034 var toArray = function(list) {
1035 return Array.prototype.slice.call(list || [], 0);
1036 };
1037
1038 var self = this;
1039 var processResults = function(entries) {
1040 for (var i = 0; i < entries.length; i++) {
1041 var entry = entries[i];
1042 var wallpaperInfo = {
1043 // Set wallpaperId to null to avoid duplicate thumbnail images,
1044 // see crbug.com/506135 for details.
1045 wallpaperId: null,
1046 baseURL: entry.name,
1047 // The layout will be replaced by the actual value saved in
1048 // local storage when requested later. Layout is not important
1049 // for constructing thumbnails grid, we use CENTER_CROPPED here
1050 // to speed up the process of constructing. So we do not need to
1051 // wait for fetching correct layout.
1052 layout: 'CENTER_CROPPED',
1053 source: Constants.WallpaperSourceEnum.Custom,
1054 availableOffline: true
1055 };
1056 wallpapersDataModel.push(wallpaperInfo);
1057 } 1120 }
1058 if (loadTimeData.getBoolean('isOEMDefaultWallpaper')) { 1121 wallpapersDataModel.push(wallpaperInfo);
1059 var oemDefaultWallpaperElement = { 1122 var url = this.manifest_.wallpaper_list[i].base_url +
1060 wallpaperId: null, 1123 Constants.HighResolutionSuffix;
1061 baseURL: 'OemDefaultWallpaper', 1124 if (url == this.currentWallpaper_) {
1062 layout: 'CENTER_CROPPED', 1125 selectedItem = wallpaperInfo;
1063 source: Constants.WallpaperSourceEnum.OEM,
1064 availableOffline: true
1065 };
1066 wallpapersDataModel.push(oemDefaultWallpaperElement);
1067 }
1068 for (var i = 0; i < wallpapersDataModel.length; i++) {
1069 // For custom wallpapers, the file name of |currentWallpaper_|
1070 // includes the first directory level (corresponding to user id hash).
1071 if (getBaseName(self.currentWallpaper_) ==
1072 wallpapersDataModel.item(i).baseURL) {
1073 selectedItem = wallpapersDataModel.item(i);
1074 }
1075 }
1076 var lastElement = {
1077 baseURL: '',
1078 layout: '',
1079 source: Constants.WallpaperSourceEnum.AddNew,
1080 availableOffline: true
1081 };
1082 wallpapersDataModel.push(lastElement);
1083 self.wallpaperGrid_.dataModel = wallpapersDataModel;
1084 if (selectedItem) {
1085 self.wallpaperGrid_.selectedItem = selectedItem;
1086 self.wallpaperGrid_.activeItem = selectedItem;
1087 }
1088 };
1089
1090 var success = function(dirEntry) {
1091 var dirReader = dirEntry.createReader();
1092 var entries = [];
1093 // All of a directory's entries are not guaranteed to return in a single
1094 // call.
1095 var readEntries = function() {
1096 dirReader.readEntries(function(results) {
1097 if (!results.length) {
1098 processResults(entries.sort());
1099 } else {
1100 entries = entries.concat(toArray(results));
1101 readEntries();
1102 }
1103 }, errorHandler);
1104 };
1105 readEntries(); // Start reading dirs.
1106 };
1107 this.wallpaperDirs_.getDirectory(Constants.WallpaperDirNameEnum.ORIGINAL,
1108 success, errorHandler);
1109 } else {
1110 this.document_.body.removeAttribute('custom');
1111 // Need this check for test purpose.
1112 var numOnlineWallpaper = (this.enableOnlineWallpaper_ && this.manifest_) ?
1113 this.manifest_.wallpaper_list.length : 0;
1114 for (var i = 0; i < numOnlineWallpaper; i++) {
1115 if (selectedIndex == AllCategoryIndex ||
1116 this.manifest_.wallpaper_list[i].categories.indexOf(
1117 selectedIndex - OnlineCategoriesOffset) != -1) {
1118 var wallpaperInfo = {
1119 wallpaperId: i,
1120 baseURL: this.manifest_.wallpaper_list[i].base_url,
1121 layout: this.manifest_.wallpaper_list[i].default_layout,
1122 source: Constants.WallpaperSourceEnum.Online,
1123 availableOffline: false,
1124 author: this.manifest_.wallpaper_list[i].author,
1125 authorWebsite: this.manifest_.wallpaper_list[i].author_website,
1126 dynamicURL: this.manifest_.wallpaper_list[i].dynamic_url
1127 };
1128 var fileName = getBaseName(wallpaperInfo.baseURL) +
1129 Constants.HighResolutionSuffix;
1130 if (this.downloadedListMap_ &&
1131 this.downloadedListMap_.hasOwnProperty(encodeURI(fileName))) {
1132 wallpaperInfo.availableOffline = true;
1133 }
1134 wallpapersDataModel.push(wallpaperInfo);
1135 var url = this.manifest_.wallpaper_list[i].base_url +
1136 Constants.HighResolutionSuffix;
1137 if (url == this.currentWallpaper_) {
1138 selectedItem = wallpaperInfo;
1139 }
1140 } 1126 }
1141 } 1127 }
1142 this.wallpaperGrid_.dataModel = wallpapersDataModel;
1143 if (selectedItem) {
1144 this.wallpaperGrid_.selectedItem = selectedItem;
1145 this.wallpaperGrid_.activeItem = selectedItem;
1146 }
1147 } 1128 }
1148 }; 1129 this.wallpaperGrid_.dataModel = wallpapersDataModel;
1130 if (selectedItem) {
1131 this.wallpaperGrid_.selectedItem = selectedItem;
1132 this.wallpaperGrid_.activeItem = selectedItem;
1133 }
1134 }
1135 };
1149 1136
1150 })(); 1137 })();
OLDNEW
« no previous file with comments | « chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_images_grid.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698