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

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

Issue 9855024: Postpone connecting to GData even more, provide progress indication. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Showing progress when opening File Manager on a GData path Created 8 years, 9 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
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 const SIMULTANEOUS_RESCAN_INTERVAL = 1000; 7 const SIMULTANEOUS_RESCAN_INTERVAL = 1000;
8 8
9 /** 9 /**
10 * Data model of the file manager. 10 * Data model of the file manager.
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 }, 561 },
562 562
563 /** 563 /**
564 * Change the state of the model to reflect the specified path (either a 564 * Change the state of the model to reflect the specified path (either a
565 * file or directory). 565 * file or directory).
566 * 566 *
567 * @param {string} path The root path to use 567 * @param {string} path The root path to use
568 * @param {Function=} opt_loadedCallback Invoked when the entire directory 568 * @param {Function=} opt_loadedCallback Invoked when the entire directory
569 * has been loaded and any default file selected. If there are any 569 * has been loaded and any default file selected. If there are any
570 * errors loading the directory this will not get called (even if the 570 * errors loading the directory this will not get called (even if the
571 * directory loads OK on retry later). 571 * directory loads OK on retry later). Will NOT be called if another
572 * directory change happened while setupPath was in progress.
572 * @param {Function=} opt_pathResolveCallback Invoked as soon as the path has 573 * @param {Function=} opt_pathResolveCallback Invoked as soon as the path has
573 * been resolved, and called with the base and leaf portions of the path 574 * been resolved, and called with the base and leaf portions of the path
574 * name, and a flag indicating if the entry exists. 575 * name, and a flag indicating if the entry exists. Will be called even
576 * if another directory change happened while setupPath was in progress,
577 * but will pass |false| as |exist| parameter.
575 */ 578 */
576 setupPath: function(path, opt_loadedCallback, opt_pathResolveCallback) { 579 setupPath: function(path, opt_loadedCallback, opt_pathResolveCallback) {
580 var overridden = false;
581 function onExternalDirChange() { overridden = true }
582 this.addEventListener('directory-changed', onExternalDirChange);
583
584 var resolveCallback = function(exists) {
585 this.removeEventListener('directory-changed', onExternalDirChange);
586 if (opt_pathResolveCallback)
587 opt_pathResolveCallback(baseName, leafName, exists && !overridden);
dgozman 2012/03/28 10:28:30 Why do we call this in the case of overridden?
Vladislav Kaznacheev 2012/03/28 14:00:57 Because the client might have to do some cleanup (
588 }.bind(this);
589
590 var changeDirectoryEntry = function (entry, callback, initial, exists) {
dgozman 2012/03/28 10:28:30 space before (
Vladislav Kaznacheev 2012/03/28 14:00:57 Done.
591 resolveCallback(exists);
592 if (!overridden)
593 this.changeDirectoryEntry_(entry, callback, initial);
594 }.bind(this);
595
596 var INITIAL = true;
597 var EXISTS = true;
598
577 // Split the dirname from the basename. 599 // Split the dirname from the basename.
578 var ary = path.match(/^(?:(.*)\/)?([^\/]*)$/); 600 var ary = path.match(/^(?:(.*)\/)?([^\/]*)$/);
579 var autoSelect = function() { 601 var autoSelect = function() {
580 this.selectIndex(this.autoSelectIndex_); 602 this.selectIndex(this.autoSelectIndex_);
581 if (opt_loadedCallback) 603 if (opt_loadedCallback)
582 opt_loadedCallback(); 604 opt_loadedCallback();
583 }.bind(this); 605 }.bind(this);
584 606
585 if (!ary) { 607 if (!ary) {
586 console.warn('Unable to split default path: ' + path); 608 console.warn('Unable to split default path: ' + path);
587 this.changeDirectoryEntry_(this.root_, autoSelect, true); 609 changeDirectoryEntry(this.root_, autoSelect, INITIAL, !EXISTS);
dgozman 2012/03/28 10:28:30 resolveCallback was not called here before. Bug?
Vladislav Kaznacheev 2012/03/28 14:00:57 Yes, it was a but (there was another one in onBase
588 return; 610 return;
589 } 611 }
590 612
591 var baseName = ary[1]; 613 var baseName = ary[1];
592 var leafName = ary[2]; 614 var leafName = ary[2];
593 615
594 function resolveCallback(exists) {
595 if (opt_pathResolveCallback)
596 opt_pathResolveCallback(baseName, leafName, exists);
597 }
598
599 function onLeafFound(baseDirEntry, leafEntry) { 616 function onLeafFound(baseDirEntry, leafEntry) {
600 if (leafEntry.isDirectory) { 617 if (leafEntry.isDirectory) {
601 baseName = path; 618 baseName = path;
602 leafName = ''; 619 leafName = '';
603 resolveCallback(true); 620 changeDirectoryEntry(leafEntry, autoSelect, INITIAL, EXISTS);
604 this.changeDirectoryEntry_(leafEntry, autoSelect, true);
605 return; 621 return;
606 } 622 }
607 623
608 resolveCallback(true);
609 // Leaf is an existing file, cd to its parent directory and select it. 624 // Leaf is an existing file, cd to its parent directory and select it.
610 this.changeDirectoryEntry_(baseDirEntry, 625 changeDirectoryEntry(baseDirEntry,
611 function() { 626 function() {
612 this.selectEntry(leafEntry.name); 627 this.selectEntry(leafEntry.name);
613 if (opt_loadedCallback) 628 if (opt_loadedCallback)
614 opt_loadedCallback(); 629 opt_loadedCallback();
615 }.bind(this), 630 }.bind(this),
616 false /*HACK*/); 631 !INITIAL /*HACK*/,
632 EXISTS);
617 // TODO(kaznacheev): Fix history.replaceState for the File Browser and 633 // TODO(kaznacheev): Fix history.replaceState for the File Browser and
618 // change the last parameter back to |true|. Passing |false| makes things 634 // change !INITIAL to INITIAL. Passing |false| makes things
619 // less ugly for now. 635 // less ugly for now.
620 } 636 }
621 637
622 function onLeafError(baseDirEntry, err) { 638 function onLeafError(baseDirEntry, err) {
623 resolveCallback(false);
624 // Usually, leaf does not exist, because it's just a suggested file name. 639 // Usually, leaf does not exist, because it's just a suggested file name.
625 if (err.code != FileError.NOT_FOUND_ERR) 640 if (err.code != FileError.NOT_FOUND_ERR)
626 console.log('Unexpected error resolving default leaf: ' + err); 641 console.log('Unexpected error resolving default leaf: ' + err);
627 this.changeDirectoryEntry_(baseDirEntry, autoSelect, true); 642 changeDirectoryEntry(baseDirEntry, autoSelect, INITIAL, !EXISTS);
628 } 643 }
629 644
630 var onBaseError = function(err) { 645 var onBaseError = function(err) {
631 resolveCallback(false);
632 console.log('Unexpected error resolving default base "' + 646 console.log('Unexpected error resolving default base "' +
633 baseName + '": ' + err); 647 baseName + '": ' + err);
634 if (path != '/' + DirectoryModel.DOWNLOADS_DIRECTORY) { 648 if (path != '/' + DirectoryModel.DOWNLOADS_DIRECTORY) {
635 // Can't find the provided path, let's go to default one instead. 649 // Can't find the provided path, let's go to default one instead.
636 this.setupDefaultPath(opt_loadedCallback); 650 resolveCallback(!EXISTS);
651 if (!overridden)
652 this.setupDefaultPath(opt_loadedCallback);
637 } else { 653 } else {
638 // Well, we can't find the downloads dir. Let's just show something, 654 // Well, we can't find the downloads dir. Let's just show something,
639 // or we will get an infinite recursion. 655 // or we will get an infinite recursion.
640 this.changeDirectoryEntry_(this.root_, opt_loadedCallback, true); 656 changeDirectoryEntry(this.root_, opt_loadedCallback, INITIAL, !EXISTS);
641 } 657 }
642 }.bind(this); 658 }.bind(this);
643 659
644 var onBaseFound = function(baseDirEntry) { 660 var onBaseFound = function(baseDirEntry) {
645 if (!leafName) { 661 if (!leafName) {
646 // Default path is just a directory, cd to it and we're done. 662 // Default path is just a directory, cd to it and we're done.
647 this.changeDirectoryEntry_(baseDirEntry, autoSelect, true); 663 changeDirectoryEntry(baseDirEntry, autoSelect, INITIAL, !EXISTS);
648 return; 664 return;
649 } 665 }
650 666
651 util.resolvePath(this.root_, path, 667 util.resolvePath(this.root_, path,
652 onLeafFound.bind(this, baseDirEntry), 668 onLeafFound.bind(this, baseDirEntry),
653 onLeafError.bind(this, baseDirEntry)); 669 onLeafError.bind(this, baseDirEntry));
654 }.bind(this); 670 }.bind(this);
655 671
656 var root = this.root_; 672 var root = this.root_;
657 if (baseName) { 673 if (baseName) {
658 root.getDirectory( 674 root.getDirectory(
659 baseName, {create: false}, onBaseFound, onBaseError); 675 baseName, {create: false}, onBaseFound, onBaseError);
660 } else { 676 } else {
661 this.getDefaultDirectory_(function(defaultDir) { 677 this.getDefaultDirectory_(function(defaultDir) {
662 baseName = defaultDir; 678 baseName = defaultDir;
663 root.getDirectory( 679 root.getDirectory(
664 baseName, {create: false}, onBaseFound, onBaseError); 680 baseName, {create: false}, onBaseFound, onBaseError);
665 }); 681 });
666 } 682 }
667 }, 683 },
668 684
669 setupDefaultPath: function(opt_callback) { 685 setupDefaultPath: function(opt_callback) {
686 var overridden = false;
687 function onExternalDirChange() { overridden = true }
688 this.addEventListener('directory-changed', onExternalDirChange);
689
670 this.getDefaultDirectory_(function(path) { 690 this.getDefaultDirectory_(function(path) {
671 this.setupPath(path, opt_callback); 691 this.removeEventListener('directory-changed', onExternalDirChange);
692 if (!overridden)
693 this.setupPath(path, opt_callback);
672 }.bind(this)); 694 }.bind(this));
673 }, 695 },
674 696
675 getDefaultDirectory_: function(callback) { 697 getDefaultDirectory_: function(callback) {
676 function onGetDirectoryComplete(entries, error) { 698 function onGetDirectoryComplete(entries, error) {
677 if (entries.length > 0) 699 if (entries.length > 0)
678 callback(entries[0].fullPath); 700 callback(entries[0].fullPath);
679 else 701 else
680 callback('/' + DirectoryModel.DOWNLOADS_DIRECTORY); 702 callback('/' + DirectoryModel.DOWNLOADS_DIRECTORY);
681 } 703 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 function onCacheDone() { 769 function onCacheDone() {
748 waitCount--; 770 waitCount--;
749 // If all caching functions finished synchronously or entries.length = 0 771 // If all caching functions finished synchronously or entries.length = 0
750 // call the callback synchronously. 772 // call the callback synchronously.
751 if (waitCount == 0) 773 if (waitCount == 0)
752 setTimeout(callback, 0); 774 setTimeout(callback, 0);
753 } 775 }
754 }, 776 },
755 777
756 /** 778 /**
757 * Get root entries asynchronously. Invokes callback 779 * Get root entries asynchronously.
758 * when have finished. 780 * @param {function(Array.<Entry>} callback Called when roots are resolved.
781 * @param {boolean} resolveGData See comment for updateRoots.
759 */ 782 */
760 resolveRoots_: function(callback) { 783 resolveRoots_: function(callback, resolveGData) {
761 var groups = { 784 var groups = {
762 downloads: null, 785 downloads: null,
763 archives: null, 786 archives: null,
764 removables: null, 787 removables: null,
765 gdata: null 788 gdata: null
766 }; 789 };
767 790
768 metrics.startInterval('Load.Roots'); 791 metrics.startInterval('Load.Roots');
769 function done() { 792 function done() {
770 for (var i in groups) 793 for (var i in groups)
(...skipping 18 matching lines...) Expand all
789 } 812 }
790 813
791 function onDownloadsError(error) { 814 function onDownloadsError(error) {
792 groups.downloads = []; 815 groups.downloads = [];
793 done(); 816 done();
794 } 817 }
795 818
796 var self = this; 819 var self = this;
797 820
798 function onGData(entry) { 821 function onGData(entry) {
799 console.log('onGData'); 822 console.log('GData found:', entry);
800 console.log(entry);
801 self.unmountedGDataEntry_ = null; 823 self.unmountedGDataEntry_ = null;
802 groups.gdata = [entry]; 824 groups.gdata = [entry];
803 done(); 825 done();
804 } 826 }
805 827
806 function onGDataError(error) { 828 function onGDataError(error) {
807 console.log('onGDataError'); 829 console.log('GData error: ', error);
808 console.log(error);
809 self.unmountedGDataEntry_ = { 830 self.unmountedGDataEntry_ = {
831 unmounted: true, // Clients use this field to distinguish a fake root.
832 toURL: function() { return '' },
810 fullPath: '/' + DirectoryModel.GDATA_DIRECTORY 833 fullPath: '/' + DirectoryModel.GDATA_DIRECTORY
811 }; 834 };
812 groups.gdata = [self.unmountedGDataEntry_]; 835 groups.gdata = [self.unmountedGDataEntry_];
813 done(); 836 done();
814 } 837 }
815 838
816 var root = this.root_; 839 var root = this.root_;
817 root.getDirectory(DirectoryModel.DOWNLOADS_DIRECTORY, { create: false }, 840 root.getDirectory(DirectoryModel.DOWNLOADS_DIRECTORY, { create: false },
818 onDownloads, onDownloadsError); 841 onDownloads, onDownloadsError);
819 util.readDirectory(root, DirectoryModel.ARCHIVE_DIRECTORY, 842 util.readDirectory(root, DirectoryModel.ARCHIVE_DIRECTORY,
820 append.bind(this, 'archives')); 843 append.bind(this, 'archives'));
821 util.readDirectory(root, DirectoryModel.REMOVABLE_DIRECTORY, 844 util.readDirectory(root, DirectoryModel.REMOVABLE_DIRECTORY,
822 append.bind(this, 'removables')); 845 append.bind(this, 'removables'));
823 if (this.showGData_) { 846 if (this.showGData_) {
824 root.getDirectory(DirectoryModel.GDATA_DIRECTORY, { create: false }, 847 if (resolveGData) {
825 onGData, onGDataError); 848 root.getDirectory(DirectoryModel.GDATA_DIRECTORY, { create: false },
849 onGData, onGDataError);
850 } else {
851 onGDataError('lazy mount');
852 }
826 } else { 853 } else {
827 groups.gdata = []; 854 groups.gdata = [];
828 } 855 }
829 }, 856 },
830 857
831 updateRoots: function(opt_callback) { 858 /**
832 console.log('directoryModel_.updateRoots'); 859 * @param {function} opt_callback Called when all roots are resolved.
860 * @param {boolean} opt_resolveGData If true GData should be resolved for real,
861 * If false a stub entry should be created.
862 */
863 updateRoots: function(opt_callback, opt_resolveGData) {
864 console.log('resolving roots');
833 var self = this; 865 var self = this;
834 this.resolveRoots_(function(rootEntries) { 866 this.resolveRoots_(function(rootEntries) {
835 console.log('rootsList_ = '); 867 console.log('resolved roots:', rootEntries);
836 console.log(self.rootsList_);
837 var dm = self.rootsList_; 868 var dm = self.rootsList_;
838 var args = [0, dm.length].concat(rootEntries); 869 var args = [0, dm.length].concat(rootEntries);
839 dm.splice.apply(dm, args); 870 dm.splice.apply(dm, args);
840 871
841 self.updateRootsListSelection_(); 872 self.updateRootsListSelection_();
842 873
843 if (opt_callback) 874 if (opt_callback)
844 opt_callback(); 875 opt_callback();
845 }); 876 }, opt_resolveGData);
846 }, 877 },
847 878
848 onRootsSelectionChanged_: function(event) { 879 onRootsSelectionChanged_: function(event) {
849 var root = this.rootsList.item(this.rootsListSelection.selectedIndex); 880 var root = this.rootsList.item(this.rootsListSelection.selectedIndex);
850 var current = this.currentEntry.fullPath;
851 if (root && this.rootPath != root.fullPath) 881 if (root && this.rootPath != root.fullPath)
852 this.changeDirectory(root.fullPath); 882 this.changeDirectory(root.fullPath);
853 }, 883 },
854 884
855 updateRootsListSelection_: function() { 885 updateRootsListSelection_: function() {
856 var roots = this.rootsList_; 886 var roots = this.rootsList_;
857 var rootPath = this.rootPath; 887 var rootPath = this.rootPath;
858 for (var index = 0; index < roots.length; index++) { 888 for (var index = 0; index < roots.length; index++) {
859 if (roots.item(index).fullPath == rootPath) { 889 if (roots.item(index).fullPath == rootPath) {
860 this.rootsListSelection.selectedIndex = index; 890 this.rootsListSelection.selectedIndex = index;
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 1020
991 recordMetrics_: function() { 1021 recordMetrics_: function() {
992 metrics.recordInterval('DirectoryScan'); 1022 metrics.recordInterval('DirectoryScan');
993 if (this.dir_.fullPath == 1023 if (this.dir_.fullPath ==
994 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) { 1024 '/' + DirectoryModel.DOWNLOADS_DIRECTORY) {
995 metrics.recordMediumCount("DownloadsCount", this.list_.length); 1025 metrics.recordMediumCount("DownloadsCount", this.list_.length);
996 } 1026 }
997 } 1027 }
998 }; 1028 };
999 1029
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698