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

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

Issue 8565009: Improving file manager load time (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge Created 9 years, 1 month 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/main.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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 // Setting the src of an img to an empty string can crash the browser, so we 5 // Setting the src of an img to an empty string can crash the browser, so we
6 // use an empty 1x1 gif instead. 6 // use an empty 1x1 gif instead.
7 const EMPTY_IMAGE_URI = 'data:image/gif;base64,' 7 const EMPTY_IMAGE_URI = 'data:image/gif;base64,'
8 + 'R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D'; 8 + 'R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D';
9 9
10 var g_slideshow_data = null; 10 var g_slideshow_data = null;
11 11
12 const GALLERY_ENABLED = true; 12 const GALLERY_ENABLED = true;
13 13
14 // If directory files changes too often, don't rescan directory more than once 14 // If directory files changes too often, don't rescan directory more than once
15 // per specified interval 15 // per specified interval
16 const SIMULTANEOUS_RESCAN_INTERVAL = 1000; 16 const SIMULTANEOUS_RESCAN_INTERVAL = 1000;
17 17
18 /** 18 /**
19 * FileManager constructor. 19 * FileManager constructor.
20 * 20 *
21 * FileManager objects encapsulate the functionality of the file selector 21 * FileManager objects encapsulate the functionality of the file selector
22 * dialogs, as well as the full screen file manager application (though the 22 * dialogs, as well as the full screen file manager application (though the
23 * latter is not yet implemented). 23 * latter is not yet implemented).
24 * 24 *
25 * @param {HTMLElement} dialogDom The DOM node containing the prototypical 25 * @param {HTMLElement} dialogDom The DOM node containing the prototypical
26 * dialog UI. 26 * dialog UI.
27 * @param {DOMFileSystem} filesystem The HTML5 filesystem object representing 27 * @param {DOMFileSystem} filesystem The HTML5 filesystem object representing
28 * the root filesystem for the new FileManager. 28 * the root filesystem for the new FileManager.
29 * @param {Object} params A map of parameter names to values controlling the
30 * appearance of the FileManager. Names are:
31 * - type: A value from FileManager.DialogType defining what kind of
32 * dialog to present. Defaults to FULL_PAGE.
33 * - title: The title for the dialog. Defaults to a localized string based
34 * on the dialog type.
35 * - defaultPath: The default path for the dialog. The default path should
36 * end with a trailing slash if it represents a directory.
37 */ 29 */
38 function FileManager(dialogDom, filesystem, rootEntries) { 30 function FileManager(dialogDom) {
39 console.log('Init FileManager: ' + dialogDom); 31 console.log('Init FileManager: ' + dialogDom);
40 32
41 this.dialogDom_ = dialogDom; 33 this.dialogDom_ = dialogDom;
42 this.rootEntries_ = rootEntries; 34 this.rootEntries_ = null;
43 this.filesystem_ = filesystem; 35 this.filesystem_ = null;
44 this.params_ = location.search ? 36 this.params_ = location.search ?
45 JSON.parse(decodeURIComponent(location.search.substr(1))) : 37 JSON.parse(decodeURIComponent(location.search.substr(1))) :
46 {}; 38 {};
47 39
48 this.listType_ = null; 40 this.listType_ = null;
49 41
50 this.selection = null; 42 this.selection = null;
51 43
52 this.clipboard_ = null; // Current clipboard, or null if empty. 44 this.clipboard_ = null; // Current clipboard, or null if empty.
53 45
(...skipping 11 matching lines...) Expand all
65 this.document_ = dialogDom.ownerDocument; 57 this.document_ = dialogDom.ownerDocument;
66 this.dialogType_ = this.params_.type || FileManager.DialogType.FULL_PAGE; 58 this.dialogType_ = this.params_.type || FileManager.DialogType.FULL_PAGE;
67 59
68 metrics.recordEnum('Create', this.dialogType_, 60 metrics.recordEnum('Create', this.dialogType_,
69 [FileManager.DialogType.SELECT_FOLDER, 61 [FileManager.DialogType.SELECT_FOLDER,
70 FileManager.DialogType.SELECT_SAVEAS_FILE, 62 FileManager.DialogType.SELECT_SAVEAS_FILE,
71 FileManager.DialogType.SELECT_OPEN_FILE, 63 FileManager.DialogType.SELECT_OPEN_FILE,
72 FileManager.DialogType.SELECT_OPEN_MULTI_FILE, 64 FileManager.DialogType.SELECT_OPEN_MULTI_FILE,
73 FileManager.DialogType.FULL_PAGE]); 65 FileManager.DialogType.FULL_PAGE]);
74 66
75 this.initDialogs_();
76
77 // TODO(dgozman): This will be changed to LocaleInfo. 67 // TODO(dgozman): This will be changed to LocaleInfo.
78 this.locale_ = new v8Locale(navigator.language); 68 this.locale_ = new v8Locale(navigator.language);
79 69
80 // TODO(rginda): 6/22/11: Remove this test when createDateTimeFormat is 70 this.resolveRoots_();
81 // available in all chrome trunk builds.
82 if ('createDateTimeFormat' in this.locale_) {
83 this.shortDateFormatter_ =
84 this.locale_.createDateTimeFormat({'dateType': 'medium'});
85 } else {
86 this.shortDateFormatter_ = {
87 format: function(d) {
88 return (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
89 }
90 };
91 }
92
93 // TODO(rginda): 6/22/11: Remove this test when createCollator is
94 // available in all chrome trunk builds.
95 if ('createCollator' in this.locale_) {
96 this.collator_ = this.locale_.createCollator({
97 'numeric': true, 'ignoreCase': true, 'ignoreAccents': true});
98 } else {
99 this.collator_ = {
100 compare: function(a, b) {
101 if (a > b) return 1;
102 if (a < b) return -1;
103 return 0;
104 }
105 };
106 }
107
108 // Optional list of file types.
109 this.fileTypes_ = this.params_.typeList;
110
111 this.showCheckboxes_ =
112 (this.dialogType_ == FileManager.DialogType.FULL_PAGE ||
113 this.dialogType_ == FileManager.DialogType.SELECT_OPEN_MULTI_FILE);
114
115 // DirectoryEntry representing the current directory of the dialog.
116 this.currentDirEntry_ = null;
117
118 this.copyManager_ = new FileCopyManager();
119 this.copyManager_.addEventListener('copy-progress',
120 this.onCopyProgress_.bind(this));
121
122 window.addEventListener('popstate', this.onPopState_.bind(this));
123 window.addEventListener('unload', this.onUnload_.bind(this));
124
125 this.addEventListener('directory-changed',
126 this.onDirectoryChanged_.bind(this));
127 this.addEventListener('selection-summarized',
128 this.onSelectionSummarized_.bind(this));
129
130 // The list of archives requested to mount. We will show contents once
131 // archive is mounted, but only for mounts from within this filebrowser tab.
132 this.mountRequests_ = [];
133 chrome.fileBrowserPrivate.onMountCompleted.addListener(
134 this.onMountCompleted_.bind(this));
135
136 chrome.fileBrowserPrivate.onFileChanged.addListener(
137 this.onFileChanged_.bind(this));
138
139 var self = this;
140
141 // The list of callbacks to be invoked during the directory rescan after
142 // all paste tasks are complete.
143 this.pasteSuccessCallbacks_ = [];
144
145 // The list of active mount points to distinct them from other directories.
146 chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) {
147 self.mountPoints_ = mountPoints;
148 });
149
150 this.initCommands_();
151 this.initDom_(); 71 this.initDom_();
152 this.initDialogType_(); 72 this.initDialogType_();
153 this.setupCurrentDirectory_(); 73 this.dialogDom_.style.opacity = '1';
154
155 this.summarizeSelection_();
156
157 this.dataModel_.sort('cachedMtime_', 'desc');
158
159 this.refocus();
160
161 this.createMetadataProvider_();
162 } 74 }
163 75
164 FileManager.prototype = { 76 FileManager.prototype = {
165 __proto__: cr.EventTarget.prototype 77 __proto__: cr.EventTarget.prototype
166 }; 78 };
167 79
168 // Anonymous "namespace". 80 // Anonymous "namespace".
169 (function() { 81 (function() {
170 82
171 // Private variables and helper functions. 83 // Private variables and helper functions.
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 chrome.fileBrowserPrivate.getStrings(function(strings) { 462 chrome.fileBrowserPrivate.getStrings(function(strings) {
551 localStrings = new LocalStrings(strings); 463 localStrings = new LocalStrings(strings);
552 if (callback) 464 if (callback)
553 callback(); 465 callback();
554 }); 466 });
555 }; 467 };
556 468
557 // Instance methods. 469 // Instance methods.
558 470
559 /** 471 /**
472 * Request file system and get root entries asynchronously. Invokes init_
473 * when have finished.
474 */
475 FileManager.prototype.resolveRoots_ = function(callback) {
476 var rootPaths = ['Downloads', 'removable', 'archive'];
477
478 metrics.startInterval('RequestLocalFileSystem');
479 var self = this;
480 chrome.fileBrowserPrivate.requestLocalFileSystem(function(filesystem) {
481 self.filesystem_ = filesystem;
482 util.installFileErrorToString();
483
484 metrics.recordTime('RequestLocalFileSystem');
485 console.log('Found filesystem: ' + filesystem.name, filesystem);
486
487 var rootEntries = [];
488
489 function onAllRootsFound() {
490 self.rootEntries_ = rootEntries;
491 self.init_();
492 }
493
494 function onPathError(path, err) {
495 console.error('Error locating root path: ' + path + ': ' + err);
496 }
497
498 function onEntryFound(entry) {
499 if (entry) {
500 rootEntries.push(entry);
501 } else {
502 onAllRootsFound();
503 }
504 }
505
506 metrics.startInterval('EnumerateRoots');
507 if (filesystem.name.match(/^chrome-extension_\S+:external/i)) {
508 // We've been handed the local filesystem, whose root directory
509 // cannot be enumerated.
510 util.getDirectories(filesystem.root, {create: false}, rootPaths,
511 onEntryFound, onPathError);
512 } else {
513 util.forEachDirEntry(filesystem.root, onEntryFound);
514 }
515 });
516 };
517
518 /**
519 * Continue initializing the file manager after resolving roots.
520 */
521 FileManager.prototype.init_ = function() {
522 metrics.startInterval('InitFileManager');
523 this.initFileList_();
524 this.initDialogs_();
525
526 // TODO(rginda): 6/22/11: Remove this test when createDateTimeFormat is
527 // available in all chrome trunk builds.
528 if ('createDateTimeFormat' in this.locale_) {
529 this.shortDateFormatter_ =
530 this.locale_.createDateTimeFormat({'dateType': 'medium'});
531 } else {
532 this.shortDateFormatter_ = {
533 format: function(d) {
534 return (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
535 }
536 };
537 }
538
539 // TODO(rginda): 6/22/11: Remove this test when createCollator is
540 // available in all chrome trunk builds.
541 if ('createCollator' in this.locale_) {
542 this.collator_ = this.locale_.createCollator({
543 'numeric': true, 'ignoreCase': true, 'ignoreAccents': true});
544 } else {
545 this.collator_ = {
546 compare: function(a, b) {
547 if (a > b) return 1;
548 if (a < b) return -1;
549 return 0;
550 }
551 };
552 }
553
554 // Optional list of file types.
555 this.fileTypes_ = this.params_.typeList;
556
557 this.showCheckboxes_ =
558 (this.dialogType_ == FileManager.DialogType.FULL_PAGE ||
559 this.dialogType_ == FileManager.DialogType.SELECT_OPEN_MULTI_FILE);
560
561 // DirectoryEntry representing the current directory of the dialog.
562 this.currentDirEntry_ = null;
563
564 this.copyManager_ = new FileCopyManager();
565 this.copyManager_.addEventListener('copy-progress',
566 this.onCopyProgress_.bind(this));
567
568 window.addEventListener('popstate', this.onPopState_.bind(this));
569 window.addEventListener('unload', this.onUnload_.bind(this));
570
571 this.addEventListener('directory-changed',
572 this.onDirectoryChanged_.bind(this));
573 this.addEventListener('selection-summarized',
574 this.onSelectionSummarized_.bind(this));
575
576 // The list of archives requested to mount. We will show contents once
577 // archive is mounted, but only for mounts from within this filebrowser tab.
578 this.mountRequests_ = [];
579 chrome.fileBrowserPrivate.onMountCompleted.addListener(
580 this.onMountCompleted_.bind(this));
581
582 chrome.fileBrowserPrivate.onFileChanged.addListener(
583 this.onFileChanged_.bind(this));
584
585 var self = this;
586
587 // The list of callbacks to be invoked during the directory rescan after
588 // all paste tasks are complete.
589 this.pasteSuccessCallbacks_ = [];
590
591 // The list of active mount points to distinct them from other directories.
592 chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) {
593 self.mountPoints_ = mountPoints;
594 });
595
596 this.initCommands_();
597
598 this.setupCurrentDirectory_();
599
600 this.summarizeSelection_();
601
602 this.dataModel_.sort('cachedMtime_', 'desc');
603
604 this.refocus();
605
606 this.createMetadataProvider_();
607 metrics.recordTime('InitFileManager');
608 metrics.recordTime('TotalLoad');
609 };
610
611 /**
560 * One-time initialization of commands. 612 * One-time initialization of commands.
561 */ 613 */
562 FileManager.prototype.initCommands_ = function() { 614 FileManager.prototype.initCommands_ = function() {
563 var commands = this.dialogDom_.querySelectorAll('command'); 615 var commands = this.dialogDom_.querySelectorAll('command');
564 for (var i = 0; i < commands.length; i++) { 616 for (var i = 0; i < commands.length; i++) {
565 var command = commands[i]; 617 var command = commands[i];
566 cr.ui.Command.decorate(command); 618 cr.ui.Command.decorate(command);
567 this.commands_[command.id] = command; 619 this.commands_[command.id] = command;
568 } 620 }
569 621
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 697
646 var ary = this.dialogDom_.querySelectorAll('[visibleif]'); 698 var ary = this.dialogDom_.querySelectorAll('[visibleif]');
647 for (var i = 0; i < ary.length; i++) { 699 for (var i = 0; i < ary.length; i++) {
648 var expr = ary[i].getAttribute('visibleif'); 700 var expr = ary[i].getAttribute('visibleif');
649 if (!eval(expr)) 701 if (!eval(expr))
650 ary[i].style.display = 'none'; 702 ary[i].style.display = 'none';
651 } 703 }
652 704
653 // Populate the static localized strings. 705 // Populate the static localized strings.
654 i18nTemplate.process(this.document_, localStrings.templateData); 706 i18nTemplate.process(this.document_, localStrings.templateData);
707 };
655 708
709 /**
710 * Constructs table and grid (heavy operation).
711 **/
712 FileManager.prototype.initFileList_ = function() {
656 // Always sharing the data model between the detail/thumb views confuses 713 // Always sharing the data model between the detail/thumb views confuses
657 // them. Instead we maintain this bogus data model, and hook it up to the 714 // them. Instead we maintain this bogus data model, and hook it up to the
658 // view that is not in use. 715 // view that is not in use.
659 this.emptyDataModel_ = new cr.ui.ArrayDataModel([]); 716 this.emptyDataModel_ = new cr.ui.ArrayDataModel([]);
660 717
661 this.dataModel_ = new cr.ui.ArrayDataModel([]); 718 this.dataModel_ = new cr.ui.ArrayDataModel([]);
662 var collator = this.collator_; 719 var collator = this.collator_;
663 this.dataModel_.setCompareFunction('name', function(a, b) { 720 this.dataModel_.setCompareFunction('name', function(a, b) {
664 return collator.compare(a.name, b.name); 721 return collator.compare(a.name, b.name);
665 }); 722 });
(...skipping 12 matching lines...) Expand all
678 } else { 735 } else {
679 this.selectionModelClass_ = cr.ui.ListSelectionModel; 736 this.selectionModelClass_ = cr.ui.ListSelectionModel;
680 } 737 }
681 738
682 this.initTable_(); 739 this.initTable_();
683 this.initGrid_(); 740 this.initGrid_();
684 741
685 this.setListType(FileManager.ListType.DETAIL); 742 this.setListType(FileManager.ListType.DETAIL);
686 743
687 this.onResize_(); 744 this.onResize_();
688 this.dialogDom_.style.opacity = '1';
689 745
690 this.textSearchState_ = {text: '', date: new Date()}; 746 this.textSearchState_ = {text: '', date: new Date()};
691 }; 747 };
692 748
693 /** 749 /**
694 * Get the icon type for a given Entry. 750 * Get the icon type for a given Entry.
695 * 751 *
696 * @param {Entry} entry An Entry subclass (FileEntry or DirectoryEntry). 752 * @param {Entry} entry An Entry subclass (FileEntry or DirectoryEntry).
697 * @return {string} 753 * @return {string}
698 */ 754 */
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
1215 this.deleteEntries(this.selection.entries); 1271 this.deleteEntries(this.selection.entries);
1216 return; 1272 return;
1217 } 1273 }
1218 }; 1274 };
1219 1275
1220 /** 1276 /**
1221 * Respond to the back and forward buttons. 1277 * Respond to the back and forward buttons.
1222 */ 1278 */
1223 FileManager.prototype.onPopState_ = function(event) { 1279 FileManager.prototype.onPopState_ = function(event) {
1224 // TODO(serya): We should restore selected items here. 1280 // TODO(serya): We should restore selected items here.
1225 this.setupCurrentDirectory_(); 1281 if (this.rootEntries_)
1282 this.setupCurrentDirectory_();
1226 }; 1283 };
1227 1284
1228 FileManager.prototype.requestResize_ = function(timeout) { 1285 FileManager.prototype.requestResize_ = function(timeout) {
1229 var self = this; 1286 var self = this;
1230 setTimeout(function() { self.onResize_() }, timeout || 0); 1287 setTimeout(function() { self.onResize_() }, timeout || 0);
1231 }; 1288 };
1232 1289
1233 /** 1290 /**
1234 * Resize details and thumb views to fit the new window size. 1291 * Resize details and thumb views to fit the new window size.
1235 */ 1292 */
(...skipping 2500 matching lines...) Expand 10 before | Expand all | Expand 10 after
3736 }); 3793 });
3737 }, onError); 3794 }, onError);
3738 3795
3739 function onError(err) { 3796 function onError(err) {
3740 console.log('Error while checking free space: ' + err); 3797 console.log('Error while checking free space: ' + err);
3741 setTimeout(doCheck, 1000 * 60); 3798 setTimeout(doCheck, 1000 * 60);
3742 } 3799 }
3743 } 3800 }
3744 } 3801 }
3745 })(); 3802 })();
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/resources/file_manager/js/main.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698