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 21 matching lines...) Expand all Loading... | |
32 this.scanFailures_ = 0; | 32 this.scanFailures_ = 0; |
33 | 33 |
34 // DirectoryEntry representing the current directory of the dialog. | 34 // DirectoryEntry representing the current directory of the dialog. |
35 this.currentDirEntry_ = root; | 35 this.currentDirEntry_ = root; |
36 | 36 |
37 this.fileList_.prepareSort = this.prepareSort_.bind(this); | 37 this.fileList_.prepareSort = this.prepareSort_.bind(this); |
38 this.autoSelectIndex_ = 0; | 38 this.autoSelectIndex_ = 0; |
39 | 39 |
40 this.rootsList_ = new cr.ui.ArrayDataModel([]); | 40 this.rootsList_ = new cr.ui.ArrayDataModel([]); |
41 this.rootsListSelection_ = new cr.ui.ListSingleSelectionModel(); | 41 this.rootsListSelection_ = new cr.ui.ListSingleSelectionModel(); |
42 this.rootsListSelection_.addEventListener( | 42 this.currentRootDirEntry_ = root; |
43 'change', this.onRootsSelectionChanged_.bind(this)); | 43 /** |
44 * A map root.fullPath -> currentDirectory.fullPath. | |
45 * @private | |
46 * @type {Object.<string, string>} | |
47 */ | |
48 this.currentDirByRoot_ = {}; | |
44 | 49 |
45 // The map 'name' -> callback. Callbacks are function(entry) -> boolean. | 50 // The map 'name' -> callback. Callbacks are function(entry) -> boolean. |
46 this.filters_ = {}; | 51 this.filters_ = {}; |
47 this.filterHidden = true; | 52 this.filterHidden = true; |
48 | 53 |
49 // Readonly status. | 54 // Readonly status. |
50 this.readonly_ = false; | 55 this.readonly_ = false; |
51 this.currentVolumeMetadata_ = {rootPath: '/'}; | 56 this.currentVolumeMetadata_ = {rootPath: '/'}; |
52 this.offline_ = false; | 57 this.offline_ = false; |
53 } | 58 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
98 | 103 |
99 /** | 104 /** |
100 * Selection in the fileList. | 105 * Selection in the fileList. |
101 * @type {cr.ui.ListSelectionModel|cr.ui.ListSingleSelectionModel} | 106 * @type {cr.ui.ListSelectionModel|cr.ui.ListSingleSelectionModel} |
102 */ | 107 */ |
103 get fileListSelection() { | 108 get fileListSelection() { |
104 return this.fileListSelection_; | 109 return this.fileListSelection_; |
105 }, | 110 }, |
106 | 111 |
107 /** | 112 /** |
108 * Top level Directories from user perspective. | |
109 * @type {cr.ui.ArrayDataModel} | |
110 */ | |
111 get rootsList() { | |
112 return this.rootsList_; | |
113 }, | |
114 | |
115 /** | |
116 * Selection in the rootsList. | 113 * Selection in the rootsList. |
117 * @type {cr.ui.ListSingleSelectionModel} | 114 * @type {cr.ui.ListSingleSelectionModel} |
118 */ | 115 */ |
119 get rootsListSelection() { | 116 get rootsListSelection() { |
120 return this.rootsListSelection_; | 117 return this.rootsListSelection_; |
121 }, | 118 }, |
122 | 119 |
123 /** | |
124 * Root path for the current directory (parent directory is not navigatable | |
125 * for the user). | |
126 * @type {string} | |
127 */ | |
128 get rootPath() { | |
129 return DirectoryModel.getRootPath(this.currentEntry.fullPath); | |
130 }, | |
131 | |
132 get rootType() { | 120 get rootType() { |
133 return DirectoryModel.getRootType(this.currentEntry.fullPath); | 121 return DirectoryModel.getRootType(this.currentEntry.fullPath); |
134 }, | 122 }, |
135 | 123 |
136 get rootName() { | 124 get rootName() { |
137 return DirectoryModel.getRootName(this.currentEntry.fullPath); | 125 return DirectoryModel.getRootName(this.currentEntry.fullPath); |
138 }, | 126 }, |
139 | 127 |
140 get rootEntry() { | 128 get rootEntry() { |
141 return this.rootsList.item(this.rootsListSelection.selectedIndex); | 129 return this.rootsList_.item(this.rootsListSelection.selectedIndex); |
142 }, | 130 }, |
143 | 131 |
144 /** | 132 /** |
145 * True if current directory is read only. | 133 * True if current directory is read only. |
146 * @type {boolean} | 134 * @type {boolean} |
147 */ | 135 */ |
148 get readonly() { | 136 get readonly() { |
149 return this.readonly_; | 137 return this.readonly_; |
150 }, | 138 }, |
151 | 139 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 }, | 227 }, |
240 | 228 |
241 set leadName(value) { | 229 set leadName(value) { |
242 for (var i = 0; i < this.fileList_.length; i++) { | 230 for (var i = 0; i < this.fileList_.length; i++) { |
243 if (this.fileList_.item(i).name == value) { | 231 if (this.fileList_.item(i).name == value) { |
244 this.fileListSelection_.leadIndex = i; | 232 this.fileListSelection_.leadIndex = i; |
245 return; | 233 return; |
246 } | 234 } |
247 } | 235 } |
248 } | 236 } |
249 }; | 237 }; |
Vladislav Kaznacheev
2012/04/20 14:55:11
nit: if you renamed these functions in place it wo
Oleg Eterevsky
2012/04/20 15:00:32
Unfortunately, they were defined as fields in
Dir
| |
250 | 238 |
251 /** | 239 /** |
240 * @return {cr.ui.ArrayDataModel} The list of roots. | |
241 */ | |
242 DirectoryModel.prototype.getRootsList = function() { | |
243 return this.rootsList_; | |
244 }; | |
245 | |
246 /** | |
247 * @return {string} Root path for the current directory (parent directory is | |
248 * not navigatable for the user). | |
249 */ | |
250 DirectoryModel.prototype.getCurrentRootPath = function() { | |
251 return DirectoryModel.getRootPath(this.currentDirEntry_.fullPath); | |
252 }; | |
253 | |
254 /** | |
252 * Add a filter for directory contents. | 255 * Add a filter for directory contents. |
253 * @param {string} name An identifier of the filter (used when removing it). | 256 * @param {string} name An identifier of the filter (used when removing it). |
254 * @param {function(Entry):boolean} filter Hide file if false. | 257 * @param {function(Entry):boolean} filter Hide file if false. |
255 */ | 258 */ |
256 DirectoryModel.prototype.addFilter = function(name, filter) { | 259 DirectoryModel.prototype.addFilter = function(name, filter) { |
257 this.filters_[name] = filter; | 260 this.filters_[name] = filter; |
258 this.rescanSoon(); | 261 this.rescanSoon(); |
259 }; | 262 }; |
260 | 263 |
261 /** | 264 /** |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
322 return; | 325 return; |
323 } | 326 } |
324 | 327 |
325 this.runningScan_ = this.createScanner_(fileList, successCallback); | 328 this.runningScan_ = this.createScanner_(fileList, successCallback); |
326 this.runningScan_.run(); | 329 this.runningScan_.run(); |
327 }; | 330 }; |
328 | 331 |
329 /** | 332 /** |
330 * @private | 333 * @private |
331 * @param {Array.<Entry>|cr.ui.ArrayDataModel} list | 334 * @param {Array.<Entry>|cr.ui.ArrayDataModel} list |
332 * @param {function} successCallback | 335 * @param {function} successCallback Callback on success. |
333 * @return {DirectoryModel.Scanner} | 336 * @return {DirectoryModel.Scanner} New Scanner instance. |
334 */ | 337 */ |
335 DirectoryModel.prototype.createScanner_ = function(list, successCallback) { | 338 DirectoryModel.prototype.createScanner_ = function(list, successCallback) { |
336 var self = this; | 339 var self = this; |
337 function onSuccess() { | 340 function onSuccess() { |
338 self.scanFailures_ = 0; | 341 self.scanFailures_ = 0; |
339 successCallback(); | 342 successCallback(); |
340 if (self.pendingScan_) { | 343 if (self.pendingScan_) { |
341 self.runningScan_ = self.pendingScan_; | 344 self.runningScan_ = self.pendingScan_; |
342 self.pendingScan_ = null; | 345 self.pendingScan_ = null; |
343 self.runningScan_.run(); | 346 self.runningScan_.run(); |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
659 function onRescanComplete() { | 662 function onRescanComplete() { |
660 action(); | 663 action(); |
661 // For tests that open the dialog to empty directories, everything | 664 // For tests that open the dialog to empty directories, everything |
662 // is loaded at this point. | 665 // is loaded at this point. |
663 chrome.test.sendMessage('directory-change-complete'); | 666 chrome.test.sendMessage('directory-change-complete'); |
664 } | 667 } |
665 this.updateReadonlyStatus_(); | 668 this.updateReadonlyStatus_(); |
666 this.updateVolumeMetadata_(); | 669 this.updateVolumeMetadata_(); |
667 this.updateRootsListSelection_(); | 670 this.updateRootsListSelection_(); |
668 this.scan_(onRescanComplete); | 671 this.scan_(onRescanComplete); |
672 this.currentDirByRoot_[this.getCurrentRootPath()] = dirEntry.fullPath; | |
669 | 673 |
670 var e = new cr.Event('directory-changed'); | 674 var e = new cr.Event('directory-changed'); |
671 e.previousDirEntry = previous; | 675 e.previousDirEntry = previous; |
672 e.newDirEntry = dirEntry; | 676 e.newDirEntry = dirEntry; |
673 e.initial = initial; | 677 e.initial = initial; |
674 this.dispatchEvent(e); | 678 this.dispatchEvent(e); |
675 }; | 679 }; |
676 | 680 |
677 /** | 681 /** |
678 * Change the state of the model to reflect the specified path (either a | 682 * Change the state of the model to reflect the specified path (either a |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
994 } | 998 } |
995 }; | 999 }; |
996 | 1000 |
997 /** | 1001 /** |
998 * @param {function} opt_callback Called when all roots are resolved. | 1002 * @param {function} opt_callback Called when all roots are resolved. |
999 * @param {boolean} opt_resolveGData If true GData should be resolved for real, | 1003 * @param {boolean} opt_resolveGData If true GData should be resolved for real, |
1000 * If false a stub entry should be created. | 1004 * If false a stub entry should be created. |
1001 */ | 1005 */ |
1002 DirectoryModel.prototype.updateRoots = function(opt_callback, | 1006 DirectoryModel.prototype.updateRoots = function(opt_callback, |
1003 opt_resolveGData) { | 1007 opt_resolveGData) { |
1004 console.log('resolving roots'); | |
1005 var self = this; | 1008 var self = this; |
1006 this.resolveRoots_(function(rootEntries) { | 1009 this.resolveRoots_(function(rootEntries) { |
1007 console.log('resolved roots:', rootEntries); | |
1008 var dm = self.rootsList_; | 1010 var dm = self.rootsList_; |
1009 var args = [0, dm.length].concat(rootEntries); | 1011 var args = [0, dm.length].concat(rootEntries); |
1010 dm.splice.apply(dm, args); | 1012 dm.splice.apply(dm, args); |
1011 | 1013 |
1012 self.updateRootsListSelection_(); | 1014 self.updateRootsListSelection_(); |
1013 | 1015 |
1014 if (opt_callback) | 1016 if (opt_callback) |
1015 opt_callback(); | 1017 opt_callback(); |
1016 }, opt_resolveGData); | 1018 }, opt_resolveGData); |
1017 }; | 1019 }; |
1018 | 1020 |
1019 /** | 1021 /** |
1022 * Register a listener for a new root element in left menu. | |
1020 * @private | 1023 * @private |
1021 * @param {Event} event | 1024 * @param {HTMLElement} li List item representing a volume. |
1025 * @param {Entry} entry Root directory entry. | |
1022 */ | 1026 */ |
1023 DirectoryModel.prototype.onRootsSelectionChanged_ = function(event) { | 1027 DirectoryModel.prototype.registerRootClickListener_ = function append(li, |
1024 var root = this.rootsList.item(this.rootsListSelection.selectedIndex); | 1028 entry) { |
1025 if (root && this.rootPath != root.fullPath) | 1029 li.addEventListener('click', this.onRootClick_.bind(this, entry)); |
1026 this.changeDirectory(root.fullPath); | 1030 }; |
1031 | |
1032 /** | |
1033 * Handler for root item being clicked. | |
1034 * @private | |
1035 * @param {Entry} entry Entry to navigate to. | |
1036 * @param {Event} event The event. | |
1037 */ | |
1038 DirectoryModel.prototype.onRootClick_ = function(entry, event) { | |
1039 var new_path = entry.fullPath; | |
1040 if (entry.fullPath == this.getCurrentRootPath()) { | |
1041 this.changeDirectory(entry.fullPath); | |
1042 } else { | |
1043 this.changeDirectory(this.currentDirByRoot_[entry.fullPath] || | |
1044 entry.fullPath); | |
1045 } | |
1027 }; | 1046 }; |
1028 | 1047 |
1029 /** | 1048 /** |
1030 * @private | 1049 * @private |
1031 */ | 1050 */ |
1032 DirectoryModel.prototype.updateRootsListSelection_ = function() { | 1051 DirectoryModel.prototype.updateRootsListSelection_ = function() { |
1033 var roots = this.rootsList_; | 1052 var roots = this.rootsList_; |
1034 var rootPath = this.rootPath; | 1053 var rootPath = this.getCurrentRootPath(); |
1035 for (var index = 0; index < roots.length; index++) { | 1054 for (var index = 0; index < roots.length; index++) { |
1036 if (roots.item(index).fullPath == rootPath) { | 1055 if (roots.item(index).fullPath == rootPath) { |
1037 this.rootsListSelection.selectedIndex = index; | 1056 this.rootsListSelection.selectedIndex = index; |
1038 return; | 1057 return; |
1039 } | 1058 } |
1040 } | 1059 } |
1041 this.rootsListSelection.selectedIndex = -1; | 1060 this.rootsListSelection.selectedIndex = -1; |
1042 }; | 1061 }; |
1043 | 1062 |
1044 /** | 1063 /** |
(...skipping 16 matching lines...) Expand all Loading... | |
1061 default: | 1080 default: |
1062 this.readonly_ = true; | 1081 this.readonly_ = true; |
1063 break; | 1082 break; |
1064 } | 1083 } |
1065 }; | 1084 }; |
1066 | 1085 |
1067 /** | 1086 /** |
1068 * @private | 1087 * @private |
1069 */ | 1088 */ |
1070 DirectoryModel.prototype.updateVolumeMetadata_ = function() { | 1089 DirectoryModel.prototype.updateVolumeMetadata_ = function() { |
1071 var rootPath = this.rootPath; | 1090 var rootPath = this.getCurrentRootPath(); |
1072 if (this.currentVolumeMetadata_.rootPath != rootPath) { | 1091 if (this.currentVolumeMetadata_.rootPath != rootPath) { |
1073 var metadata = this.currentVolumeMetadata_ = {rootPath: rootPath}; | 1092 var metadata = this.currentVolumeMetadata_ = {rootPath: rootPath}; |
1074 if (DirectoryModel.getRootType(rootPath) == | 1093 if (DirectoryModel.getRootType(rootPath) == |
1075 DirectoryModel.RootType.REMOVABLE) { | 1094 DirectoryModel.RootType.REMOVABLE) { |
1076 var self = this; | 1095 var self = this; |
1077 this.root_.getDirectory(rootPath, {}, function(entry) { | 1096 this.root_.getDirectory(rootPath, {}, function(entry) { |
1078 chrome.fileBrowserPrivate.getVolumeMetadata(entry.toURL(), | 1097 chrome.fileBrowserPrivate.getVolumeMetadata(entry.toURL(), |
1079 function(systemMetadata) { | 1098 function(systemMetadata) { |
1080 if (systemMetadata) { | 1099 if (systemMetadata) { |
1081 metadata.isReadOnly = systemMetadata.isReadOnly; | 1100 metadata.isReadOnly = systemMetadata.isReadOnly; |
1082 self.updateReadonlyStatus_(); | 1101 self.updateReadonlyStatus_(); |
1083 } | 1102 } |
1084 }); | 1103 }); |
1085 }); | 1104 }); |
1086 } | 1105 } |
1087 } | 1106 } |
1088 }; | 1107 }; |
1089 | 1108 |
1090 /** | 1109 /** |
1091 * @param {string} path | 1110 * @param {string} path Any path in the file system. |
1092 * @return {string} The root path. | 1111 * @return {string} The root path. |
1093 */ | 1112 */ |
1094 DirectoryModel.getRootPath = function(path) { | 1113 DirectoryModel.getRootPath = function(path) { |
1095 var type = DirectoryModel.getRootType(path); | 1114 var type = DirectoryModel.getRootType(path); |
1096 | 1115 |
1097 if (type == DirectoryModel.RootType.DOWNLOADS) | 1116 if (type == DirectoryModel.RootType.DOWNLOADS) |
1098 return '/' + DirectoryModel.DOWNLOADS_DIRECTORY; | 1117 return '/' + DirectoryModel.DOWNLOADS_DIRECTORY; |
1099 if (type == DirectoryModel.RootType.GDATA) | 1118 if (type == DirectoryModel.RootType.GDATA) |
1100 return '/' + DirectoryModel.GDATA_DIRECTORY; | 1119 return '/' + DirectoryModel.GDATA_DIRECTORY; |
1101 | 1120 |
(...skipping 13 matching lines...) Expand all Loading... | |
1115 * @param {string} path | 1134 * @param {string} path |
1116 * @return {string} | 1135 * @return {string} |
1117 */ | 1136 */ |
1118 DirectoryModel.getRootName = function(path) { | 1137 DirectoryModel.getRootName = function(path) { |
1119 var root = DirectoryModel.getRootPath(path); | 1138 var root = DirectoryModel.getRootPath(path); |
1120 var index = root.lastIndexOf('/'); | 1139 var index = root.lastIndexOf('/'); |
1121 return index == -1 ? root : root.substring(index + 1); | 1140 return index == -1 ? root : root.substring(index + 1); |
1122 }; | 1141 }; |
1123 | 1142 |
1124 /** | 1143 /** |
1125 * @param {string} path | 1144 * @param {string} path Path. |
1126 * @return {string} | 1145 * @return {string} A root type. |
1127 */ | 1146 */ |
1128 DirectoryModel.getRootType = function(path) { | 1147 DirectoryModel.getRootType = function(path) { |
1129 function isTop(dir) { | 1148 function isTop(dir) { |
1130 return path.substr(1, dir.length) == dir; | 1149 return path.substr(1, dir.length) == dir; |
1131 } | 1150 } |
1132 | 1151 |
1133 if (isTop(DirectoryModel.DOWNLOADS_DIRECTORY)) | 1152 if (isTop(DirectoryModel.DOWNLOADS_DIRECTORY)) |
1134 return DirectoryModel.RootType.DOWNLOADS; | 1153 return DirectoryModel.RootType.DOWNLOADS; |
1135 else if (isTop(DirectoryModel.GDATA_DIRECTORY)) | 1154 if (isTop(DirectoryModel.GDATA_DIRECTORY)) |
1136 return DirectoryModel.RootType.GDATA; | 1155 return DirectoryModel.RootType.GDATA; |
1137 else if (isTop(DirectoryModel.ARCHIVE_DIRECTORY)) | 1156 if (isTop(DirectoryModel.ARCHIVE_DIRECTORY)) |
1138 return DirectoryModel.RootType.ARCHIVE; | 1157 return DirectoryModel.RootType.ARCHIVE; |
1139 else if (isTop(DirectoryModel.REMOVABLE_DIRECTORY)) | 1158 if (isTop(DirectoryModel.REMOVABLE_DIRECTORY)) |
1140 return DirectoryModel.RootType.REMOVABLE; | 1159 return DirectoryModel.RootType.REMOVABLE; |
1141 return ''; | 1160 return ''; |
1142 }; | 1161 }; |
1143 | 1162 |
1144 /** | 1163 /** |
1145 * @param {string} path | 1164 * @param {string} path |
1146 * @return {boolean} | 1165 * @return {boolean} |
1147 */ | 1166 */ |
1148 DirectoryModel.isRootPath = function(path) { | 1167 DirectoryModel.isRootPath = function(path) { |
1149 if (path[path.length - 1] == '/') | 1168 if (path[path.length - 1] == '/') |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1241 /** | 1260 /** |
1242 * @private | 1261 * @private |
1243 */ | 1262 */ |
1244 DirectoryModel.Scanner.prototype.recordMetrics_ = function() { | 1263 DirectoryModel.Scanner.prototype.recordMetrics_ = function() { |
1245 metrics.recordInterval('DirectoryScan'); | 1264 metrics.recordInterval('DirectoryScan'); |
1246 if (this.dir_.fullPath == | 1265 if (this.dir_.fullPath == |
1247 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) { | 1266 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) { |
1248 metrics.recordMediumCount('DownloadsCount', this.list_.length); | 1267 metrics.recordMediumCount('DownloadsCount', this.list_.length); |
1249 } | 1268 } |
1250 }; | 1269 }; |
OLD | NEW |