Chromium Code Reviews| 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 // If directory files changes too often, don't rescan directory more than once | 5 // If directory files changes too often, don't rescan directory more than once |
| 6 // per specified interval | 6 // per specified interval |
| 7 var SIMULTANEOUS_RESCAN_INTERVAL = 1000; | 7 var SIMULTANEOUS_RESCAN_INTERVAL = 1000; |
| 8 // Used for operations that require almost instant rescan. | 8 // Used for operations that require almost instant rescan. |
| 9 var SHORT_RESCAN_INTERVAL = 100; | 9 var SHORT_RESCAN_INTERVAL = 100; |
| 10 | 10 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 50 | 50 |
| 51 // The map 'name' -> callback. Callbacks are function(entry) -> boolean. | 51 // The map 'name' -> callback. Callbacks are function(entry) -> boolean. |
| 52 this.filters_ = {}; | 52 this.filters_ = {}; |
| 53 this.setFilterHidden(true); | 53 this.setFilterHidden(true); |
| 54 | 54 |
| 55 /** | 55 /** |
| 56 * @private | 56 * @private |
| 57 * @type {Object.<string, boolean>} | 57 * @type {Object.<string, boolean>} |
| 58 */ | 58 */ |
| 59 this.volumeReadOnlyStatus_ = {}; | 59 this.volumeReadOnlyStatus_ = {}; |
| 60 | |
| 61 /** | |
| 62 * File path of the last directory that is not under virtual search directory. | |
| 63 * This is the path to go to when the search box content clears on GData. | |
| 64 * @private | |
| 65 * @type {string} | |
| 66 */ | |
| 67 this.lastNonGDataSearchDirPath_ = null; | |
| 60 } | 68 } |
| 61 | 69 |
| 62 /** | 70 /** |
| 63 * The name of the directory containing externally | 71 * The name of the directory containing externally |
| 64 * mounted removable storage volumes. | 72 * mounted removable storage volumes. |
| 65 */ | 73 */ |
| 66 DirectoryModel.REMOVABLE_DIRECTORY = 'removable'; | 74 DirectoryModel.REMOVABLE_DIRECTORY = 'removable'; |
| 67 | 75 |
| 68 /** | 76 /** |
| 69 * The name of the directory containing externally | 77 * The name of the directory containing externally |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 172 * @return {boolean} If current directory is system. | 180 * @return {boolean} If current directory is system. |
| 173 */ | 181 */ |
| 174 DirectoryModel.prototype.isSystemDirectory = function() { | 182 DirectoryModel.prototype.isSystemDirectory = function() { |
| 175 var path = this.currentDirEntry_.fullPath; | 183 var path = this.currentDirEntry_.fullPath; |
| 176 return path == '/' || | 184 return path == '/' || |
| 177 path == '/' + DirectoryModel.REMOVABLE_DIRECTORY || | 185 path == '/' + DirectoryModel.REMOVABLE_DIRECTORY || |
| 178 path == '/' + DirectoryModel.ARCHIVE_DIRECTORY; | 186 path == '/' + DirectoryModel.ARCHIVE_DIRECTORY; |
| 179 }; | 187 }; |
| 180 | 188 |
| 181 /** | 189 /** |
| 190 * Tests if the entry is a gdata search result entry. | |
| 191 * @param {entry} entry Entry to test. | |
| 192 * @return {boolean} Result. | |
| 193 */ | |
| 194 DirectoryModel.prototype.isGDataSearchResult = function(entry) { | |
| 195 return (util.getFileAndDisplayNameForGDataSearchResult(entry.fullPath) != | |
| 196 null); | |
| 197 }; | |
| 198 | |
| 199 /** | |
| 182 * @return {boolean} If the files with names starting with "." are not shown. | 200 * @return {boolean} If the files with names starting with "." are not shown. |
| 183 */ | 201 */ |
| 184 DirectoryModel.prototype.isFilterHiddenOn = function() { | 202 DirectoryModel.prototype.isFilterHiddenOn = function() { |
| 185 return !!this.filters_['hidden']; | 203 return !!this.filters_['hidden']; |
| 186 }; | 204 }; |
| 187 | 205 |
| 188 /** | 206 /** |
| 189 * @param {boolean} value Whether files with leading "." are hidden. | 207 * @param {boolean} value Whether files with leading "." are hidden. |
| 190 */ | 208 */ |
| 191 DirectoryModel.prototype.setFilterHidden = function(value) { | 209 DirectoryModel.prototype.setFilterHidden = function(value) { |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 490 callback) { | 508 callback) { |
| 491 var field = this.fileList_.sortStatus.field; | 509 var field = this.fileList_.sortStatus.field; |
| 492 if (field) { | 510 if (field) { |
| 493 this.prepareSortEntries_(entries, field, callback); | 511 this.prepareSortEntries_(entries, field, callback); |
| 494 } else { | 512 } else { |
| 495 callback(); | 513 callback(); |
| 496 } | 514 } |
| 497 }; | 515 }; |
| 498 | 516 |
| 499 /** | 517 /** |
| 518 * Gets name that should be dispalyed in the UI for the entry. | |
| 519 * @param {string} path Full path of the entry whose display name we are | |
| 520 * getting. | |
| 521 * @param {string} defaultName Default name to use if no name is calculated. | |
| 522 * @return {string} Name to be used for display. | |
| 523 */ | |
| 524 DirectoryModel.prototype.getDisplayName = function(path, defaultName) { | |
| 525 var searchResultName = util.getFileAndDisplayNameForGDataSearchResult(path); | |
| 526 return searchResultName ? searchResultName.displayName : defaultName; | |
| 527 }; | |
| 528 | |
| 529 /** | |
| 500 * Delete the list of files and directories from filesystem and | 530 * Delete the list of files and directories from filesystem and |
| 501 * update the file list. | 531 * update the file list. |
| 502 * @param {Array.<Entry>} entries Entries to delete. | 532 * @param {Array.<Entry>} entries Entries to delete. |
| 503 * @param {function()=} opt_callback Called when finished. | 533 * @param {function()=} opt_callback Called when finished. |
| 504 */ | 534 */ |
| 505 DirectoryModel.prototype.deleteEntries = function(entries, opt_callback) { | 535 DirectoryModel.prototype.deleteEntries = function(entries, opt_callback) { |
| 506 var downcount = entries.length + 1; | 536 var downcount = entries.length + 1; |
| 507 | 537 |
| 508 var onComplete = opt_callback ? function() { | 538 var onComplete = opt_callback ? function() { |
| 509 if (--downcount == 0) | 539 if (--downcount == 0) |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 */ | 620 */ |
| 591 DirectoryModel.prototype.renameEntry = function(entry, newName, errorCallback, | 621 DirectoryModel.prototype.renameEntry = function(entry, newName, errorCallback, |
| 592 opt_successCallback) { | 622 opt_successCallback) { |
| 593 var self = this; | 623 var self = this; |
| 594 function onSuccess(newEntry) { | 624 function onSuccess(newEntry) { |
| 595 self.prefetchCacheForSorting_([newEntry], function() { | 625 self.prefetchCacheForSorting_([newEntry], function() { |
| 596 var fileList = self.fileList_; | 626 var fileList = self.fileList_; |
| 597 var index = fileList.indexOf(entry); | 627 var index = fileList.indexOf(entry); |
| 598 if (index >= 0) | 628 if (index >= 0) |
| 599 fileList.splice(index, 1, newEntry); | 629 fileList.splice(index, 1, newEntry); |
| 600 self.selectEntry(newName); | 630 self.selectEntry(newEntry.name); |
| 601 // If the entry doesn't exist in the list it mean that it updated from | 631 // If the entry doesn't exist in the list it mean that it updated from |
| 602 // outside (probably by directory rescan). | 632 // outside (probably by directory rescan). |
| 603 if (opt_successCallback) | 633 if (opt_successCallback) |
| 604 opt_successCallback(); | 634 opt_successCallback(); |
| 605 }); | 635 }); |
| 606 } | 636 } |
| 607 entry.moveTo(this.currentDirEntry_, newName, onSuccess, errorCallback); | 637 |
| 638 // If we are renaming gdata search result, we'll have to format newName to | |
| 639 // use in file system operation like: <resource_id>.<file_name>. | |
| 640 var searchResultName = | |
| 641 util.getFileAndDisplayNameForGDataSearchResult(entry.fullPath); | |
| 642 var newNameToUse = | |
| 643 searchResultName ? searchResultName.resourceId + '.' + newName : newName; | |
| 644 | |
| 645 entry.moveTo(this.currentDirEntry_, newNameToUse, onSuccess, errorCallback); | |
| 608 }; | 646 }; |
| 609 | 647 |
| 610 /** | 648 /** |
| 611 * Checks if current directory contains a file or directory with this name. | 649 * Checks if current directory contains a file or directory with this name. |
| 650 * @param {string} entry Entry to which newNAme will be given. | |
| 612 * @param {string} newName Name to check. | 651 * @param {string} newName Name to check. |
| 613 * @param {function(boolean, boolean?)} callback Called when the result's | 652 * @param {function(boolean, boolean?)} callback Called when the result's |
| 614 * available. First parameter is true if the entry exists and second | 653 * available. First parameter is true if the entry exists and second |
| 615 * is true if it's a file. | 654 * is true if it's a file. |
| 616 */ | 655 */ |
| 617 DirectoryModel.prototype.doesExist = function(newName, callback) { | 656 DirectoryModel.prototype.doesExist = function(entry, newName, callback) { |
| 618 util.resolvePath(this.currentDirEntry_, newName, | 657 // If we are looking for gdata search result, we'll have to format newName to |
| 658 // use in file system operation like: <resource_id>.<file_name>. | |
| 659 var searchResultName = | |
| 660 util.getFileAndDisplayNameForGDataSearchResult(entry.fullPath); | |
| 661 var newNameToUse = | |
| 662 searchResultName ? searchResultName.resourceId + '.' + newName : newName; | |
|
SeRya
2012/05/07 14:06:00
Code duplication. Create a method.
tbarzic
2012/05/10 03:20:47
Done.
| |
| 663 | |
| 664 util.resolvePath(this.currentDirEntry_, newNameToUse, | |
| 619 function(entry) { | 665 function(entry) { |
| 620 callback(true, entry.isFile); | 666 callback(true, entry.isFile); |
| 621 }, | 667 }, |
| 622 callback.bind(window, false)); | 668 callback.bind(window, false)); |
| 623 }; | 669 }; |
| 624 | 670 |
| 625 /** | 671 /** |
| 626 * Creates directory and updates the file list. | 672 * Creates directory and updates the file list. |
| 627 * | 673 * |
| 628 * @param {string} name Directory name. | 674 * @param {string} name Directory name. |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 659 * Changes directory. Causes 'directory-change' event. | 705 * Changes directory. Causes 'directory-change' event. |
| 660 * | 706 * |
| 661 * @param {string} path New current directory path. | 707 * @param {string} path New current directory path. |
| 662 */ | 708 */ |
| 663 DirectoryModel.prototype.changeDirectory = function(path) { | 709 DirectoryModel.prototype.changeDirectory = function(path) { |
| 664 this.resolveDirectory(path, function(directoryEntry) { | 710 this.resolveDirectory(path, function(directoryEntry) { |
| 665 this.changeDirectoryEntry_(false, directoryEntry); | 711 this.changeDirectoryEntry_(false, directoryEntry); |
| 666 }.bind(this), function(error) { | 712 }.bind(this), function(error) { |
| 667 console.error('Error changing directory to ' + path + ': ', error); | 713 console.error('Error changing directory to ' + path + ': ', error); |
| 668 }); | 714 }); |
| 669 } | 715 }; |
| 670 | 716 |
| 671 /** | 717 /** |
| 672 * Resolves absolute directory path. Handles GData stub. | 718 * Resolves absolute directory path. Handles GData stub. |
| 673 * @param {string} path Path to the directory. | 719 * @param {string} path Path to the directory. |
| 674 * @param {function(DirectoryEntry} successCallback Success callback. | 720 * @param {function(DirectoryEntry} successCallback Success callback. |
| 675 * @param {function(FileError} errorCallback Error callback. | 721 * @param {function(FileError} errorCallback Error callback. |
| 676 */ | 722 */ |
| 677 DirectoryModel.prototype.resolveDirectory = function(path, successCallback, | 723 DirectoryModel.prototype.resolveDirectory = function(path, successCallback, |
| 678 errorCallback) { | 724 errorCallback) { |
| 679 if (this.unmountedGDataEntry_ && | 725 if (this.unmountedGDataEntry_ && |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1106 // Re-place the entry into the roots data model to force re-rendering. | 1152 // Re-place the entry into the roots data model to force re-rendering. |
| 1107 this.rootsList_.splice(index, 1, entry); | 1153 this.rootsList_.splice(index, 1, entry); |
| 1108 | 1154 |
| 1109 if (rootPath == this.rootPath) { | 1155 if (rootPath == this.rootPath) { |
| 1110 // TODO(kaznacheev): Consider changing to the most recently used root. | 1156 // TODO(kaznacheev): Consider changing to the most recently used root. |
| 1111 this.changeDirectory(this.getDefaultDirectory()); | 1157 this.changeDirectory(this.getDefaultDirectory()); |
| 1112 } | 1158 } |
| 1113 }; | 1159 }; |
| 1114 | 1160 |
| 1115 /** | 1161 /** |
| 1162 * Performs search and displays results. The search type is dependent on the | |
| 1163 * current directory. If we are currently on gdata, server side content search | |
| 1164 * over gdata mount point. If the current directory is not on the gdata, file | |
| 1165 * name search over current directory wil be performed. | |
| 1166 * | |
| 1167 * @param {string} query Query that will be searched for. | |
| 1168 */ | |
| 1169 DirectoryModel.prototype.search = function(query) { | |
| 1170 if (this.getCurrentRootPath() == '/' + DirectoryModel.GDATA_DIRECTORY) { | |
| 1171 if (query) { | |
| 1172 var currentDirPath = this.currentDirEntry_.fullPath; | |
| 1173 if (currentDirPath.search(util.GDATA_SEARCH_ROOT_PATH) != 0) | |
| 1174 this.lastNonGDataSearchDirPath_ = currentDirPath; | |
| 1175 this.changeDirectory(util.createGDataSearchPath(query)); | |
| 1176 } else { | |
| 1177 var newDirPath = this.lastNonGDataSearchDirPath_ || | |
| 1178 '/' + DirectoryModel.GDATA_DIRECTORY; | |
| 1179 this.lastNonGDataSearchDirPath_; | |
|
SeRya
2012/05/07 14:06:00
As I mentioned before I don't think that changing
tbarzic
2012/05/10 03:20:47
Yep, this is much cleaner, thanks for suggestion ;
| |
| 1180 this.changeDirectory(newDirPath); | |
| 1181 } | |
| 1182 } else { | |
| 1183 if (query) { | |
| 1184 this.addFilter( | |
| 1185 'searchbox', | |
| 1186 function(e) { | |
| 1187 return e.name.substring(0, query.length) == query; | |
| 1188 }); | |
| 1189 } else { | |
| 1190 this.directoryModel_.removeFilter('searchbox'); | |
| 1191 } | |
| 1192 } | |
| 1193 }; | |
| 1194 | |
| 1195 /** | |
| 1116 * @param {string} path Any path. | 1196 * @param {string} path Any path. |
| 1117 * @return {string} The root path. | 1197 * @return {string} The root path. |
| 1118 */ | 1198 */ |
| 1119 DirectoryModel.getRootPath = function(path) { | 1199 DirectoryModel.getRootPath = function(path) { |
| 1120 var type = DirectoryModel.getRootType(path); | 1200 var type = DirectoryModel.getRootType(path); |
| 1121 | 1201 |
| 1122 if (type == DirectoryModel.RootType.DOWNLOADS) | 1202 if (type == DirectoryModel.RootType.DOWNLOADS) |
| 1123 return '/' + DirectoryModel.DOWNLOADS_DIRECTORY; | 1203 return '/' + DirectoryModel.DOWNLOADS_DIRECTORY; |
| 1124 if (type == DirectoryModel.RootType.GDATA) | 1204 if (type == DirectoryModel.RootType.GDATA) |
| 1125 return '/' + DirectoryModel.GDATA_DIRECTORY; | 1205 return '/' + DirectoryModel.GDATA_DIRECTORY; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1266 /** | 1346 /** |
| 1267 * @private | 1347 * @private |
| 1268 */ | 1348 */ |
| 1269 DirectoryModel.Scanner.prototype.recordMetrics_ = function() { | 1349 DirectoryModel.Scanner.prototype.recordMetrics_ = function() { |
| 1270 metrics.recordInterval('DirectoryScan'); | 1350 metrics.recordInterval('DirectoryScan'); |
| 1271 if (this.dir_.fullPath == | 1351 if (this.dir_.fullPath == |
| 1272 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) { | 1352 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) { |
| 1273 metrics.recordMediumCount('DownloadsCount', this.list_.length); | 1353 metrics.recordMediumCount('DownloadsCount', this.list_.length); |
| 1274 } | 1354 } |
| 1275 }; | 1355 }; |
| OLD | NEW |