| OLD | NEW |
| 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 'use strict'; | 5 'use strict'; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * FileManager constructor. | 8 * FileManager constructor. |
| 9 * | 9 * |
| 10 * FileManager objects encapsulate the functionality of the file selector | 10 * FileManager objects encapsulate the functionality of the file selector |
| (...skipping 1921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1932 * @private | 1932 * @private |
| 1933 */ | 1933 */ |
| 1934 FileManager.prototype.focusCurrentList_ = function() { | 1934 FileManager.prototype.focusCurrentList_ = function() { |
| 1935 if (this.listType_ == FileManager.ListType.DETAIL) | 1935 if (this.listType_ == FileManager.ListType.DETAIL) |
| 1936 this.table_.focus(); | 1936 this.table_.focus(); |
| 1937 else // this.listType_ == FileManager.ListType.THUMBNAIL) | 1937 else // this.listType_ == FileManager.ListType.THUMBNAIL) |
| 1938 this.grid_.focus(); | 1938 this.grid_.focus(); |
| 1939 }; | 1939 }; |
| 1940 | 1940 |
| 1941 /** | 1941 /** |
| 1942 * Return full path of the current directory or null. | |
| 1943 * @return {?string} The full path of the current directory. | |
| 1944 */ | |
| 1945 FileManager.prototype.getCurrentDirectory = function() { | |
| 1946 return this.directoryModel_ && this.directoryModel_.getCurrentDirPath(); | |
| 1947 }; | |
| 1948 | |
| 1949 /** | |
| 1950 * Return URL of the current directory or null. | |
| 1951 * @return {string} URL representing the current directory. | |
| 1952 */ | |
| 1953 FileManager.prototype.getCurrentDirectoryURL = function() { | |
| 1954 return this.directoryModel_ && | |
| 1955 this.directoryModel_.getCurrentDirectoryURL(); | |
| 1956 }; | |
| 1957 | |
| 1958 /** | |
| 1959 * Return DirectoryEntry of the current directory or null. | 1942 * Return DirectoryEntry of the current directory or null. |
| 1960 * @return {DirectoryEntry} DirectoryEntry of the current directory. Returns | 1943 * @return {DirectoryEntry} DirectoryEntry of the current directory. Returns |
| 1961 * null if the directory model is not ready or the current directory is | 1944 * null if the directory model is not ready or the current directory is |
| 1962 * not set. | 1945 * not set. |
| 1963 */ | 1946 */ |
| 1964 FileManager.prototype.getCurrentDirectoryEntry = function() { | 1947 FileManager.prototype.getCurrentDirectoryEntry = function() { |
| 1965 return this.directoryModel_ && this.directoryModel_.getCurrentDirEntry(); | 1948 return this.directoryModel_ && this.directoryModel_.getCurrentDirEntry(); |
| 1966 }; | 1949 }; |
| 1967 | 1950 |
| 1968 /** | 1951 /** |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2199 }; | 2182 }; |
| 2200 | 2183 |
| 2201 /** | 2184 /** |
| 2202 * Update the window title. | 2185 * Update the window title. |
| 2203 * @private | 2186 * @private |
| 2204 */ | 2187 */ |
| 2205 FileManager.prototype.updateTitle_ = function() { | 2188 FileManager.prototype.updateTitle_ = function() { |
| 2206 if (this.dialogType != DialogType.FULL_PAGE) | 2189 if (this.dialogType != DialogType.FULL_PAGE) |
| 2207 return; | 2190 return; |
| 2208 | 2191 |
| 2209 var path = this.getCurrentDirectory(); | 2192 // TODO(mtomasz): Use VolumeInfo.root instead. |
| 2193 var path = this.getCurrentDirectoryEntry().fullPath; |
| 2210 var rootPath = PathUtil.getRootPath(path); | 2194 var rootPath = PathUtil.getRootPath(path); |
| 2211 this.document_.title = PathUtil.getRootLabel(rootPath) + | 2195 this.document_.title = PathUtil.getRootLabel(rootPath) + |
| 2212 path.substring(rootPath.length); | 2196 path.substring(rootPath.length); |
| 2213 }; | 2197 }; |
| 2214 | 2198 |
| 2215 /** | 2199 /** |
| 2216 * Update the gear menu. | 2200 * Update the gear menu. |
| 2217 * @private | 2201 * @private |
| 2218 */ | 2202 */ |
| 2219 FileManager.prototype.updateGearMenu_ = function() { | 2203 FileManager.prototype.updateGearMenu_ = function() { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2264 | 2248 |
| 2265 /** | 2249 /** |
| 2266 * Update the UI when the current directory changes. | 2250 * Update the UI when the current directory changes. |
| 2267 * | 2251 * |
| 2268 * @param {Event} event The directory-changed event. | 2252 * @param {Event} event The directory-changed event. |
| 2269 * @private | 2253 * @private |
| 2270 */ | 2254 */ |
| 2271 FileManager.prototype.onDirectoryChanged_ = function(event) { | 2255 FileManager.prototype.onDirectoryChanged_ = function(event) { |
| 2272 this.selectionHandler_.onFileSelectionChanged(); | 2256 this.selectionHandler_.onFileSelectionChanged(); |
| 2273 this.ui_.searchBox.clear(); | 2257 this.ui_.searchBox.clear(); |
| 2274 util.updateAppState(this.getCurrentDirectory()); | 2258 // TODO(mtomasz): Use Entry.toURL() instead of fullPath. |
| 2259 util.updateAppState( |
| 2260 this.getCurrentDirectoryEntry() && |
| 2261 this.getCurrentDirectoryEntry().fullPath); |
| 2275 | 2262 |
| 2276 // If the current directory is moved from the device's volume, do not | 2263 // If the current directory is moved from the device's volume, do not |
| 2277 // automatically close the window on device removal. | 2264 // automatically close the window on device removal. |
| 2278 if (event.previousDirEntry && | 2265 if (event.previousDirEntry && |
| 2279 PathUtil.getRootPath(event.previousDirEntry.fullPath) != | 2266 PathUtil.getRootPath(event.previousDirEntry.fullPath) != |
| 2280 PathUtil.getRootPath(event.newDirEntry.fullPath)) | 2267 PathUtil.getRootPath(event.newDirEntry.fullPath)) |
| 2281 this.closeOnUnmount_ = false; | 2268 this.closeOnUnmount_ = false; |
| 2282 | 2269 |
| 2283 if (this.commandHandler) | 2270 if (this.commandHandler) |
| 2284 this.commandHandler.updateAvailability(); | 2271 this.commandHandler.updateAvailability(); |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2486 newName); | 2473 newName); |
| 2487 } else { | 2474 } else { |
| 2488 message = strf('ERROR_RENAMING', entry.name, | 2475 message = strf('ERROR_RENAMING', entry.name, |
| 2489 util.getFileErrorString(err.code)); | 2476 util.getFileErrorString(err.code)); |
| 2490 } | 2477 } |
| 2491 | 2478 |
| 2492 this.alert.show(message); | 2479 this.alert.show(message); |
| 2493 }.bind(this)); | 2480 }.bind(this)); |
| 2494 }; | 2481 }; |
| 2495 | 2482 |
| 2496 // TODO(haruki): this.getCurrentDirectoryURL() might not return the actual | 2483 // TODO(haruki): this.getCurrentDirectoryEntry() might not return the actual |
| 2497 // parent if the directory content is a search result. Fix it to do proper | 2484 // parent if the directory content is a search result. Fix it to do proper |
| 2498 // validation. | 2485 // validation. |
| 2499 this.validateFileName_(this.getCurrentDirectoryURL(), | 2486 this.validateFileName_(this.getCurrentDirectoryEntry(), |
| 2500 newName, | 2487 newName, |
| 2501 validationDone.bind(this)); | 2488 validationDone.bind(this)); |
| 2502 }; | 2489 }; |
| 2503 | 2490 |
| 2504 /** | 2491 /** |
| 2505 * @private | 2492 * @private |
| 2506 */ | 2493 */ |
| 2507 FileManager.prototype.cancelRename_ = function() { | 2494 FileManager.prototype.cancelRename_ = function() { |
| 2508 this.renameInput_.currentEntry = null; | 2495 this.renameInput_.currentEntry = null; |
| 2509 | 2496 |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2834 */ | 2821 */ |
| 2835 FileManager.prototype.onListKeyDown_ = function(event) { | 2822 FileManager.prototype.onListKeyDown_ = function(event) { |
| 2836 if (event.srcElement.tagName == 'INPUT') { | 2823 if (event.srcElement.tagName == 'INPUT') { |
| 2837 // Ignore keydown handler in the rename input box. | 2824 // Ignore keydown handler in the rename input box. |
| 2838 return; | 2825 return; |
| 2839 } | 2826 } |
| 2840 | 2827 |
| 2841 switch (util.getKeyModifiers(event) + event.keyCode) { | 2828 switch (util.getKeyModifiers(event) + event.keyCode) { |
| 2842 case '8': // Backspace => Up one directory. | 2829 case '8': // Backspace => Up one directory. |
| 2843 event.preventDefault(); | 2830 event.preventDefault(); |
| 2844 var path = this.getCurrentDirectory(); | 2831 // TODO(mtomasz): Use Entry.getParent() instead. |
| 2832 if (!this.getCurrentDirectoryEntry()) |
| 2833 break; |
| 2834 var path = this.getCurrentDirectoryEntry().fullPath; |
| 2845 if (path && !PathUtil.isRootPath(path)) { | 2835 if (path && !PathUtil.isRootPath(path)) { |
| 2846 var path = path.replace(/\/[^\/]+$/, ''); | 2836 var path = path.replace(/\/[^\/]+$/, ''); |
| 2847 this.directoryModel_.changeDirectory(path); | 2837 this.directoryModel_.changeDirectory(path); |
| 2848 } | 2838 } |
| 2849 break; | 2839 break; |
| 2850 | 2840 |
| 2851 case '13': // Enter => Change directory or perform default action. | 2841 case '13': // Enter => Change directory or perform default action. |
| 2852 // TODO(dgozman): move directory action to dispatchSelectionAction. | 2842 // TODO(dgozman): move directory action to dispatchSelectionAction. |
| 2853 var selection = this.getSelection(); | 2843 var selection = this.getSelection(); |
| 2854 if (selection.totalCount == 1 && | 2844 if (selection.totalCount == 1 && |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3125 */ | 3115 */ |
| 3126 FileManager.prototype.onOk_ = function(event) { | 3116 FileManager.prototype.onOk_ = function(event) { |
| 3127 if (this.dialogType == DialogType.SELECT_SAVEAS_FILE) { | 3117 if (this.dialogType == DialogType.SELECT_SAVEAS_FILE) { |
| 3128 // Save-as doesn't require a valid selection from the list, since | 3118 // Save-as doesn't require a valid selection from the list, since |
| 3129 // we're going to take the filename from the text input. | 3119 // we're going to take the filename from the text input. |
| 3130 var filename = this.filenameInput_.value; | 3120 var filename = this.filenameInput_.value; |
| 3131 if (!filename) | 3121 if (!filename) |
| 3132 throw new Error('Missing filename!'); | 3122 throw new Error('Missing filename!'); |
| 3133 | 3123 |
| 3134 var directory = this.getCurrentDirectoryEntry(); | 3124 var directory = this.getCurrentDirectoryEntry(); |
| 3135 var currentDirUrl = directory.toURL(); | 3125 this.validateFileName_(directory, filename, function(isValid) { |
| 3136 if (currentDirUrl.charAt(currentDirUrl.length - 1) != '/') | |
| 3137 currentDirUrl += '/'; | |
| 3138 this.validateFileName_(currentDirUrl, filename, function(isValid) { | |
| 3139 if (!isValid) | 3126 if (!isValid) |
| 3140 return; | 3127 return; |
| 3141 | 3128 |
| 3142 if (util.isFakeEntry(directory)) { | 3129 if (util.isFakeEntry(directory)) { |
| 3143 // Can't save a file into a fake directory. | 3130 // Can't save a file into a fake directory. |
| 3144 return; | 3131 return; |
| 3145 } | 3132 } |
| 3146 | 3133 |
| 3147 var selectFileAndClose = function() { | 3134 var selectFileAndClose = function() { |
| 3135 // TODO(mtomasz): Clean this up by avoiding constructing a URL |
| 3136 // via string concatenation. |
| 3137 var currentDirUrl = directory.toURL(); |
| 3138 if (currentDirUrl.charAt(currentDirUrl.length - 1) != '/') |
| 3139 currentDirUrl += '/'; |
| 3148 this.selectFilesAndClose_({ | 3140 this.selectFilesAndClose_({ |
| 3149 urls: [currentDirUrl + encodeURIComponent(filename)], | 3141 urls: [currentDirUrl + encodeURIComponent(filename)], |
| 3150 multiple: false, | 3142 multiple: false, |
| 3151 filterIndex: this.getSelectedFilterIndex_(filename) | 3143 filterIndex: this.getSelectedFilterIndex_(filename) |
| 3152 }); | 3144 }); |
| 3153 }.bind(this); | 3145 }.bind(this); |
| 3154 | 3146 |
| 3155 directory.getFile( | 3147 directory.getFile( |
| 3156 filename, {create: false}, | 3148 filename, {create: false}, |
| 3157 function(entry) { | 3149 function(entry) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3179 }.bind(this)); | 3171 }.bind(this)); |
| 3180 }.bind(this)); | 3172 }.bind(this)); |
| 3181 return; | 3173 return; |
| 3182 } | 3174 } |
| 3183 | 3175 |
| 3184 var files = []; | 3176 var files = []; |
| 3185 var selectedIndexes = this.currentList_.selectionModel.selectedIndexes; | 3177 var selectedIndexes = this.currentList_.selectionModel.selectedIndexes; |
| 3186 | 3178 |
| 3187 if (DialogType.isFolderDialog(this.dialogType) && | 3179 if (DialogType.isFolderDialog(this.dialogType) && |
| 3188 selectedIndexes.length == 0) { | 3180 selectedIndexes.length == 0) { |
| 3189 var url = this.getCurrentDirectoryURL(); | 3181 var url = this.getCurrentDirectoryEntry().toURL(); |
| 3190 var singleSelection = { | 3182 var singleSelection = { |
| 3191 urls: [url], | 3183 urls: [url], |
| 3192 multiple: false, | 3184 multiple: false, |
| 3193 filterIndex: this.getSelectedFilterIndex_() | 3185 filterIndex: this.getSelectedFilterIndex_() |
| 3194 }; | 3186 }; |
| 3195 this.selectFilesAndClose_(singleSelection); | 3187 this.selectFilesAndClose_(singleSelection); |
| 3196 return; | 3188 return; |
| 3197 } | 3189 } |
| 3198 | 3190 |
| 3199 // All other dialog types require at least one selected list item. | 3191 // All other dialog types require at least one selected list item. |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3248 /** | 3240 /** |
| 3249 * Verifies the user entered name for file or folder to be created or | 3241 * Verifies the user entered name for file or folder to be created or |
| 3250 * renamed to. Name restrictions must correspond to File API restrictions | 3242 * renamed to. Name restrictions must correspond to File API restrictions |
| 3251 * (see DOMFilePath::isValidPath). Curernt WebKit implementation is | 3243 * (see DOMFilePath::isValidPath). Curernt WebKit implementation is |
| 3252 * out of date (spec is | 3244 * out of date (spec is |
| 3253 * http://dev.w3.org/2009/dap/file-system/file-dir-sys.html, 8.3) and going to | 3245 * http://dev.w3.org/2009/dap/file-system/file-dir-sys.html, 8.3) and going to |
| 3254 * be fixed. Shows message box if the name is invalid. | 3246 * be fixed. Shows message box if the name is invalid. |
| 3255 * | 3247 * |
| 3256 * It also verifies if the name length is in the limit of the filesystem. | 3248 * It also verifies if the name length is in the limit of the filesystem. |
| 3257 * | 3249 * |
| 3258 * @param {string} parentUrl The URL of the parent directory entry. | 3250 * @param {DirectoryEntry} parentEntry The URL of the parent directory entry. |
| 3259 * @param {string} name New file or folder name. | 3251 * @param {string} name New file or folder name. |
| 3260 * @param {function} onDone Function to invoke when user closes the | 3252 * @param {function} onDone Function to invoke when user closes the |
| 3261 * warning box or immediatelly if file name is correct. If the name was | 3253 * warning box or immediatelly if file name is correct. If the name was |
| 3262 * valid it is passed true, and false otherwise. | 3254 * valid it is passed true, and false otherwise. |
| 3263 * @private | 3255 * @private |
| 3264 */ | 3256 */ |
| 3265 FileManager.prototype.validateFileName_ = function(parentUrl, name, onDone) { | 3257 FileManager.prototype.validateFileName_ = function( |
| 3258 parentEntry, name, onDone) { |
| 3266 var msg; | 3259 var msg; |
| 3267 var testResult = /[\/\\\<\>\:\?\*\"\|]/.exec(name); | 3260 var testResult = /[\/\\\<\>\:\?\*\"\|]/.exec(name); |
| 3268 if (testResult) { | 3261 if (testResult) { |
| 3269 msg = strf('ERROR_INVALID_CHARACTER', testResult[0]); | 3262 msg = strf('ERROR_INVALID_CHARACTER', testResult[0]); |
| 3270 } else if (/^\s*$/i.test(name)) { | 3263 } else if (/^\s*$/i.test(name)) { |
| 3271 msg = str('ERROR_WHITESPACE_NAME'); | 3264 msg = str('ERROR_WHITESPACE_NAME'); |
| 3272 } else if (/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$/i.test(name)) { | 3265 } else if (/^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$/i.test(name)) { |
| 3273 msg = str('ERROR_RESERVED_NAME'); | 3266 msg = str('ERROR_RESERVED_NAME'); |
| 3274 } else if (this.fileFilter_.isFilterHiddenOn() && name[0] == '.') { | 3267 } else if (this.fileFilter_.isFilterHiddenOn() && name[0] == '.') { |
| 3275 msg = str('ERROR_HIDDEN_NAME'); | 3268 msg = str('ERROR_HIDDEN_NAME'); |
| 3276 } | 3269 } |
| 3277 | 3270 |
| 3278 if (msg) { | 3271 if (msg) { |
| 3279 this.alert.show(msg, function() { | 3272 this.alert.show(msg, function() { |
| 3280 onDone(false); | 3273 onDone(false); |
| 3281 }); | 3274 }); |
| 3282 return; | 3275 return; |
| 3283 } | 3276 } |
| 3284 | 3277 |
| 3285 var self = this; | 3278 var self = this; |
| 3286 chrome.fileBrowserPrivate.validatePathNameLength( | 3279 chrome.fileBrowserPrivate.validatePathNameLength( |
| 3287 parentUrl, name, function(valid) { | 3280 parentEntry.toURL(), name, function(valid) { |
| 3288 if (!valid) { | 3281 if (!valid) { |
| 3289 self.alert.show(str('ERROR_LONG_NAME'), | 3282 self.alert.show(str('ERROR_LONG_NAME'), |
| 3290 function() { onDone(false); }); | 3283 function() { onDone(false); }); |
| 3291 } else { | 3284 } else { |
| 3292 onDone(true); | 3285 onDone(true); |
| 3293 } | 3286 } |
| 3294 }); | 3287 }); |
| 3295 }; | 3288 }; |
| 3296 | 3289 |
| 3297 /** | 3290 /** |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3644 callback(this.preferences_); | 3637 callback(this.preferences_); |
| 3645 return; | 3638 return; |
| 3646 } | 3639 } |
| 3647 | 3640 |
| 3648 chrome.fileBrowserPrivate.getPreferences(function(prefs) { | 3641 chrome.fileBrowserPrivate.getPreferences(function(prefs) { |
| 3649 this.preferences_ = prefs; | 3642 this.preferences_ = prefs; |
| 3650 callback(prefs); | 3643 callback(prefs); |
| 3651 }.bind(this)); | 3644 }.bind(this)); |
| 3652 }; | 3645 }; |
| 3653 })(); | 3646 })(); |
| OLD | NEW |