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

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

Issue 10206015: 1. Fix JSDocs in directory_model.js. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 8 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
« no previous file with comments | « no previous file | chrome/browser/resources/file_manager/js/file_manager.js » ('j') | 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) 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 44
45 /** 45 /**
46 * A map root.fullPath -> currentDirectory.fullPath. 46 * A map root.fullPath -> currentDirectory.fullPath.
47 * @private 47 * @private
48 * @type {Object.<string, string>} 48 * @type {Object.<string, string>}
49 */ 49 */
50 this.currentDirByRoot_ = {}; 50 this.currentDirByRoot_ = {};
51 51
52 // The map 'name' -> callback. Callbacks are function(entry) -> boolean. 52 // The map 'name' -> callback. Callbacks are function(entry) -> boolean.
53 this.filters_ = {}; 53 this.filters_ = {};
54 this.filterHidden = true; 54 this.setFilterHidden(true);
55 55
56 // Readonly status. 56 // Readonly status.
57 this.readonly_ = false; 57 this.readonly_ = false;
58 this.currentVolumeMetadata_ = {rootPath: '/'}; 58 this.currentVolumeMetadata_ = {rootPath: '/'};
59 this.offline_ = false; 59 this.offline_ = false;
60 } 60 }
61 61
62 /** 62 /**
63 * The name of the directory containing externally 63 * The name of the directory containing externally
64 * mounted removable storage volumes. 64 * mounted removable storage volumes.
(...skipping 20 matching lines...) Expand all
85 /** 85 /**
86 * The name of the downloads directory. 86 * The name of the downloads directory.
87 */ 87 */
88 DirectoryModel.DOWNLOADS_DIRECTORY = 'Downloads'; 88 DirectoryModel.DOWNLOADS_DIRECTORY = 'Downloads';
89 89
90 /** 90 /**
91 * The name of the gdata provider directory. 91 * The name of the gdata provider directory.
92 */ 92 */
93 DirectoryModel.GDATA_DIRECTORY = 'gdata'; 93 DirectoryModel.GDATA_DIRECTORY = 'gdata';
94 94
95 DirectoryModel.prototype = { 95 /**
96 __proto__: cr.EventTarget.prototype, 96 * DirectoryModel extends cr.EventTarget.
97 */
98 DirectoryModel.prototype.__proto__ = cr.EventTarget.prototype;
97 99
98 /** 100 /**
99 * Files in the current directory. 101 * @return {cr.ui.ArrayDataModel} Files in the current directory.
100 * @type {cr.ui.ArrayDataModel} 102 */
101 */ 103 DirectoryModel.prototype.getFileList = function() {
102 get fileList() { 104 return this.fileList_;
103 return this.fileList_; 105 };
104 },
105 106
106 /** 107 /**
107 * Selection in the fileList. 108 * Sort the file list.
108 * @type {cr.ui.ListSelectionModel|cr.ui.ListSingleSelectionModel} 109 * @param {string} sortField Sort field.
109 */ 110 * @param {string} sortDirection "asc" or "desc".
110 get fileListSelection() { 111 */
111 return this.fileListSelection_; 112 DirectoryModel.prototype.sortFileList = function(sortField, sortDirection) {
112 }, 113 this.fileList_.sort(sortField, sortDirection);
114 };
113 115
114 get rootType() { 116 /**
115 return DirectoryModel.getRootType(this.currentEntry.fullPath); 117 * @return {cr.ui.ListSelectionModel|cr.ui.ListSingleSelectionModel} Selection
116 }, 118 * in the fileList.
119 */
120 DirectoryModel.prototype.getFileListSelection = function() {
121 return this.fileListSelection_;
122 };
117 123
118 get rootName() { 124 /**
119 return DirectoryModel.getRootName(this.currentEntry.fullPath); 125 * @return {DirectoryModel.RootType} Root type of current root.
120 }, 126 */
127 DirectoryModel.prototype.getRootType = function() {
128 return DirectoryModel.getRootType(this.currentDirEntry_.fullPath);
129 };
121 130
122 /** 131 /**
123 * True if current directory is read only. 132 * @return {string} Root name.
124 * @type {boolean} 133 */
125 */ 134 DirectoryModel.prototype.getRootName = function() {
126 get readonly() { 135 return DirectoryModel.getRootName(this.currentDirEntry_.fullPath);
127 return this.readonly_; 136 };
128 },
129 137
130 get offline() { 138 /**
131 return this.offline_; 139 * @return {boolean} True if current directory is read only.
132 }, 140 */
133 set offline(value) { 141 DirectoryModel.prototype.isReadOnly = function() {
134 if (this.offline_ != value) { 142 return this.readonly_;
135 this.offline_ = !!value; 143 };
136 this.updateReadonlyStatus_();
137 }
138 },
139 144
140 get isSystemDirectoy() { 145 /**
141 var path = this.currentEntry.fullPath; 146 * @return {boolean} If offline.
142 return path == '/' || 147 */
143 path == '/' + DirectoryModel.REMOVABLE_DIRECTORY || 148 DirectoryModel.prototype.isOffline = function() {
144 path == '/' + DirectoryModel.ARCHIVE_DIRECTORY; 149 return this.offline_;
145 }, 150 };
146 151
147 get filterHidden() { 152 /**
148 return !!this.filters_['hidden']; 153 * @param {boolean} value New online status.
149 }, 154 */
155 DirectoryModel.prototype.setOffline = function(value) {
156 if (this.offline_ != value) {
157 this.offline_ = !!value;
158 this.updateReadonlyStatus_();
159 }
160 };
150 161
151 set filterHidden(value) { 162 /**
152 if (value) { 163 * @return {boolean} If current directory is system.
153 this.addFilter('hidden', 164 */
154 function(e) {return e.name.substr(0, 1) != '.';}); 165 DirectoryModel.prototype.isSystemDirectory = function() {
155 } else { 166 var path = this.currentDirEntry_.fullPath;
156 this.removeFilter('hidden'); 167 return path == '/' ||
157 } 168 path == '/' + DirectoryModel.REMOVABLE_DIRECTORY ||
158 }, 169 path == '/' + DirectoryModel.ARCHIVE_DIRECTORY;
170 };
159 171
160 /** 172 /**
161 * Current directory. 173 * @return {boolean} If the files with names starting with "." are not shown.
162 * @type {DirectoryEntry} 174 */
163 */ 175 DirectoryModel.prototype.isFilterHiddenOn = function() {
164 get currentEntry() { 176 return !!this.filters_['hidden'];
165 return this.currentDirEntry_; 177 };
166 },
167 178
168 set autoSelectIndex(value) { 179 /**
169 this.autoSelectIndex_ = value; 180 * @param {boolean} value Whether files with leading "." are hidden.
170 }, 181 */
182 DirectoryModel.prototype.setFilterHidden = function(value) {
183 if (value) {
184 this.addFilter('hidden',
185 function(e) {return e.name.substr(0, 1) != '.';});
186 } else {
187 this.removeFilter('hidden');
188 }
189 };
171 190
172 /** 191 /**
173 * Names of selected files. 192 * @return {DirectoryEntry} Current directory.
174 * @type {Array.<string>} 193 */
175 */ 194 DirectoryModel.prototype.getCurrentDirEntry = function() {
176 get selectedNames() { 195 return this.currentDirEntry_;
177 var indexes = this.fileListSelection_.selectedIndexes; 196 };
178 var dataModel = this.fileList_;
179 if (dataModel) {
180 return indexes.map(function(i) {
181 return dataModel.item(i).name;
182 });
183 }
184 return [];
185 },
186 197
187 set selectedNames(value) { 198 /**
188 var indexes = []; 199 * @param {number} value New auto select index.
189 var dataModel = this.fileList_; 200 */
201 DirectoryModel.prototype.setAutoSelectIndex = function(value) {
202 this.autoSelectIndex_ = value;
203 };
190 204
191 function safeKey(key) { 205 /**
192 // The transformation must: 206 * @private
193 // 1. Never generate a reserved name ('__proto__') 207 * @return {Array.<string>} Names of selected files.
194 // 2. Keep different keys different. 208 */
195 return '#' + key; 209 DirectoryModel.prototype.getSelectedNames_ = function() {
196 } 210 var indexes = this.fileListSelection_.selectedIndexes;
211 var dataModel = this.fileList_;
212 if (dataModel) {
213 return indexes.map(function(i) {
214 return dataModel.item(i).name;
215 });
216 }
217 return [];
218 };
197 219
198 var hash = {}; 220 /**
221 * @private
222 * @param {Array.<string>} value List of names of selected files.
223 */
224 DirectoryModel.prototype.setSelectedNames_ = function(value) {
225 var indexes = [];
226 var dataModel = this.fileList_;
199 227
200 for (var i = 0; i < value.length; i++) 228 function safeKey(key) {
201 hash[safeKey(value[i])] = 1; 229 // The transformation must:
230 // 1. Never generate a reserved name ('__proto__')
231 // 2. Keep different keys different.
232 return '#' + key;
233 }
202 234
203 for (var i = 0; i < dataModel.length; i++) { 235 var hash = {};
204 if (hash.hasOwnProperty(safeKey(dataModel.item(i).name)))
205 indexes.push(i);
206 }
207 this.fileListSelection_.selectedIndexes = indexes;
208 },
209 236
210 /** 237 for (var i = 0; i < value.length; i++)
211 * Lead item file name. 238 hash[safeKey(value[i])] = 1;
212 * @type {string?}
213 */
214 get leadName() {
215 var index = this.fileListSelection_.leadIndex;
216 return index >= 0 && this.fileList_.item(index).name;
217 },
218 239
219 set leadName(value) { 240 for (var i = 0; i < dataModel.length; i++) {
220 for (var i = 0; i < this.fileList_.length; i++) { 241 if (hash.hasOwnProperty(safeKey(dataModel.item(i).name)))
221 if (this.fileList_.item(i).name == value) { 242 indexes.push(i);
222 this.fileListSelection_.leadIndex = i; 243 }
223 return; 244 this.fileListSelection_.selectedIndexes = indexes;
224 } 245 };
246
247 /**
248 * @private
249 * @return {string} Lead item file name.
250 */
251 DirectoryModel.prototype.getLeadName_ = function() {
252 var index = this.fileListSelection_.leadIndex;
253 return index >= 0 && this.fileList_.item(index).name;
254 };
255
256 /**
257 * @private
258 * @param {string} value The name of new lead index.
259 */
260 DirectoryModel.prototype.setLeadName_ = function(value) {
261 for (var i = 0; i < this.fileList_.length; i++) {
262 if (this.fileList_.item(i).name == value) {
263 this.fileListSelection_.leadIndex = i;
264 return;
225 } 265 }
226 } 266 }
227 }; 267 };
228 268
229 /** 269 /**
230 * @return {cr.ui.ArrayDataModel} The list of roots. 270 * @return {cr.ui.ArrayDataModel} The list of roots.
231 */ 271 */
232 DirectoryModel.prototype.getRootsList = function() { 272 DirectoryModel.prototype.getRootsList = function() {
233 return this.rootsList_; 273 return this.rootsList_;
234 }; 274 };
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 this.pendingScan_ = this.createScanner_(fileList, successCallback); 368 this.pendingScan_ = this.createScanner_(fileList, successCallback);
329 return; 369 return;
330 } 370 }
331 371
332 this.runningScan_ = this.createScanner_(fileList, successCallback); 372 this.runningScan_ = this.createScanner_(fileList, successCallback);
333 this.runningScan_.run(); 373 this.runningScan_.run();
334 }; 374 };
335 375
336 /** 376 /**
337 * @private 377 * @private
338 * @param {Array.<Entry>|cr.ui.ArrayDataModel} list 378 * @param {Array.<Entry>|cr.ui.ArrayDataModel} list File list.
339 * @param {function} successCallback Callback on success. 379 * @param {function} successCallback Callback on success.
340 * @return {DirectoryModel.Scanner} New Scanner instance. 380 * @return {DirectoryModel.Scanner} New Scanner instance.
341 */ 381 */
342 DirectoryModel.prototype.createScanner_ = function(list, successCallback) { 382 DirectoryModel.prototype.createScanner_ = function(list, successCallback) {
343 var self = this; 383 var self = this;
344 function onSuccess() { 384 function onSuccess() {
345 self.scanFailures_ = 0; 385 self.scanFailures_ = 0;
346 successCallback(); 386 successCallback();
347 if (self.pendingScan_) { 387 if (self.pendingScan_) {
348 self.runningScan_ = self.pendingScan_; 388 self.runningScan_ = self.pendingScan_;
(...skipping 14 matching lines...) Expand all
363 this.currentDirEntry_, 403 this.currentDirEntry_,
364 list, 404 list,
365 onSuccess, 405 onSuccess,
366 onFailure, 406 onFailure,
367 this.prefetchCacheForSorting_.bind(this), 407 this.prefetchCacheForSorting_.bind(this),
368 this.filters_); 408 this.filters_);
369 }; 409 };
370 410
371 /** 411 /**
372 * @private 412 * @private
373 * @param {Array.<Entry>} entries 413 * @param {Array.<Entry>} entries List of files.
374 */ 414 */
375 DirectoryModel.prototype.replaceFileList_ = function(entries) { 415 DirectoryModel.prototype.replaceFileList_ = function(entries) {
376 cr.dispatchSimpleEvent(this, 'begin-update-files'); 416 cr.dispatchSimpleEvent(this, 'begin-update-files');
377 this.fileListSelection_.beginChange(); 417 this.fileListSelection_.beginChange();
378 418
379 var selectedNames = this.selectedNames; 419 var selectedNames = this.getSelectedNames_();
380 // Restore leadIndex in case leadName no longer exists. 420 // Restore leadIndex in case leadName no longer exists.
381 var leadIndex = this.fileListSelection_.leadIndex; 421 var leadIndex = this.fileListSelection_.leadIndex;
382 var leadName = this.leadName; 422 var leadName = this.getLeadName_();
383 423
384 var spliceArgs = [].slice.call(entries); 424 var spliceArgs = [].slice.call(entries);
385 spliceArgs.unshift(0, this.fileList_.length); 425 spliceArgs.unshift(0, this.fileList_.length);
386 this.fileList_.splice.apply(this.fileList_, spliceArgs); 426 this.fileList_.splice.apply(this.fileList_, spliceArgs);
387 427
388 this.selectedNames = selectedNames; 428 this.setSelectedNames_(selectedNames);
389 this.fileListSelection_.leadIndex = leadIndex; 429 this.fileListSelection_.leadIndex = leadIndex;
390 this.leadName = leadName; 430 this.setLeadName_(leadName);
391 this.fileListSelection_.endChange(); 431 this.fileListSelection_.endChange();
392 cr.dispatchSimpleEvent(this, 'end-update-files'); 432 cr.dispatchSimpleEvent(this, 'end-update-files');
393 }; 433 };
394 434
395 /** 435 /**
396 * Cancels waiting and scheduled rescans and starts new scan. 436 * Cancels waiting and scheduled rescans and starts new scan.
397 * 437 *
398 * If the scan completes successfully on the first attempt, the callback will 438 * If the scan completes successfully on the first attempt, the callback will
399 * be invoked and a 'scan-completed' event will be dispatched. If the scan 439 * be invoked and a 'scan-completed' event will be dispatched. If the scan
400 * fails for any reason, we'll periodically retry until it succeeds (and then 440 * fails for any reason, we'll periodically retry until it succeeds (and then
(...skipping 26 matching lines...) Expand all
427 if (this.currentDirEntry_ == this.unmountedGDataEntry_) { 467 if (this.currentDirEntry_ == this.unmountedGDataEntry_) {
428 onDone(); 468 onDone();
429 return; 469 return;
430 } 470 }
431 this.runningScan_ = this.createScanner_(this.fileList_, onDone); 471 this.runningScan_ = this.createScanner_(this.fileList_, onDone);
432 this.runningScan_.run(); 472 this.runningScan_.run();
433 }; 473 };
434 474
435 /** 475 /**
436 * @private 476 * @private
437 * @param {Array.<Entry>} entries 477 * @param {Array.<Entry>} entries Files.
438 * @param {function} callback 478 * @param {function} callback Callback on done.
439 */ 479 */
440 DirectoryModel.prototype.prefetchCacheForSorting_ = function(entries, 480 DirectoryModel.prototype.prefetchCacheForSorting_ = function(entries,
441 callback) { 481 callback) {
442 var field = this.fileList_.sortStatus.field; 482 var field = this.fileList_.sortStatus.field;
443 if (field) { 483 if (field) {
444 this.prepareSortEntries_(entries, field, callback); 484 this.prepareSortEntries_(entries, field, callback);
445 } else { 485 } else {
446 callback(); 486 callback();
447 } 487 }
448 }; 488 };
(...skipping 25 matching lines...) Expand all
474 514
475 util.removeFileOrDirectory( 515 util.removeFileOrDirectory(
476 entry, 516 entry,
477 onSuccess, 517 onSuccess,
478 util.flog('Error deleting ' + entry.fullPath, onComplete)); 518 util.flog('Error deleting ' + entry.fullPath, onComplete));
479 } 519 }
480 onComplete(); 520 onComplete();
481 }; 521 };
482 522
483 /** 523 /**
484 * @param {string} name 524 * @param {string} name Filename.
485 */ 525 */
486 DirectoryModel.prototype.onEntryChanged = function(name) { 526 DirectoryModel.prototype.onEntryChanged = function(name) {
487 var currentEntry = this.currentEntry; 527 var currentEntry = this.currentDirEntry_;
488 var dm = this.fileList_; 528 var dm = this.fileList_;
489 var self = this; 529 var self = this;
490 530
491 function onEntryFound(entry) { 531 function onEntryFound(entry) {
492 self.prefetchCacheForSorting_([entry], function() { 532 self.prefetchCacheForSorting_([entry], function() {
493 // Do nothing if current directory changed during async operations. 533 // Do nothing if current directory changed during async operations.
494 if (self.currentEntry != currentEntry) 534 if (self.currentDirEntry_ != currentEntry)
495 return; 535 return;
496 536
497 var index = self.findIndexByName_(name); 537 var index = self.findIndexByName_(name);
498 if (index >= 0) 538 if (index >= 0)
499 dm.splice(index, 1, entry); 539 dm.splice(index, 1, entry);
500 else 540 else
501 dm.splice(dm.length, 0, entry); 541 dm.splice(dm.length, 0, entry);
502 }); 542 });
503 }; 543 };
504 544
505 function onError(err) { 545 function onError(err) {
506 // Do nothing if current directory changed during async operations. 546 // Do nothing if current directory changed during async operations.
507 if (self.currentEntry != currentEntry) 547 if (self.currentDirEntry_ != currentEntry)
508 return; 548 return;
509 if (err.code != FileError.NOT_FOUND_ERR) { 549 if (err.code != FileError.NOT_FOUND_ERR) {
510 self.rescanLater(); 550 self.rescanLater();
511 return; 551 return;
512 } 552 }
513 553
514 var index = self.findIndexByName_(name); 554 var index = self.findIndexByName_(name);
515 if (index >= 0) 555 if (index >= 0)
516 dm.splice(index, 1); 556 dm.splice(index, 1);
517 }; 557 };
518 558
519 util.resolvePath(currentEntry, name, onEntryFound, onError); 559 util.resolvePath(this.currentDirEntry_, name, onEntryFound, onError);
520 }; 560 };
521 561
522 /** 562 /**
523 * @private 563 * @private
524 * @param {string} name 564 * @param {string} name Filename.
525 * @return {number} The index in the fileList. 565 * @return {number} The index in the fileList.
526 */ 566 */
527 DirectoryModel.prototype.findIndexByName_ = function(name) { 567 DirectoryModel.prototype.findIndexByName_ = function(name) {
528 var dm = this.fileList_; 568 var dm = this.fileList_;
529 for (var i = 0; i < dm.length; i++) 569 for (var i = 0; i < dm.length; i++)
530 if (dm.item(i).name == name) 570 if (dm.item(i).name == name)
531 return i; 571 return i;
532 return -1; 572 return -1;
533 }; 573 };
534 574
535 /** 575 /**
536 * Rename the entry in the filesystem and update the file list. 576 * Rename the entry in the filesystem and update the file list.
537 * @param {Entry} entry Entry to rename. 577 * @param {Entry} entry Entry to rename.
538 * @param {string} newName 578 * @param {string} newName New name.
539 * @param {function} errorCallback Called on error. 579 * @param {function} errorCallback Called on error.
540 * @param {function} opt_successCallback Called on success. 580 * @param {function} opt_successCallback Called on success.
541 */ 581 */
542 DirectoryModel.prototype.renameEntry = function(entry, newName, errorCallback, 582 DirectoryModel.prototype.renameEntry = function(entry, newName, errorCallback,
543 opt_successCallback) { 583 opt_successCallback) {
544 var self = this; 584 var self = this;
545 function onSuccess(newEntry) { 585 function onSuccess(newEntry) {
546 self.prefetchCacheForSorting_([newEntry], function() { 586 self.prefetchCacheForSorting_([newEntry], function() {
547 var fileList = self.fileList_; 587 var fileList = self.fileList_;
548 var index = fileList.indexOf(entry); 588 var index = fileList.indexOf(entry);
549 if (index >= 0) 589 if (index >= 0)
550 fileList.splice(index, 1, newEntry); 590 fileList.splice(index, 1, newEntry);
551 self.selectEntry(newName); 591 self.selectEntry(newName);
552 // If the entry doesn't exist in the list it mean that it updated from 592 // If the entry doesn't exist in the list it mean that it updated from
553 // outside (probably by directory rescan). 593 // outside (probably by directory rescan).
554 if (opt_successCallback) 594 if (opt_successCallback)
555 opt_successCallback(); 595 opt_successCallback();
556 }); 596 });
557 } 597 }
558 entry.moveTo(this.currentEntry, newName, 598 entry.moveTo(this.currentDirEntry_, newName, onSuccess, errorCallback);
559 onSuccess, errorCallback);
560 }; 599 };
561 600
562 /** 601 /**
563 * Checks if current directory contains a file or directory with this name. 602 * Checks if current directory contains a file or directory with this name.
564 * @param {string} newName Name to check. 603 * @param {string} newName Name to check.
565 * @param {function(boolean, boolean?)} callback Called when the result's 604 * @param {function(boolean, boolean?)} callback Called when the result's
566 * available. First parameter is true if the entry exists and second 605 * available. First parameter is true if the entry exists and second
567 * is true if it's a file. 606 * is true if it's a file.
568 */ 607 */
569 DirectoryModel.prototype.doesExist = function(newName, callback) { 608 DirectoryModel.prototype.doesExist = function(newName, callback) {
570 util.resolvePath(this.currentEntry, newName, 609 util.resolvePath(this.currentDirEntry_, newName,
571 function(entry) { 610 function(entry) {
572 callback(true, entry.isFile); 611 callback(true, entry.isFile);
573 }, 612 },
574 callback.bind(window, false)); 613 callback.bind(window, false));
575 }; 614 };
576 615
577 /** 616 /**
578 * Creates directory and updates the file list. 617 * Creates directory and updates the file list.
579 * 618 *
580 * @param {string} name 619 * @param {string} name Directory name.
581 * @param {function} successCallback 620 * @param {function} successCallback Callback on success.
582 * @param {function} errorCallback 621 * @param {function} errorCallback Callback on failure.
583 */ 622 */
584 DirectoryModel.prototype.createDirectory = function(name, successCallback, 623 DirectoryModel.prototype.createDirectory = function(name, successCallback,
585 errorCallback) { 624 errorCallback) {
586 var self = this; 625 var self = this;
587 function onSuccess(newEntry) { 626 function onSuccess(newEntry) {
588 self.prefetchCacheForSorting_([newEntry], function() { 627 self.prefetchCacheForSorting_([newEntry], function() {
589 var fileList = self.fileList_; 628 var fileList = self.fileList_;
590 var existing = fileList.slice().filter( 629 var existing = fileList.slice().filter(
591 function(e) { return e.name == name; }); 630 function(e) { return e.name == name; });
592 631
593 if (existing.length) { 632 if (existing.length) {
594 self.selectEntry(name); 633 self.selectEntry(name);
595 successCallback(existing[0]); 634 successCallback(existing[0]);
596 } else { 635 } else {
597 self.fileListSelection.beginChange(); 636 self.fileListSelection_.beginChange();
598 fileList.splice(0, 0, newEntry); 637 fileList.splice(0, 0, newEntry);
599 self.selectEntry(name); 638 self.selectEntry(name);
600 self.fileListSelection.endChange(); 639 self.fileListSelection_.endChange();
601 successCallback(newEntry); 640 successCallback(newEntry);
602 } 641 }
603 }); 642 });
604 } 643 }
605 644
606 this.currentEntry.getDirectory(name, {create: true, exclusive: true}, 645 this.currentDirEntry_.getDirectory(name, {create: true, exclusive: true},
607 onSuccess, errorCallback); 646 onSuccess, errorCallback);
608 }; 647 };
609 648
610 /** 649 /**
611 * Changes directory. Causes 'directory-change' event. 650 * Changes directory. Causes 'directory-change' event.
612 * 651 *
613 * @param {string} path New current directory path. 652 * @param {string} path New current directory path.
614 * @param {function} opt_OnError Called if failed. 653 * @param {function} opt_OnError Called if failed.
615 */ 654 */
616 DirectoryModel.prototype.changeDirectory = function(path, opt_OnError) { 655 DirectoryModel.prototype.changeDirectory = function(path, opt_OnError) {
617 var onDirectoryResolved = function(dirEntry) { 656 var onDirectoryResolved = function(dirEntry) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 * @private 693 * @private
655 * @param {DirectoryEntry} dirEntry The absolute path to the new directory. 694 * @param {DirectoryEntry} dirEntry The absolute path to the new directory.
656 * @param {function} action Action executed if the directory loads 695 * @param {function} action Action executed if the directory loads
657 * successfully. By default selects the first item (unless it's a save 696 * successfully. By default selects the first item (unless it's a save
658 * dialog). 697 * dialog).
659 * @param {boolean} initial True if it comes from setupPath and 698 * @param {boolean} initial True if it comes from setupPath and
660 * false if caused by an user action. 699 * false if caused by an user action.
661 */ 700 */
662 DirectoryModel.prototype.changeDirectoryEntry_ = function(dirEntry, action, 701 DirectoryModel.prototype.changeDirectoryEntry_ = function(dirEntry, action,
663 initial) { 702 initial) {
664 var previous = this.currentEntry; 703 var previous = this.currentDirEntry_;
665 this.currentDirEntry_ = dirEntry; 704 this.currentDirEntry_ = dirEntry;
666 function onRescanComplete() { 705 function onRescanComplete() {
667 action(); 706 action();
668 // For tests that open the dialog to empty directories, everything 707 // For tests that open the dialog to empty directories, everything
669 // is loaded at this point. 708 // is loaded at this point.
670 chrome.test.sendMessage('directory-change-complete'); 709 chrome.test.sendMessage('directory-change-complete');
671 } 710 }
672 this.updateReadonlyStatus_(); 711 this.updateReadonlyStatus_();
673 this.updateVolumeMetadata_(); 712 this.updateVolumeMetadata_();
674 this.updateRootsListSelection_(); 713 this.updateRootsListSelection_();
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 } else { 838 } else {
800 this.getDefaultDirectory_(function(defaultDir) { 839 this.getDefaultDirectory_(function(defaultDir) {
801 baseName = defaultDir; 840 baseName = defaultDir;
802 root.getDirectory( 841 root.getDirectory(
803 baseName, {create: false}, onBaseFound, onBaseError); 842 baseName, {create: false}, onBaseFound, onBaseError);
804 }); 843 });
805 } 844 }
806 }; 845 };
807 846
808 /** 847 /**
809 * @param {function} opt_callback 848 * @param {function} opt_callback Callback on done.
810 */ 849 */
811 DirectoryModel.prototype.setupDefaultPath = function(opt_callback) { 850 DirectoryModel.prototype.setupDefaultPath = function(opt_callback) {
812 var overridden = false; 851 var overridden = false;
813 function onExternalDirChange() { overridden = true } 852 function onExternalDirChange() {
853 overridden = true;
854 }
814 this.addEventListener('directory-changed', onExternalDirChange); 855 this.addEventListener('directory-changed', onExternalDirChange);
815 856
816 this.getDefaultDirectory_(function(path) { 857 this.getDefaultDirectory_(function(path) {
817 this.removeEventListener('directory-changed', onExternalDirChange); 858 this.removeEventListener('directory-changed', onExternalDirChange);
818 if (!overridden) 859 if (!overridden)
819 this.setupPath(path, opt_callback); 860 this.setupPath(path, opt_callback);
820 }.bind(this)); 861 }.bind(this));
821 }; 862 };
822 863
823 /** 864 /**
824 * @private 865 * @private
825 * @param {function} callback 866 * @param {function(string)} callback Called with the path to directory.
826 */ 867 */
827 DirectoryModel.prototype.getDefaultDirectory_ = function(callback) { 868 DirectoryModel.prototype.getDefaultDirectory_ = function(callback) {
828 function onGetDirectoryComplete(entries, error) { 869 function onGetDirectoryComplete(entries, error) {
829 if (entries.length > 0) 870 if (entries.length > 0)
830 callback(entries[0].fullPath); 871 callback(entries[0].fullPath);
831 else 872 else
832 callback('/' + DirectoryModel.DOWNLOADS_DIRECTORY); 873 callback('/' + DirectoryModel.DOWNLOADS_DIRECTORY);
833 } 874 }
834 875
835 // No preset given, find a good place to start. 876 // No preset given, find a good place to start.
836 // Check for removable devices, if there are none, go to Downloads. 877 // Check for removable devices, if there are none, go to Downloads.
837 util.readDirectory(this.root_, DirectoryModel.REMOVABLE_DIRECTORY, 878 util.readDirectory(this.root_, DirectoryModel.REMOVABLE_DIRECTORY,
838 onGetDirectoryComplete); 879 onGetDirectoryComplete);
839 }; 880 };
840 881
841 /** 882 /**
842 * @param {string} name 883 * @param {string} name Filename.
843 */ 884 */
844 DirectoryModel.prototype.selectEntry = function(name) { 885 DirectoryModel.prototype.selectEntry = function(name) {
845 var dm = this.fileList_; 886 var dm = this.fileList_;
846 for (var i = 0; i < dm.length; i++) { 887 for (var i = 0; i < dm.length; i++) {
847 if (dm.item(i).name == name) { 888 if (dm.item(i).name == name) {
848 this.selectIndex(i); 889 this.selectIndex(i);
849 return; 890 return;
850 } 891 }
851 } 892 }
852 }; 893 };
853 894
854 /** 895 /**
855 * @param {number} index 896 * @param {number} index Index of file.
856 */ 897 */
857 DirectoryModel.prototype.selectIndex = function(index) { 898 DirectoryModel.prototype.selectIndex = function(index) {
858 // this.focusCurrentList_(); 899 // this.focusCurrentList_();
859 if (index >= this.fileList_.length) 900 if (index >= this.fileList_.length)
860 return; 901 return;
861 902
862 // If a list bound with the model it will do scrollIndexIntoView(index). 903 // If a list bound with the model it will do scrollIndexIntoView(index).
863 this.fileListSelection_.selectedIndex = index; 904 this.fileListSelection_.selectedIndex = index;
864 }; 905 };
865 906
866 /** 907 /**
867 * Cache necessary data before a sort happens. 908 * Cache necessary data before a sort happens.
868 * 909 *
869 * This is called by the table code before a sort happens, so that we can 910 * This is called by the table code before a sort happens, so that we can
870 * go fetch data for the sort field that we may not have yet. 911 * go fetch data for the sort field that we may not have yet.
871 * @private 912 * @private
872 * @param {string} field 913 * @param {string} field Sort field.
873 * @param {function} callback 914 * @param {function} callback Called when done.
874 */ 915 */
875 DirectoryModel.prototype.prepareSort_ = function(field, callback) { 916 DirectoryModel.prototype.prepareSort_ = function(field, callback) {
876 this.prepareSortEntries_(this.fileList_.slice(), field, callback); 917 this.prepareSortEntries_(this.fileList_.slice(), field, callback);
877 }; 918 };
878 919
879 /** 920 /**
880 * @private 921 * @private
881 * @param {Array.<Entry>} entries 922 * @param {Array.<Entry>} entries Files.
882 * @param {string} field 923 * @param {string} field Sort field.
883 * @param {function} callback 924 * @param {function} callback Called when done.
884 */ 925 */
885 DirectoryModel.prototype.prepareSortEntries_ = function(entries, field, 926 DirectoryModel.prototype.prepareSortEntries_ = function(entries, field,
886 callback) { 927 callback) {
887 this.metadataCache_.get(entries, 'filesystem', function(properties) { 928 this.metadataCache_.get(entries, 'filesystem', function(properties) {
888 callback(); 929 callback();
889 }); 930 });
890 }; 931 };
891 932
892 /** 933 /**
893 * Get root entries asynchronously. 934 * Get root entries asynchronously.
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1027 */ 1068 */
1028 DirectoryModel.prototype.updateRootsListSelection_ = function() { 1069 DirectoryModel.prototype.updateRootsListSelection_ = function() {
1029 this.rootsListSelection_.selectedIndex = 1070 this.rootsListSelection_.selectedIndex =
1030 this.findRootsListItem_(this.rootPath); 1071 this.findRootsListItem_(this.rootPath);
1031 }; 1072 };
1032 1073
1033 /** 1074 /**
1034 * @private 1075 * @private
1035 */ 1076 */
1036 DirectoryModel.prototype.updateReadonlyStatus_ = function() { 1077 DirectoryModel.prototype.updateReadonlyStatus_ = function() {
1037 switch (this.rootType) { 1078 switch (this.getRootType()) {
1038 case DirectoryModel.RootType.REMOVABLE: 1079 case DirectoryModel.RootType.REMOVABLE:
1039 this.readonly_ = !!this.currentVolumeMetadata_.isReadOnly; 1080 this.readonly_ = !!this.currentVolumeMetadata_.isReadOnly;
1040 break; 1081 break;
1041 case DirectoryModel.RootType.ARCHIVE: 1082 case DirectoryModel.RootType.ARCHIVE:
1042 this.readonly_ = true; 1083 this.readonly_ = true;
1043 break; 1084 break;
1044 case DirectoryModel.RootType.DOWNLOADS: 1085 case DirectoryModel.RootType.DOWNLOADS:
1045 this.readonly_ = false; 1086 this.readonly_ = false;
1046 break; 1087 break;
1047 case DirectoryModel.RootType.GDATA: 1088 case DirectoryModel.RootType.GDATA:
1048 this.readonly_ = this.offline; 1089 this.readonly_ = this.offline_;
1049 break; 1090 break;
1050 default: 1091 default:
1051 this.readonly_ = true; 1092 this.readonly_ = true;
1052 break; 1093 break;
1053 } 1094 }
1054 }; 1095 };
1055 1096
1056 /** 1097 /**
1057 * @private 1098 * @private
1058 */ 1099 */
(...skipping 13 matching lines...) Expand all
1072 } 1113 }
1073 }); 1114 });
1074 }); 1115 });
1075 } 1116 }
1076 } 1117 }
1077 }; 1118 };
1078 1119
1079 /** 1120 /**
1080 * Prepare the root for the unmount. 1121 * Prepare the root for the unmount.
1081 * 1122 *
1082 * @param {string} rootPath 1123 * @param {string} rootPath The path to the root.
1083 */ 1124 */
1084 DirectoryModel.prototype.prepareUnmount = function(rootPath) { 1125 DirectoryModel.prototype.prepareUnmount = function(rootPath) {
1085 var index = this.findRootsListItem_(rootPath); 1126 var index = this.findRootsListItem_(rootPath);
1086 if (index == -1) { 1127 if (index == -1) {
1087 console.error('Unknown root entry', rootPath); 1128 console.error('Unknown root entry', rootPath);
1088 return; 1129 return;
1089 } 1130 }
1090 var entry = this.rootsList_.item(index); 1131 var entry = this.rootsList_.item(index);
1091 1132
1092 // We never need to remove this attribute because even if the unmount fails 1133 // We never need to remove this attribute because even if the unmount fails
1093 // the onMountCompleted handler calls updateRoots which creates a new entry 1134 // the onMountCompleted handler calls updateRoots which creates a new entry
1094 // object for this volume. 1135 // object for this volume.
1095 entry.unmounting = true; 1136 entry.unmounting = true;
1096 1137
1097 // Re-place the entry into the roots data model to force re-rendering. 1138 // Re-place the entry into the roots data model to force re-rendering.
1098 this.rootsList_.splice(index, 1, entry); 1139 this.rootsList_.splice(index, 1, entry);
1099 1140
1100 if (rootPath == this.rootPath) { 1141 if (rootPath == this.rootPath) {
1101 // TODO(kaznacheev): Consider changing to the most recently used root. 1142 // TODO(kaznacheev): Consider changing to the most recently used root.
1102 this.changeDirectory('/' + DirectoryModel.DOWNLOADS_DIRECTORY); 1143 this.changeDirectory('/' + DirectoryModel.DOWNLOADS_DIRECTORY);
1103 } 1144 }
1104 }; 1145 };
1105 1146
1106 /** 1147 /**
1107 * @param {string} path 1148 * @param {string} path Any path.
1108 * @return {string} The root path. 1149 * @return {string} The root path.
1109 */ 1150 */
1110 DirectoryModel.getRootPath = function(path) { 1151 DirectoryModel.getRootPath = function(path) {
1111 var type = DirectoryModel.getRootType(path); 1152 var type = DirectoryModel.getRootType(path);
1112 1153
1113 if (type == DirectoryModel.RootType.DOWNLOADS) 1154 if (type == DirectoryModel.RootType.DOWNLOADS)
1114 return '/' + DirectoryModel.DOWNLOADS_DIRECTORY; 1155 return '/' + DirectoryModel.DOWNLOADS_DIRECTORY;
1115 if (type == DirectoryModel.RootType.GDATA) 1156 if (type == DirectoryModel.RootType.GDATA)
1116 return '/' + DirectoryModel.GDATA_DIRECTORY; 1157 return '/' + DirectoryModel.GDATA_DIRECTORY;
1117 1158
1118 function subdir(dir) { 1159 function subdir(dir) {
1119 var end = path.indexOf('/', dir.length + 2); 1160 var end = path.indexOf('/', dir.length + 2);
1120 return end == -1 ? path : path.substr(0, end); 1161 return end == -1 ? path : path.substr(0, end);
1121 } 1162 }
1122 1163
1123 if (type == DirectoryModel.RootType.ARCHIVE) 1164 if (type == DirectoryModel.RootType.ARCHIVE)
1124 return subdir(DirectoryModel.ARCHIVE_DIRECTORY); 1165 return subdir(DirectoryModel.ARCHIVE_DIRECTORY);
1125 if (type == DirectoryModel.REMOVABLE_DIRECTORY) 1166 if (type == DirectoryModel.REMOVABLE_DIRECTORY)
1126 return subdir(DirectoryModel.REMOVABLE_DIRECTORY); 1167 return subdir(DirectoryModel.REMOVABLE_DIRECTORY);
1127 return '/'; 1168 return '/';
1128 }; 1169 };
1129 1170
1130 /** 1171 /**
1131 * @param {string} path 1172 * @param {string} path Any path.
1132 * @return {string} 1173 * @return {string} The name of the root.
1133 */ 1174 */
1134 DirectoryModel.getRootName = function(path) { 1175 DirectoryModel.getRootName = function(path) {
1135 var root = DirectoryModel.getRootPath(path); 1176 var root = DirectoryModel.getRootPath(path);
1136 var index = root.lastIndexOf('/'); 1177 var index = root.lastIndexOf('/');
1137 return index == -1 ? root : root.substring(index + 1); 1178 return index == -1 ? root : root.substring(index + 1);
1138 }; 1179 };
1139 1180
1140 /** 1181 /**
1141 * @param {string} path Path. 1182 * @param {string} path Path.
dgozman 2012/04/24 10:58:14 'Any path' for consistency? :)
Oleg Eterevsky 2012/04/24 11:03:33 Changed to "A path".
1142 * @return {string} A root type. 1183 * @return {string} A root type.
1143 */ 1184 */
1144 DirectoryModel.getRootType = function(path) { 1185 DirectoryModel.getRootType = function(path) {
1145 function isTop(dir) { 1186 function isTop(dir) {
1146 return path.substr(1, dir.length) == dir; 1187 return path.substr(1, dir.length) == dir;
1147 } 1188 }
1148 1189
1149 if (isTop(DirectoryModel.DOWNLOADS_DIRECTORY)) 1190 if (isTop(DirectoryModel.DOWNLOADS_DIRECTORY))
1150 return DirectoryModel.RootType.DOWNLOADS; 1191 return DirectoryModel.RootType.DOWNLOADS;
1151 if (isTop(DirectoryModel.GDATA_DIRECTORY)) 1192 if (isTop(DirectoryModel.GDATA_DIRECTORY))
1152 return DirectoryModel.RootType.GDATA; 1193 return DirectoryModel.RootType.GDATA;
1153 if (isTop(DirectoryModel.ARCHIVE_DIRECTORY)) 1194 if (isTop(DirectoryModel.ARCHIVE_DIRECTORY))
1154 return DirectoryModel.RootType.ARCHIVE; 1195 return DirectoryModel.RootType.ARCHIVE;
1155 if (isTop(DirectoryModel.REMOVABLE_DIRECTORY)) 1196 if (isTop(DirectoryModel.REMOVABLE_DIRECTORY))
1156 return DirectoryModel.RootType.REMOVABLE; 1197 return DirectoryModel.RootType.REMOVABLE;
1157 return ''; 1198 return '';
1158 }; 1199 };
1159 1200
1160 /** 1201 /**
1161 * @param {string} path 1202 * @param {string} path A path.
1162 * @return {boolean} 1203 * @return {boolean} True if it is a path to the root.
1163 */ 1204 */
1164 DirectoryModel.isRootPath = function(path) { 1205 DirectoryModel.isRootPath = function(path) {
1165 if (path[path.length - 1] == '/') 1206 if (path[path.length - 1] == '/')
1166 path = path.substring(0, path.length - 1); 1207 path = path.substring(0, path.length - 1);
1167 return DirectoryModel.getRootPath(path) == path; 1208 return DirectoryModel.getRootPath(path) == path;
1168 }; 1209 };
1169 1210
1170 /** 1211 /**
1171 * @constructor 1212 * @constructor
1172 * @extends cr.EventTarget 1213 * @extends cr.EventTarget
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1217 /** 1258 /**
1218 * @private 1259 * @private
1219 */ 1260 */
1220 DirectoryModel.Scanner.prototype.readNextChunk_ = function() { 1261 DirectoryModel.Scanner.prototype.readNextChunk_ = function() {
1221 this.reader_.readEntries(this.onChunkComplete_.bind(this), 1262 this.reader_.readEntries(this.onChunkComplete_.bind(this),
1222 this.errorCallback_); 1263 this.errorCallback_);
1223 }; 1264 };
1224 1265
1225 /** 1266 /**
1226 * @private 1267 * @private
1227 * @param {Array.<Entry>} entries 1268 * @param {Array.<Entry>} entries File list.
1228 */ 1269 */
1229 DirectoryModel.Scanner.prototype.onChunkComplete_ = function(entries) { 1270 DirectoryModel.Scanner.prototype.onChunkComplete_ = function(entries) {
1230 if (this.cancelled_) 1271 if (this.cancelled_)
1231 return; 1272 return;
1232 1273
1233 if (entries.length == 0) { 1274 if (entries.length == 0) {
1234 this.successCallback_(); 1275 this.successCallback_();
1235 this.recordMetrics_(); 1276 this.recordMetrics_();
1236 return; 1277 return;
1237 } 1278 }
(...skipping 19 matching lines...) Expand all
1257 /** 1298 /**
1258 * @private 1299 * @private
1259 */ 1300 */
1260 DirectoryModel.Scanner.prototype.recordMetrics_ = function() { 1301 DirectoryModel.Scanner.prototype.recordMetrics_ = function() {
1261 metrics.recordInterval('DirectoryScan'); 1302 metrics.recordInterval('DirectoryScan');
1262 if (this.dir_.fullPath == 1303 if (this.dir_.fullPath ==
1263 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) { 1304 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) {
1264 metrics.recordMediumCount('DownloadsCount', this.list_.length); 1305 metrics.recordMediumCount('DownloadsCount', this.list_.length);
1265 } 1306 }
1266 }; 1307 };
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/resources/file_manager/js/file_manager.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698