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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 | 48 |
49 // The map 'name' -> callback. Callbacks are function(entry) -> boolean. | 49 // The map 'name' -> callback. Callbacks are function(entry) -> boolean. |
50 this.filters_ = {}; | 50 this.filters_ = {}; |
51 this.setFilterHidden(true); | 51 this.setFilterHidden(true); |
52 | 52 |
53 /** | 53 /** |
54 * @private | 54 * @private |
55 * @type {Object.<string, boolean>} | 55 * @type {Object.<string, boolean>} |
56 */ | 56 */ |
57 this.volumeReadOnlyStatus_ = {}; | 57 this.volumeReadOnlyStatus_ = {}; |
| 58 |
| 59 /** |
| 60 * Directory in which search results are displayed. Not null iff search |
| 61 * results are being displayed. |
| 62 * @private |
| 63 * @type {Entry} |
| 64 */ |
| 65 this.searchDirEntry_ = null; |
| 66 |
| 67 /** |
| 68 * Is search in progress. |
| 69 * @private |
| 70 * @type {boolean} |
| 71 */ |
| 72 this.isSearching_ = false; |
58 } | 73 } |
59 | 74 |
60 /** | 75 /** |
61 * The name of the directory containing externally | 76 * The name of the directory containing externally |
62 * mounted removable storage volumes. | 77 * mounted removable storage volumes. |
63 */ | 78 */ |
64 DirectoryModel.REMOVABLE_DIRECTORY = 'removable'; | 79 DirectoryModel.REMOVABLE_DIRECTORY = 'removable'; |
65 | 80 |
66 /** | 81 /** |
67 * The name of the directory containing externally | 82 * The name of the directory containing externally |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 * GData access mode: lazy (GData root displayed, no content is fetched yet). | 114 * GData access mode: lazy (GData root displayed, no content is fetched yet). |
100 */ | 115 */ |
101 DirectoryModel.GDATA_ACCESS_LAZY = 1; | 116 DirectoryModel.GDATA_ACCESS_LAZY = 1; |
102 | 117 |
103 /** | 118 /** |
104 * GData access mode: full (GData root displayed, content is available). | 119 * GData access mode: full (GData root displayed, content is available). |
105 */ | 120 */ |
106 DirectoryModel.GDATA_ACCESS_FULL = 2; | 121 DirectoryModel.GDATA_ACCESS_FULL = 2; |
107 | 122 |
108 /** | 123 /** |
| 124 * Root path used for displaying gdata content search results. |
| 125 * Search results will be shown in directory 'GDATA_SEARCH_ROOT_PATH/query'. |
| 126 * |
| 127 * @const |
| 128 * @type {string} |
| 129 */ |
| 130 DirectoryModel.GDATA_SEARCH_ROOT_PATH = '/drive/.search'; |
| 131 |
| 132 /** |
| 133 * @const |
| 134 * @type {Array.<string>} |
| 135 */ |
| 136 DirectoryModel.GDATA_SEARCH_ROOT_COMPONENTS = ['', 'drive', '.search']; |
| 137 |
| 138 /** |
109 * DirectoryModel extends cr.EventTarget. | 139 * DirectoryModel extends cr.EventTarget. |
110 */ | 140 */ |
111 DirectoryModel.prototype.__proto__ = cr.EventTarget.prototype; | 141 DirectoryModel.prototype.__proto__ = cr.EventTarget.prototype; |
112 | 142 |
113 /** | 143 /** |
114 * @return {cr.ui.ArrayDataModel} Files in the current directory. | 144 * @return {cr.ui.ArrayDataModel} Files in the current directory. |
115 */ | 145 */ |
116 DirectoryModel.prototype.getFileList = function() { | 146 DirectoryModel.prototype.getFileList = function() { |
117 return this.fileList_; | 147 return this.fileList_; |
118 }; | 148 }; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 }; | 200 }; |
171 | 201 |
172 /** | 202 /** |
173 * @return {boolean} True if current directory is read only. | 203 * @return {boolean} True if current directory is read only. |
174 */ | 204 */ |
175 DirectoryModel.prototype.isReadOnly = function() { | 205 DirectoryModel.prototype.isReadOnly = function() { |
176 return this.isPathReadOnly(this.getCurrentRootPath()); | 206 return this.isPathReadOnly(this.getCurrentRootPath()); |
177 }; | 207 }; |
178 | 208 |
179 /** | 209 /** |
180 * @param {string} path Path to check. | 210 * @return {boolean} True if search is in progress. |
| 211 */ |
| 212 DirectoryModel.prototype.isSearching = function() { |
| 213 return this.isSearching_; |
| 214 }; |
| 215 |
| 216 /** |
| 217 * @return {boolean} True if we are currently showing search results. |
| 218 */ |
| 219 DirectoryModel.prototype.isOnGDataSearchDir = function() { |
| 220 return this.getSearchOrCurrentDirEntry() != this.getCurrentDirEntry(); |
| 221 }; |
| 222 |
| 223 /** |
| 224 * @param {strin} path Path to check. |
181 * @return {boolean} True if the |path| is read only. | 225 * @return {boolean} True if the |path| is read only. |
182 */ | 226 */ |
183 DirectoryModel.prototype.isPathReadOnly = function(path) { | 227 DirectoryModel.prototype.isPathReadOnly = function(path) { |
184 switch (DirectoryModel.getRootType(path)) { | 228 switch (DirectoryModel.getRootType(path)) { |
185 case DirectoryModel.RootType.REMOVABLE: | 229 case DirectoryModel.RootType.REMOVABLE: |
186 return !!this.volumeReadOnlyStatus_[DirectoryModel.getRootPath(path)]; | 230 return !!this.volumeReadOnlyStatus_[DirectoryModel.getRootPath(path)]; |
187 case DirectoryModel.RootType.ARCHIVE: | 231 case DirectoryModel.RootType.ARCHIVE: |
188 return true; | 232 return true; |
189 case DirectoryModel.RootType.DOWNLOADS: | 233 case DirectoryModel.RootType.DOWNLOADS: |
190 return false; | 234 return false; |
(...skipping 24 matching lines...) Expand all Loading... |
215 }; | 259 }; |
216 | 260 |
217 /** | 261 /** |
218 * @return {DirectoryEntry} Current directory. | 262 * @return {DirectoryEntry} Current directory. |
219 */ | 263 */ |
220 DirectoryModel.prototype.getCurrentDirEntry = function() { | 264 DirectoryModel.prototype.getCurrentDirEntry = function() { |
221 return this.currentDirEntry_; | 265 return this.currentDirEntry_; |
222 }; | 266 }; |
223 | 267 |
224 /** | 268 /** |
| 269 * If search results are being displayed, returns search directory, else returns |
| 270 * current directory. |
| 271 * |
| 272 * @return {DirectoryEntry} search or directory entry. |
| 273 */ |
| 274 DirectoryModel.prototype.getSearchOrCurrentDirEntry = function() { |
| 275 return this.searchDirEntry_ || this.currentDirEntry_; |
| 276 }; |
| 277 |
| 278 /** |
225 * @return {string} Path for the current directory. | 279 * @return {string} Path for the current directory. |
226 */ | 280 */ |
227 DirectoryModel.prototype.getCurrentDirPath = function() { | 281 DirectoryModel.prototype.getCurrentDirPath = function() { |
228 return this.currentDirEntry_.fullPath; | 282 return this.currentDirEntry_.fullPath; |
229 }; | 283 }; |
230 | 284 |
231 /** | 285 /** |
232 * @private | 286 * @private |
233 * @return {Array.<string>} Names of selected files. | 287 * @return {Array.<string>} Names of selected files. |
234 */ | 288 */ |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 DirectoryModel.prototype.addFilter = function(name, filter) { | 383 DirectoryModel.prototype.addFilter = function(name, filter) { |
330 this.filters_[name] = filter; | 384 this.filters_[name] = filter; |
331 this.rescanSoon(); | 385 this.rescanSoon(); |
332 }; | 386 }; |
333 | 387 |
334 /** | 388 /** |
335 * Remove one of the directory contents filters, specified by name. | 389 * Remove one of the directory contents filters, specified by name. |
336 * @param {string} name Identifier of a filter. | 390 * @param {string} name Identifier of a filter. |
337 */ | 391 */ |
338 DirectoryModel.prototype.removeFilter = function(name) { | 392 DirectoryModel.prototype.removeFilter = function(name) { |
339 delete this.filters_[name]; | 393 if (this.filters_[name]) |
| 394 delete this.filters_[name]; |
340 this.rescanSoon(); | 395 this.rescanSoon(); |
341 }; | 396 }; |
342 | 397 |
343 /** | 398 /** |
344 * Schedule rescan with short delay. | 399 * Schedule rescan with short delay. |
345 */ | 400 */ |
346 DirectoryModel.prototype.rescanSoon = function() { | 401 DirectoryModel.prototype.rescanSoon = function() { |
347 this.scheduleRescan(SHORT_RESCAN_INTERVAL); | 402 this.scheduleRescan(SHORT_RESCAN_INTERVAL); |
348 }; | 403 }; |
349 | 404 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 } | 474 } |
420 } | 475 } |
421 | 476 |
422 function onFailure() { | 477 function onFailure() { |
423 self.scanFailures_++; | 478 self.scanFailures_++; |
424 if (self.scanFailures_ <= 1) | 479 if (self.scanFailures_ <= 1) |
425 self.rescanLater(); | 480 self.rescanLater(); |
426 } | 481 } |
427 | 482 |
428 return new DirectoryModel.Scanner( | 483 return new DirectoryModel.Scanner( |
429 this.currentDirEntry_, | 484 this.getSearchOrCurrentDirEntry(), |
430 list, | 485 list, |
431 onSuccess, | 486 onSuccess, |
432 onFailure, | 487 onFailure, |
433 this.prefetchCacheForSorting_.bind(this), | 488 this.prefetchCacheForSorting_.bind(this), |
434 this.filters_); | 489 this.filters_); |
435 }; | 490 }; |
436 | 491 |
437 /** | 492 /** |
438 * @private | 493 * @private |
439 * @param {Array.<Entry>} entries List of files. | 494 * @param {Array.<Entry>} entries List of files. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 callback) { | 561 callback) { |
507 var field = this.fileList_.sortStatus.field; | 562 var field = this.fileList_.sortStatus.field; |
508 if (field) { | 563 if (field) { |
509 this.prepareSortEntries_(entries, field, callback); | 564 this.prepareSortEntries_(entries, field, callback); |
510 } else { | 565 } else { |
511 callback(); | 566 callback(); |
512 } | 567 } |
513 }; | 568 }; |
514 | 569 |
515 /** | 570 /** |
| 571 * Gets name that should be displayed in the UI for the entry. |
| 572 * @param {string} path Full path of the entry whose display name we are |
| 573 * getting. |
| 574 * @param {string} defaultName Default name to use if no name is calculated. |
| 575 * @return {string} Name to be used for display. |
| 576 */ |
| 577 DirectoryModel.prototype.getDisplayName = function(path, defaultName) { |
| 578 var searchResultName = util.getFileAndDisplayNameForGDataSearchResult(path); |
| 579 return searchResultName ? searchResultName.displayName : defaultName; |
| 580 }; |
| 581 |
| 582 /** |
| 583 * Creates file name that should be used as a new file name in filesystem |
| 584 * operations while renaming. If the given entry is not a gdata search result |
| 585 * entry, |displayName| will be used. |
| 586 * |
| 587 * @private |
| 588 * @param {Entry} entry Entry which is being renamed. |
| 589 * @param {string} displayName The new file name provided by user. |
| 590 * @return {string} File name that should be used in renaming filesystem |
| 591 * operations. |
| 592 */ |
| 593 DirectoryModel.prototype.getEntryNameForRename_ = function(entry, displayName) { |
| 594 // If we are renaming gdata search result, we'll have to format newName to |
| 595 // use in file system operation like: <resource_id>.<file_name>. |
| 596 var searchResultName = |
| 597 util.getFileAndDisplayNameForGDataSearchResult(entry.fullPath); |
| 598 return searchResultName ? searchResultName.resourceId + '.' + displayName : |
| 599 displayName; |
| 600 }; |
| 601 |
| 602 /** |
516 * Delete the list of files and directories from filesystem and | 603 * Delete the list of files and directories from filesystem and |
517 * update the file list. | 604 * update the file list. |
518 * @param {Array.<Entry>} entries Entries to delete. | 605 * @param {Array.<Entry>} entries Entries to delete. |
519 * @param {function()=} opt_callback Called when finished. | 606 * @param {function()=} opt_callback Called when finished. |
520 */ | 607 */ |
521 DirectoryModel.prototype.deleteEntries = function(entries, opt_callback) { | 608 DirectoryModel.prototype.deleteEntries = function(entries, opt_callback) { |
522 var downcount = entries.length + 1; | 609 var downcount = entries.length + 1; |
523 | 610 |
524 var onComplete = opt_callback ? function() { | 611 var onComplete = opt_callback ? function() { |
525 if (--downcount == 0) | 612 if (--downcount == 0) |
(...skipping 16 matching lines...) Expand all Loading... |
542 onSuccess, | 629 onSuccess, |
543 util.flog('Error deleting ' + entry.fullPath, onComplete)); | 630 util.flog('Error deleting ' + entry.fullPath, onComplete)); |
544 } | 631 } |
545 onComplete(); | 632 onComplete(); |
546 }; | 633 }; |
547 | 634 |
548 /** | 635 /** |
549 * @param {string} name Filename. | 636 * @param {string} name Filename. |
550 */ | 637 */ |
551 DirectoryModel.prototype.onEntryChanged = function(name) { | 638 DirectoryModel.prototype.onEntryChanged = function(name) { |
552 var currentEntry = this.currentDirEntry_; | 639 var currentEntry = this.getSearchOrCurrentDirEntry(); |
| 640 if (currentEntry != this.currentDirEntry_) |
| 641 return; |
553 var dm = this.fileList_; | 642 var dm = this.fileList_; |
554 var self = this; | 643 var self = this; |
555 | 644 |
556 function onEntryFound(entry) { | 645 function onEntryFound(entry) { |
| 646 // Do nothing if current directory changed during async operations. |
| 647 if (self.getSearchOrCurrentDirEntry() != currentEntry) |
| 648 return; |
557 self.prefetchCacheForSorting_([entry], function() { | 649 self.prefetchCacheForSorting_([entry], function() { |
558 // Do nothing if current directory changed during async operations. | 650 // Do nothing if current directory changed during async operations. |
559 if (self.currentDirEntry_ != currentEntry) | 651 if (self.getSearchOrCurrentDirEntry() != currentEntry) |
560 return; | 652 return; |
561 | 653 |
562 var index = self.findIndexByName_(name); | 654 var index = self.findIndexByName_(name); |
563 if (index >= 0) | 655 if (index >= 0) |
564 dm.splice(index, 1, entry); | 656 dm.splice(index, 1, entry); |
565 else | 657 else |
566 dm.splice(dm.length, 0, entry); | 658 dm.splice(dm.length, 0, entry); |
567 }); | 659 }); |
568 }; | 660 }; |
569 | 661 |
570 function onError(err) { | 662 function onError(err) { |
571 // Do nothing if current directory changed during async operations. | 663 // Do nothing if current directory changed during async operations. |
572 if (self.currentDirEntry_ != currentEntry) | 664 if (self.currentDirEntry_ != currentEntry) |
573 return; | 665 return; |
574 if (err.code != FileError.NOT_FOUND_ERR) { | 666 if (err.code != FileError.NOT_FOUND_ERR) { |
575 self.rescanLater(); | 667 self.rescanLater(); |
576 return; | 668 return; |
577 } | 669 } |
578 | 670 |
579 var index = self.findIndexByName_(name); | 671 var index = self.findIndexByName_(name); |
580 if (index >= 0) | 672 if (index >= 0) |
581 dm.splice(index, 1); | 673 dm.splice(index, 1); |
582 }; | 674 }; |
583 | 675 |
584 util.resolvePath(this.currentDirEntry_, name, onEntryFound, onError); | 676 util.resolvePath(currentEntry, name, onEntryFound, onError); |
585 }; | 677 }; |
586 | 678 |
587 /** | 679 /** |
588 * @private | 680 * @private |
589 * @param {string} name Filename. | 681 * @param {string} name Filename. |
590 * @return {number} The index in the fileList. | 682 * @return {number} The index in the fileList. |
591 */ | 683 */ |
592 DirectoryModel.prototype.findIndexByName_ = function(name) { | 684 DirectoryModel.prototype.findIndexByName_ = function(name) { |
593 var dm = this.fileList_; | 685 var dm = this.fileList_; |
594 for (var i = 0; i < dm.length; i++) | 686 for (var i = 0; i < dm.length; i++) |
595 if (dm.item(i).name == name) | 687 if (dm.item(i).name == name) |
596 return i; | 688 return i; |
597 return -1; | 689 return -1; |
598 }; | 690 }; |
599 | 691 |
600 /** | 692 /** |
601 * Rename the entry in the filesystem and update the file list. | 693 * Rename the entry in the filesystem and update the file list. |
602 * @param {Entry} entry Entry to rename. | 694 * @param {Entry} entry Entry to rename. |
603 * @param {string} newName New name. | 695 * @param {string} newDisplayName New name. |
604 * @param {function} errorCallback Called on error. | 696 * @param {function} errorCallback Called on error. |
605 * @param {function} opt_successCallback Called on success. | 697 * @param {function} opt_successCallback Called on success. |
606 */ | 698 */ |
607 DirectoryModel.prototype.renameEntry = function(entry, newName, errorCallback, | 699 DirectoryModel.prototype.renameEntry = function(entry, newDisplayName, |
| 700 errorCallback, |
608 opt_successCallback) { | 701 opt_successCallback) { |
609 var self = this; | 702 var self = this; |
610 function onSuccess(newEntry) { | 703 function onSuccess(newEntry) { |
611 self.prefetchCacheForSorting_([newEntry], function() { | 704 self.prefetchCacheForSorting_([newEntry], function() { |
612 var fileList = self.fileList_; | 705 var fileList = self.fileList_; |
613 var index = fileList.indexOf(entry); | 706 var index = fileList.indexOf(entry); |
614 if (index >= 0) | 707 if (index >= 0) |
615 fileList.splice(index, 1, newEntry); | 708 fileList.splice(index, 1, newEntry); |
616 self.selectEntry(newName); | 709 self.selectEntry(newEntry.name); |
617 // If the entry doesn't exist in the list it mean that it updated from | 710 // If the entry doesn't exist in the list it mean that it updated from |
618 // outside (probably by directory rescan). | 711 // outside (probably by directory rescan). |
619 if (opt_successCallback) | 712 if (opt_successCallback) |
620 opt_successCallback(); | 713 opt_successCallback(); |
621 }); | 714 }); |
622 } | 715 } |
623 entry.moveTo(this.currentDirEntry_, newName, onSuccess, errorCallback); | 716 |
| 717 var newEntryName = this.getEntryNameForRename_(entry, newDisplayName); |
| 718 entry.moveTo(this.getSearchOrCurrentDirEntry(), newEntryName, onSuccess, |
| 719 errorCallback); |
624 }; | 720 }; |
625 | 721 |
626 /** | 722 /** |
627 * Checks if current directory contains a file or directory with this name. | 723 * Checks if current directory contains a file or directory with this name. |
628 * @param {string} newName Name to check. | 724 * @param {string} entry Entry to which newName will be given. |
| 725 * @param {string} displayName Name to check. |
629 * @param {function(boolean, boolean?)} callback Called when the result's | 726 * @param {function(boolean, boolean?)} callback Called when the result's |
630 * available. First parameter is true if the entry exists and second | 727 * available. First parameter is true if the entry exists and second |
631 * is true if it's a file. | 728 * is true if it's a file. |
632 */ | 729 */ |
633 DirectoryModel.prototype.doesExist = function(newName, callback) { | 730 DirectoryModel.prototype.doesExist = function(entry, displayName, callback) { |
634 util.resolvePath(this.currentDirEntry_, newName, | 731 var entryName = this.getEntryNameForRename_(entry, displayName); |
| 732 |
| 733 util.resolvePath(this.getSearchOrCurrentDirEntry(), entryName, |
635 function(entry) { | 734 function(entry) { |
636 callback(true, entry.isFile); | 735 callback(true, entry.isFile); |
637 }, | 736 }, |
638 callback.bind(window, false)); | 737 callback.bind(window, false)); |
639 }; | 738 }; |
640 | 739 |
641 /** | 740 /** |
642 * Creates directory and updates the file list. | 741 * Creates directory and updates the file list. |
643 * | 742 * |
644 * @param {string} name Directory name. | 743 * @param {string} name Directory name. |
(...skipping 25 matching lines...) Expand all Loading... |
670 this.currentDirEntry_.getDirectory(name, {create: true, exclusive: true}, | 769 this.currentDirEntry_.getDirectory(name, {create: true, exclusive: true}, |
671 onSuccess, errorCallback); | 770 onSuccess, errorCallback); |
672 }; | 771 }; |
673 | 772 |
674 /** | 773 /** |
675 * Changes directory. Causes 'directory-change' event. | 774 * Changes directory. Causes 'directory-change' event. |
676 * | 775 * |
677 * @param {string} path New current directory path. | 776 * @param {string} path New current directory path. |
678 */ | 777 */ |
679 DirectoryModel.prototype.changeDirectory = function(path) { | 778 DirectoryModel.prototype.changeDirectory = function(path) { |
680 this.resolveDirectory(path, function(directoryEntry) { | 779 var targetPath = path; |
| 780 // We should not be changing directory to gdata search path. If we do, default |
| 781 // to gdata root. |
| 782 if (DirectoryModel.isGDataSearchPath(path)) { |
| 783 console.error('Attempt to change directory to search path.'); |
| 784 targetPath = '/' + DirectoryModel.GDATA_DIRECTORY; |
| 785 } |
| 786 |
| 787 this.resolveDirectory(targetPath, function(directoryEntry) { |
681 this.changeDirectoryEntry_(false, directoryEntry); | 788 this.changeDirectoryEntry_(false, directoryEntry); |
682 }.bind(this), function(error) { | 789 }.bind(this), function(error) { |
683 console.error('Error changing directory to ' + path + ': ', error); | 790 console.error('Error changing directory to ' + path + ': ', error); |
684 }); | 791 }); |
685 }; | 792 }; |
686 | 793 |
687 /** | 794 /** |
688 * Resolves absolute directory path. Handles GData stub. | 795 * Resolves absolute directory path. Handles GData stub. |
689 * @param {string} path Path to the directory. | 796 * @param {string} path Path to the directory. |
690 * @param {function(DirectoryEntry} successCallback Success callback. | 797 * @param {function(DirectoryEntry} successCallback Success callback. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
752 * changed. | 859 * changed. |
753 * | 860 * |
754 * @private | 861 * @private |
755 * @param {boolean} initial True if it comes from setupPath and | 862 * @param {boolean} initial True if it comes from setupPath and |
756 * false if caused by an user action. | 863 * false if caused by an user action. |
757 * @param {DirectoryEntry} dirEntry The absolute path to the new directory. | 864 * @param {DirectoryEntry} dirEntry The absolute path to the new directory. |
758 * @param {function} opt_callback Executed if the directory loads successfully. | 865 * @param {function} opt_callback Executed if the directory loads successfully. |
759 */ | 866 */ |
760 DirectoryModel.prototype.changeDirectoryEntry_ = function(initial, dirEntry, | 867 DirectoryModel.prototype.changeDirectoryEntry_ = function(initial, dirEntry, |
761 opt_callback) { | 868 opt_callback) { |
| 869 this.clearSearch_(); |
762 var previous = this.currentDirEntry_; | 870 var previous = this.currentDirEntry_; |
763 this.currentDirEntry_ = dirEntry; | 871 this.currentDirEntry_ = dirEntry; |
764 function onRescanComplete() { | 872 function onRescanComplete() { |
765 if (opt_callback) | 873 if (opt_callback) |
766 opt_callback(); | 874 opt_callback(); |
767 // For tests that open the dialog to empty directories, everything | 875 // For tests that open the dialog to empty directories, everything |
768 // is loaded at this point. | 876 // is loaded at this point. |
769 chrome.test.sendMessage('directory-change-complete'); | 877 chrome.test.sendMessage('directory-change-complete'); |
770 } | 878 } |
771 this.updateRootsListSelection_(); | 879 this.updateRootsListSelection_(); |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1128 /** | 1236 /** |
1129 * @param {string} path Path | 1237 * @param {string} path Path |
1130 * @return {boolean} If current directory is system. | 1238 * @return {boolean} If current directory is system. |
1131 */ | 1239 */ |
1132 DirectoryModel.isSystemDirectory = function(path) { | 1240 DirectoryModel.isSystemDirectory = function(path) { |
1133 return path == '/' + DirectoryModel.REMOVABLE_DIRECTORY || | 1241 return path == '/' + DirectoryModel.REMOVABLE_DIRECTORY || |
1134 path == '/' + DirectoryModel.ARCHIVE_DIRECTORY; | 1242 path == '/' + DirectoryModel.ARCHIVE_DIRECTORY; |
1135 }; | 1243 }; |
1136 | 1244 |
1137 /** | 1245 /** |
| 1246 * Performs search and displays results. The search type is dependent on the |
| 1247 * current directory. If we are currently on gdata, server side content search |
| 1248 * over gdata mount point. If the current directory is not on the gdata, file |
| 1249 * name search over current directory wil be performed. |
| 1250 * |
| 1251 * @param {string} query Query that will be searched for. |
| 1252 * @param {function} onSearchRescan Function that will be called when the search |
| 1253 * directory is rescanned (i.e. search results are displayed) |
| 1254 * @param {function} onClearSearch Function to be called when search state gets |
| 1255 * cleared. |
| 1256 */ |
| 1257 DirectoryModel.prototype.search = function(query, |
| 1258 onSearchRescan, |
| 1259 onClearSearch) { |
| 1260 if (!query) { |
| 1261 if (this.isSearching_) |
| 1262 this.clearSearch_(); |
| 1263 return; |
| 1264 } |
| 1265 |
| 1266 this.isSearching_ = true; |
| 1267 |
| 1268 // If we alreaqdy have event listener for an old search, we have to remove it. |
| 1269 if (this.onSearchRescan_) |
| 1270 this.removeEventListener('rescan-completed', this.onSearchRescan_); |
| 1271 |
| 1272 this.onSearchRescan_ = onSearchRescan; |
| 1273 this.onClearSearch_ = onClearSearch; |
| 1274 |
| 1275 this.addEventListener('rescan-completed', this.onSearchRescan_); |
| 1276 |
| 1277 // If we are offline, let's fallback to file name search inside dir. |
| 1278 if (this.getRootType() == DirectoryModel.RootType.GDATA && |
| 1279 !this.isOffline()) { |
| 1280 var self = this; |
| 1281 // Create shadow directory which will contain search results. |
| 1282 this.root_.getDirectory(DirectoryModel.createGDataSearchPath(query), |
| 1283 {create: false}, |
| 1284 function(dir) { |
| 1285 self.searchDirEntry_ = dir; |
| 1286 self.rescanSoon(); |
| 1287 }, |
| 1288 function() { |
| 1289 self.isSearching_ = false; |
| 1290 }); |
| 1291 } else { |
| 1292 var queryLC = query.toLowerCase(); |
| 1293 this.searchDirEntry_ = this.currentDirEntry_; |
| 1294 this.addFilter( |
| 1295 'searchbox', |
| 1296 function(e) { |
| 1297 return e.name.toLowerCase().indexOf(queryLC) > -1; |
| 1298 }); |
| 1299 } |
| 1300 }; |
| 1301 |
| 1302 |
| 1303 /** |
| 1304 * Clears any state set by previous searches. |
| 1305 * @private |
| 1306 */ |
| 1307 DirectoryModel.prototype.clearSearch_ = function() { |
| 1308 if (!this.isSearching_) |
| 1309 return; |
| 1310 this.searchDirEntry_ = null; |
| 1311 this.isSearching_ = false; |
| 1312 // This will trigger rescan. |
| 1313 this.removeFilter('searchbox'); |
| 1314 |
| 1315 if (this.onSearchRescan_) { |
| 1316 this.removeEventListener('rescan-completed', this.onSearchRescan_); |
| 1317 this.onSearchRescan_ = null; |
| 1318 } |
| 1319 |
| 1320 if (this.onClearSearch_) { |
| 1321 this.onClearSearch_(); |
| 1322 this.onClearSearch_ = null; |
| 1323 } |
| 1324 }; |
| 1325 |
| 1326 /** |
1138 * @param {string} path Any path. | 1327 * @param {string} path Any path. |
1139 * @return {string} The root path. | 1328 * @return {string} The root path. |
1140 */ | 1329 */ |
1141 DirectoryModel.getRootPath = function(path) { | 1330 DirectoryModel.getRootPath = function(path) { |
1142 var type = DirectoryModel.getRootType(path); | 1331 var type = DirectoryModel.getRootType(path); |
1143 | 1332 |
1144 if (type == DirectoryModel.RootType.DOWNLOADS) | 1333 if (type == DirectoryModel.RootType.DOWNLOADS) |
1145 return '/' + DirectoryModel.DOWNLOADS_DIRECTORY; | 1334 return '/' + DirectoryModel.DOWNLOADS_DIRECTORY; |
1146 if (type == DirectoryModel.RootType.GDATA) | 1335 if (type == DirectoryModel.RootType.GDATA) |
1147 return '/' + DirectoryModel.GDATA_DIRECTORY; | 1336 return '/' + DirectoryModel.GDATA_DIRECTORY; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1192 * @param {string} path A path. | 1381 * @param {string} path A path. |
1193 * @return {boolean} True if it is a path to the root. | 1382 * @return {boolean} True if it is a path to the root. |
1194 */ | 1383 */ |
1195 DirectoryModel.isRootPath = function(path) { | 1384 DirectoryModel.isRootPath = function(path) { |
1196 if (path[path.length - 1] == '/') | 1385 if (path[path.length - 1] == '/') |
1197 path = path.substring(0, path.length - 1); | 1386 path = path.substring(0, path.length - 1); |
1198 return DirectoryModel.getRootPath(path) == path; | 1387 return DirectoryModel.getRootPath(path) == path; |
1199 }; | 1388 }; |
1200 | 1389 |
1201 /** | 1390 /** |
| 1391 * Checks if the provided path is under gdata search. |
| 1392 * |
| 1393 * @param {string} path Path to be tested. |
| 1394 * @return {boolean} Is the path gdata search path. |
| 1395 */ |
| 1396 DirectoryModel.isGDataSearchPath = function(path) { |
| 1397 return path == DirectoryModel.GDATA_SEARCH_ROOT_PATH || |
| 1398 path.indexOf(DirectoryModel.GDATA_SEARCH_ROOT_PATH + '/') == 0; |
| 1399 }; |
| 1400 |
| 1401 /** |
| 1402 * Creates directory path in which gdata content search results for |query| |
| 1403 * should be displayed. |
| 1404 * |
| 1405 * @param {string} query Search query. |
| 1406 * @return {string} Virtual directory path for search results. |
| 1407 */ |
| 1408 DirectoryModel.createGDataSearchPath = function(query) { |
| 1409 return DirectoryModel.GDATA_SEARCH_ROOT_PATH + '/' + query; |
| 1410 }; |
| 1411 |
| 1412 /** |
1202 * @constructor | 1413 * @constructor |
1203 * @extends cr.EventTarget | 1414 * @extends cr.EventTarget |
1204 * @param {DirectoryEntry} dir Directory to scan. | 1415 * @param {DirectoryEntry} dir Directory to scan. |
1205 * @param {Array.<Entry>|cr.ui.ArrayDataModel} list Target to put the files. | 1416 * @param {Array.<Entry>|cr.ui.ArrayDataModel} list Target to put the files. |
1206 * @param {function} successCallback Callback to call when (and if) scan | 1417 * @param {function} successCallback Callback to call when (and if) scan |
1207 * successfully completed. | 1418 * successfully completed. |
1208 * @param {function} errorCallback Callback to call in case of IO error. | 1419 * @param {function} errorCallback Callback to call in case of IO error. |
1209 * @param {function(Array.<Entry>):void, Function)} preprocessChunk | 1420 * @param {function(Array.<Entry>):void, Function)} preprocessChunk |
1210 * Callback to preprocess each chunk of files. | 1421 * Callback to preprocess each chunk of files. |
1211 * @param {Object.<string, function(Entry):Boolean>} filters The map of filters | 1422 * @param {Object.<string, function(Entry):Boolean>} filters The map of filters |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1288 /** | 1499 /** |
1289 * @private | 1500 * @private |
1290 */ | 1501 */ |
1291 DirectoryModel.Scanner.prototype.recordMetrics_ = function() { | 1502 DirectoryModel.Scanner.prototype.recordMetrics_ = function() { |
1292 metrics.recordInterval('DirectoryScan'); | 1503 metrics.recordInterval('DirectoryScan'); |
1293 if (this.dir_.fullPath == | 1504 if (this.dir_.fullPath == |
1294 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) { | 1505 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) { |
1295 metrics.recordMediumCount('DownloadsCount', this.list_.length); | 1506 metrics.recordMediumCount('DownloadsCount', this.list_.length); |
1296 } | 1507 } |
1297 }; | 1508 }; |
OLD | NEW |