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

Side by Side Diff: chrome/browser/resources/file_manager/js/file_manager.js

Issue 9839009: [filebrowser] Show progress indication, while files from GData are being downloaded. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 // Setting the src of an img to an empty string can crash the browser, so we 5 // Setting the src of an img to an empty string can crash the browser, so we
6 // use an empty 1x1 gif instead. 6 // use an empty 1x1 gif instead.
7 7
8 /** 8 /**
9 * FileManager constructor. 9 * FileManager constructor.
10 * 10 *
(...skipping 3967 matching lines...) Expand 10 before | Expand all | Expand 10 after
3978 } 3978 }
3979 } 3979 }
3980 callback(fileUrls); 3980 callback(fileUrls);
3981 }); 3981 });
3982 } else { 3982 } else {
3983 callback(fileUrls); 3983 callback(fileUrls);
3984 } 3984 }
3985 }, 3985 },
3986 3986
3987 /** 3987 /**
3988 * Selects a file. 3988 * Closes this modal dialog with some files selected.
3989 * 3989 * TODO(jamescook): Make unload handler work automatically, crbug.com/104811
3990 * @param {string} fileUrl The filename as a URL. 3990 * @param {Object} selection Contains urls, filterIndex and multiple fields.
3991 * @param {number} filterIndex The integer file filter index.
3992 */ 3991 */
3993 FileManager.prototype.selectFile_ = function(fileUrl, filterIndex) { 3992 FileManager.prototype.callSelectFilesApiAndClose_ = function(selection) {
3994 this.resolveSelectResults_( 3993 if (selection.multiple) {
3995 [fileUrl], 3994 chrome.fileBrowserPrivate.selectFiles(selection.urls);
3996 function(resolvedUrls) { 3995 } else {
3997 // Call doSelectFiles_ on a timeout, as it's unsafe to 3996 chrome.fileBrowserPrivate.selectFile(
3998 // close a window from a callback. 3997 selection.urls[0], selection.filterIndex);
3999 setTimeout( 3998 }
4000 this.doSelectFile_.bind(this, resolvedUrls[0], filterIndex), 0);
4001 }.bind(this));
4002 };
4003
4004 /**
4005 * Selects a file. Closes the window.
4006 * TODO(jamescook): Make unload handler work automatically, crbug.com/104811
4007 *
4008 * @param {string} fileUrl The filename as a URL.
4009 * @param {number} filterIndex The integer file filter index.
4010 */
4011 FileManager.prototype.doSelectFile_ = function(fileUrl, filterIndex) {
4012 chrome.fileBrowserPrivate.selectFile(fileUrl, filterIndex);
4013 this.onUnload_();
4014 window.close();
4015 };
4016
4017
4018 /**
4019 * Selects a file. Starts getting gdata files if needed.
4020 *
4021 * @param {Array.<string>} fileUrls Array of filename URLs.
4022 */
4023 FileManager.prototype.selectFiles_ = function(fileUrls) {
4024 this.resolveSelectResults_(
4025 fileUrls,
4026 function(resolvedUrls) {
4027 // Call doSelectFiles_ on a timeout, as it's unsafe to
4028 // close a window from a callback.
4029 setTimeout(this.doSelectFiles_.bind(this, resolvedUrls), 0);
4030 }.bind(this));
4031 };
4032
4033 /**
4034 * Selects multiple files. Closes the window.
4035 * TODO(jamescook): Make unload handler work automatically, crbug.com/104811
4036 *
4037 * @param {Array.<string>} fileUrls Array of filename URLs.
4038 */
4039 FileManager.prototype.doSelectFiles_ = function(fileUrls) {
4040 chrome.fileBrowserPrivate.selectFiles(fileUrls);
4041 this.onUnload_(); 3999 this.onUnload_();
4042 window.close(); 4000 window.close();
4043 }; 4001 };
4044 4002
4045 /** 4003 /**
4004 * Tries to close this modal dialog with some files selected.
4005 * Performs preprocessing if needed (e.g. for GData).
4006 * @param {Object} selection Contains urls, filterIndex and multiple fields.
4007 */
4008 FileManager.prototype.selectFilesAndClose_ = function(selection) {
4009 if (!this.isOnGData()) {
4010 setTimeout(this.callSelectFilesApiAndClose_.bind(this, selection), 0);
4011 return;
4012 }
4013
4014 var shade = this.document_.createElement('div');
4015 shade.className = 'shade';
4016 var footer = this.document_.querySelector('.dialog-footer');
4017 var progress = footer.querySelector('.progress-track');
4018 progress.style.width = '0%';
4019 var cancelled = false;
4020
4021 var onFileTransfersUpdated = function(statusList) {
4022 var total = 0;
4023 var done = 0;
4024 var known = 0; // The number of files we have information about.
4025 for (var index = 0; index < statusList.length; index++) {
4026 var status = statusList[index];
4027 var escaped = encodeURI(status.fileUrl);
4028 if (selection.urls.indexOf(escaped) == -1) continue;
4029 if (status.total == -1) continue;
4030 known++;
4031 total += status.total;
4032 done += status.processed;
4033 }
4034
4035 var percent = total == 0 ? 0 : done / total;
4036 // For files we don't have information about, assume the progress is zero.
4037 percent = percent * known / selection.urls.length * 100;
4038 progress.style.width = percent + '%';
4039 }.bind(this);
4040
4041 var setup = function() {
4042 this.document_.querySelector('.dialog-container').appendChild(shade);
4043 setTimeout(function() { shade.setAttribute('fadein', 'fadein') }, 100);
4044 footer.setAttribute('progress', 'progress');
4045 this.cancelButton_.removeEventListener('click', this.onCancelBound_);
4046 this.cancelButton_.addEventListener('click', onCancel);
4047 chrome.fileBrowserPrivate.onFileTransfersUpdated.addListener(
4048 onFileTransfersUpdated);
4049 }.bind(this);
4050
4051 var cleanup = function() {
4052 shade.parentNode.removeChild(shade);
4053 footer.removeAttribute('progress');
4054 this.cancelButton_.removeEventListener('click', onCancel);
4055 this.cancelButton_.addEventListener('click', this.onCancelBound_);
4056 chrome.fileBrowserPrivate.onFileTransfersUpdated.removeListener(
4057 onFileTransfersUpdated);
4058 }.bind(this);
4059
4060 var onCancel = function() {
4061 cancelled = true;
4062 // Accroding to API cancel may fail, but there is no proper UI to reflect
Vladislav Kaznacheev 2012/03/23 13:11:14 Accroding -> According
4063 // this. So, we just silently assume that everything is cancelled.
4064 chrome.fileBrowserPrivate.cancelFileTransfers(
4065 selection.urls, function(response) {});
4066 cleanup();
4067 }.bind(this);
4068
4069 var onResolved = function(resolvedUrls) {
4070 if (cancelled) return;
4071 cleanup();
4072 selection.urls = resolvedUrls;
4073 // Call next method on a timeout, as it's unsafe to
4074 // close a window from a callback.
4075 setTimeout(this.callSelectFilesApiAndClose_.bind(this, selection), 0);
4076 }.bind(this);
4077
4078 setup();
4079 this.resolveSelectResults_(selection.urls, onResolved);
4080 };
4081
4082 /**
4046 * Handle a click of the ok button. 4083 * Handle a click of the ok button.
4047 * 4084 *
4048 * The ok button has different UI labels depending on the type of dialog, but 4085 * The ok button has different UI labels depending on the type of dialog, but
4049 * in code it's always referred to as 'ok'. 4086 * in code it's always referred to as 'ok'.
4050 * 4087 *
4051 * @param {Event} event The click event. 4088 * @param {Event} event The click event.
4052 */ 4089 */
4053 FileManager.prototype.onOk_ = function(event) { 4090 FileManager.prototype.onOk_ = function(event) {
4054 var currentDirUrl = this.getCurrentDirectoryURL(); 4091 var currentDirUrl = this.getCurrentDirectoryURL();
4055 4092
4056 if (currentDirUrl.charAt(currentDirUrl.length - 1) != '/') 4093 if (currentDirUrl.charAt(currentDirUrl.length - 1) != '/')
4057 currentDirUrl += '/'; 4094 currentDirUrl += '/';
4058 4095
4059 var self = this; 4096 var self = this;
4060 if (this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) { 4097 if (this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) {
4061 // Save-as doesn't require a valid selection from the list, since 4098 // Save-as doesn't require a valid selection from the list, since
4062 // we're going to take the filename from the text input. 4099 // we're going to take the filename from the text input.
4063 var filename = this.filenameInput_.value; 4100 var filename = this.filenameInput_.value;
4064 if (!filename) 4101 if (!filename)
4065 throw new Error('Missing filename!'); 4102 throw new Error('Missing filename!');
4066 if (!this.validateFileName_(filename)) 4103 if (!this.validateFileName_(filename))
4067 return; 4104 return;
4068 4105
4106 var singleSelection = {
4107 urls: [currentDirUrl + encodeURIComponent(filename)],
4108 multiple: false,
4109 filterIndex: self.getSelectedFilterIndex_(filename)
4110 };
4111
4069 function resolveCallback(victim) { 4112 function resolveCallback(victim) {
4070 if (victim instanceof FileError) { 4113 if (victim instanceof FileError) {
4071 // File does not exist. Closes the window and does not return. 4114 // File does not exist.
4072 self.selectFile_( 4115 self.selectFilesAndClose_(singleSelection);
4073 currentDirUrl + encodeURIComponent(filename), 4116 return;
4074 self.getSelectedFilterIndex_(filename));
4075 } 4117 }
4076 4118
4077 if (victim.isDirectory) { 4119 if (victim.isDirectory) {
4078 // Do not allow to overwrite directory. 4120 // Do not allow to overwrite directory.
4079 self.alert.show(strf('DIRECTORY_ALREADY_EXISTS', filename)); 4121 self.alert.show(strf('DIRECTORY_ALREADY_EXISTS', filename));
4080 } else { 4122 } else {
4081 self.confirm.show(strf('CONFIRM_OVERWRITE_FILE', filename), 4123 self.confirm.show(strf('CONFIRM_OVERWRITE_FILE', filename),
4082 function() { 4124 function() {
4083 // User selected Ok from the confirm dialog. 4125 // User selected Ok from the confirm dialog.
4084 self.selectFile_( 4126 self.selectFilesAndClose_(singleSelection);
4085 currentDirUrl + encodeURIComponent(filename),
4086 self.getSelectedFilterIndex_(filename));
4087 }); 4127 });
4088 } 4128 }
4089 return;
4090 } 4129 }
4091 4130
4092 this.resolvePath(this.getCurrentDirectory() + '/' + filename, 4131 this.resolvePath(this.getCurrentDirectory() + '/' + filename,
4093 resolveCallback, resolveCallback); 4132 resolveCallback, resolveCallback);
4094 return; 4133 return;
4095 } 4134 }
4096 4135
4097 var files = []; 4136 var files = [];
4098 var selectedIndexes = this.currentList_.selectionModel.selectedIndexes; 4137 var selectedIndexes = this.currentList_.selectionModel.selectedIndexes;
4099 4138
4100 // All other dialog types require at least one selected list item. 4139 // All other dialog types require at least one selected list item.
4101 // The logic to control whether or not the ok button is enabled should 4140 // The logic to control whether or not the ok button is enabled should
4102 // prevent us from ever getting here, but we sanity check to be sure. 4141 // prevent us from ever getting here, but we sanity check to be sure.
4103 if (!selectedIndexes.length) 4142 if (!selectedIndexes.length)
4104 throw new Error('Nothing selected!'); 4143 throw new Error('Nothing selected!');
4105 4144
4106 var dm = this.directoryModel_.fileList; 4145 var dm = this.directoryModel_.fileList;
4107 for (var i = 0; i < selectedIndexes.length; i++) { 4146 for (var i = 0; i < selectedIndexes.length; i++) {
4108 var entry = dm.item(selectedIndexes[i]); 4147 var entry = dm.item(selectedIndexes[i]);
4109 if (!entry) { 4148 if (!entry) {
4110 console.log('Error locating selected file at index: ' + i); 4149 console.log('Error locating selected file at index: ' + i);
4111 continue; 4150 continue;
4112 } 4151 }
4113 4152
4114 files.push(currentDirUrl + encodeURIComponent(entry.name)); 4153 files.push(currentDirUrl + encodeURIComponent(entry.name));
4115 } 4154 }
4116 4155
4117 // Multi-file selection has no other restrictions. 4156 // Multi-file selection has no other restrictions.
4118 if (this.dialogType_ == FileManager.DialogType.SELECT_OPEN_MULTI_FILE) { 4157 if (this.dialogType_ == FileManager.DialogType.SELECT_OPEN_MULTI_FILE) {
4119 // Closes the window and does not return. 4158 var multipleSelection = {
4120 this.selectFiles_(files); 4159 urls: files,
4160 multiple: true
4161 };
4162 this.selectFilesAndClose_(multipleSelection);
4121 return; 4163 return;
4122 } 4164 }
4123 4165
4124 // Everything else must have exactly one. 4166 // Everything else must have exactly one.
4125 if (files.length > 1) 4167 if (files.length > 1)
4126 throw new Error('Too many files selected!'); 4168 throw new Error('Too many files selected!');
4127 4169
4128 var selectedEntry = dm.item(selectedIndexes[0]); 4170 var selectedEntry = dm.item(selectedIndexes[0]);
4129 4171
4130 if (this.dialogType_ == FileManager.DialogType.SELECT_FOLDER) { 4172 if (this.dialogType_ == FileManager.DialogType.SELECT_FOLDER) {
4131 if (!selectedEntry.isDirectory) 4173 if (!selectedEntry.isDirectory)
4132 throw new Error('Selected entry is not a folder!'); 4174 throw new Error('Selected entry is not a folder!');
4133 } else if (this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FILE) { 4175 } else if (this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FILE) {
4134 if (!selectedEntry.isFile) 4176 if (!selectedEntry.isFile)
4135 throw new Error('Selected entry is not a file!'); 4177 throw new Error('Selected entry is not a file!');
4136 } 4178 }
4137 4179
4138 // Closes the window and does not return. 4180 var singleSelection = {
4139 this.selectFile_(files[0], this.getSelectedFilterIndex_(files[0])); 4181 urls: [files[0]],
4182 multiple: false,
4183 filterIndex: this.getSelectedFilterIndex_(files[0])
4184 };
4185 this.selectFilesAndClose_(singleSelection);
4140 }; 4186 };
4141 4187
4142 /** 4188 /**
4143 * Verifies the user entered name for file or folder to be created or 4189 * Verifies the user entered name for file or folder to be created or
4144 * renamed to. Name restrictions must correspond to File API restrictions 4190 * renamed to. Name restrictions must correspond to File API restrictions
4145 * (see DOMFilePath::isValidPath). Curernt WebKit implementation is 4191 * (see DOMFilePath::isValidPath). Curernt WebKit implementation is
4146 * out of date (spec is 4192 * out of date (spec is
4147 * http://dev.w3.org/2009/dap/file-system/file-dir-sys.html, 8.3) and going to 4193 * http://dev.w3.org/2009/dap/file-system/file-dir-sys.html, 8.3) and going to
4148 * be fixed. Shows message box if the name is invalid. 4194 * be fixed. Shows message box if the name is invalid.
4149 * 4195 *
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
4222 }); 4268 });
4223 }, onError); 4269 }, onError);
4224 4270
4225 function onError(err) { 4271 function onError(err) {
4226 console.log('Error while checking free space: ' + err); 4272 console.log('Error while checking free space: ' + err);
4227 setTimeout(doCheck, 1000 * 60); 4273 setTimeout(doCheck, 1000 * 60);
4228 } 4274 }
4229 } 4275 }
4230 } 4276 }
4231 })(); 4277 })();
OLDNEW
« no previous file with comments | « chrome/browser/resources/file_manager/css/file_manager.css ('k') | chrome/browser/resources/file_manager/js/mock_chrome.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698