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

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

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

Powered by Google App Engine
This is Rietveld 408576698