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 // 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 /** | 10 /** |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 }; | 470 }; |
471 } | 471 } |
472 | 472 |
473 // Optional list of file types. | 473 // Optional list of file types. |
474 this.fileTypes_ = this.params_.typeList; | 474 this.fileTypes_ = this.params_.typeList; |
475 | 475 |
476 this.showCheckboxes_ = | 476 this.showCheckboxes_ = |
477 (this.dialogType_ == FileManager.DialogType.FULL_PAGE || | 477 (this.dialogType_ == FileManager.DialogType.FULL_PAGE || |
478 this.dialogType_ == FileManager.DialogType.SELECT_OPEN_MULTI_FILE); | 478 this.dialogType_ == FileManager.DialogType.SELECT_OPEN_MULTI_FILE); |
479 | 479 |
480 this.table_.startBatchUpdates(); | 480 this.table_.list.startBatchUpdates(); |
481 this.grid_.startBatchUpdates(); | 481 this.grid_.startBatchUpdates(); |
482 | 482 |
483 this.initFileList_(); | 483 this.initFileList_(); |
484 this.initDialogs_(); | 484 this.initDialogs_(); |
485 | 485 |
486 this.copyManager_ = new FileCopyManager(); | 486 this.copyManager_ = new FileCopyManager(); |
487 this.copyManager_.addEventListener('copy-progress', | 487 this.copyManager_.addEventListener('copy-progress', |
488 this.onCopyProgress_.bind(this)); | 488 this.onCopyProgress_.bind(this)); |
489 | 489 |
490 window.addEventListener('popstate', this.onPopState_.bind(this)); | 490 window.addEventListener('popstate', this.onPopState_.bind(this)); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 sortDirection = | 538 sortDirection = |
539 window.localStorage['sort-direction-' + this.dialogType_] || | 539 window.localStorage['sort-direction-' + this.dialogType_] || |
540 sortDirection; | 540 sortDirection; |
541 } | 541 } |
542 this.directoryModel_.fileList.sort(sortField, sortDirection); | 542 this.directoryModel_.fileList.sort(sortField, sortDirection); |
543 | 543 |
544 this.refocus(); | 544 this.refocus(); |
545 | 545 |
546 this.createMetadataProvider_(); | 546 this.createMetadataProvider_(); |
547 | 547 |
548 this.table_.endBatchUpdates(); | 548 this.table_.list.endBatchUpdates(); |
549 this.grid_.endBatchUpdates(); | 549 this.grid_.endBatchUpdates(); |
550 | 550 |
551 metrics.recordInterval('Load.DOM'); | 551 metrics.recordInterval('Load.DOM'); |
552 metrics.recordInterval('Load.Total'); | 552 metrics.recordInterval('Load.Total'); |
553 }; | 553 }; |
554 | 554 |
555 /** | 555 /** |
556 * One-time initialization of commands. | 556 * One-time initialization of commands. |
557 */ | 557 */ |
558 FileManager.prototype.initCommands_ = function() { | 558 FileManager.prototype.initCommands_ = function() { |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 | 749 |
750 var self = this; | 750 var self = this; |
751 this.rootsList_.itemConstructor = function(entry) { | 751 this.rootsList_.itemConstructor = function(entry) { |
752 return self.renderRoot_(entry); | 752 return self.renderRoot_(entry); |
753 }; | 753 }; |
754 | 754 |
755 this.rootsList_.selectionModel = this.directoryModel_.rootsListSelection; | 755 this.rootsList_.selectionModel = this.directoryModel_.rootsListSelection; |
756 | 756 |
757 // TODO(dgozman): add "Add a drive" item. | 757 // TODO(dgozman): add "Add a drive" item. |
758 this.rootsList_.dataModel = this.directoryModel_.rootsList; | 758 this.rootsList_.dataModel = this.directoryModel_.rootsList; |
759 this.directoryModel_.updateRoots(function() { | 759 this.directoryModel_.updateRoots(); |
760 self.rootsList_.endBatchUpdates(); | |
761 }); | |
762 }; | 760 }; |
763 | 761 |
764 FileManager.prototype.initGData_ = function() { | 762 FileManager.prototype.initGData_ = function() { |
765 metrics.startInterval('Load.GData'); | 763 metrics.startInterval('Load.GData'); |
766 // TODO(zelidrag): We should do this first time user selects this provider. | 764 // TODO(zelidrag): We should do this first time user selects this provider. |
767 chrome.fileBrowserPrivate.addMount('', 'gdata', {}); | 765 chrome.fileBrowserPrivate.addMount('', 'gdata', {}); |
768 }; | 766 }; |
769 | 767 |
770 /** | 768 /** |
771 * Get the icon type for a given Entry. | 769 * Get the icon type for a given Entry. |
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1390 | 1388 |
1391 /** | 1389 /** |
1392 * Restores current directory and may be a selected item after page load (or | 1390 * Restores current directory and may be a selected item after page load (or |
1393 * reload) or popping a state (after click on back/forward). If location.hash | 1391 * reload) or popping a state (after click on back/forward). If location.hash |
1394 * is present it means that the user has navigated somewhere and that place | 1392 * is present it means that the user has navigated somewhere and that place |
1395 * will be restored. defaultPath primarily is used with save/open dialogs. | 1393 * will be restored. defaultPath primarily is used with save/open dialogs. |
1396 * Default path may also contain a file name. Freshly opened file manager | 1394 * Default path may also contain a file name. Freshly opened file manager |
1397 * window has neither. | 1395 * window has neither. |
1398 */ | 1396 */ |
1399 FileManager.prototype.setupCurrentDirectory_ = function() { | 1397 FileManager.prototype.setupCurrentDirectory_ = function() { |
1400 // Avoid a bunch of intermediate list redraws while the data model is | |
1401 // cleared and updated. Note that it may (or may not) be desirable to draw | |
1402 // partial results as we get them, but today the DirectoryReader API | |
1403 // generally returns all entries in one chunk so even without this batching | |
1404 // we wouldn't have incremental updates. | |
1405 this.table_.startBatchUpdates(); | |
1406 var onLoaded = this.table_.endBatchUpdates.bind(this.table_); | |
1407 | |
1408 if (location.hash) { | 1398 if (location.hash) { |
1409 // Location hash has the highest priority. | 1399 // Location hash has the highest priority. |
1410 var path = decodeURI(location.hash.substr(1)); | 1400 var path = decodeURI(location.hash.substr(1)); |
1411 | 1401 |
1412 // In the FULL_PAGE mode if the path points to a file we should invoke | 1402 // In the FULL_PAGE mode if the path points to a file we should invoke |
1413 // the default action after selecting it. | 1403 // the default action after selecting it. |
1414 if (this.dialogType_ == FileManager.DialogType.FULL_PAGE) { | 1404 if (this.dialogType_ == FileManager.DialogType.FULL_PAGE) { |
1415 // To prevent the file list flickering for a moment before the action | 1405 // To prevent the file list flickering for a moment before the action |
1416 // is executed we hide it under a white div. | 1406 // is executed we hide it under a white div. |
1417 var shade = this.document_.createElement('div'); | 1407 var shade = this.document_.createElement('div'); |
1418 shade.className = 'overlay-pane'; | 1408 shade.className = 'overlay-pane'; |
1419 shade.style.backgroundColor = 'white'; | 1409 shade.style.backgroundColor = 'white'; |
1420 this.document_.body.appendChild(shade); | 1410 this.document_.body.appendChild(shade); |
1421 function removeShade() { shade.parentNode.removeChild(shade) } | 1411 function removeShade() { shade.parentNode.removeChild(shade) } |
1422 | 1412 |
1423 // Keep track of whether the path is identified as an existing leaf | |
1424 // node. Note that onResolve is guaranteed to be called (exactly once) | |
1425 // before onLoadedActivateLeaf. | |
1426 var foundLeaf = true; | |
1427 function onResolve(baseName, leafName, exists) { | 1413 function onResolve(baseName, leafName, exists) { |
1428 if (!exists || leafName == '') { | 1414 if (!exists || leafName == '') { |
1429 // Non-existent file or a directory. Remove the shade immediately. | 1415 // Non-existent file or a directory. Remove the shade immediately. |
1430 removeShade(); | 1416 removeShade(); |
1431 foundLeaf = false; | |
1432 } | 1417 } |
1433 } | 1418 } |
1434 | 1419 |
1435 // TODO(kaznacheev): refactor dispatchDefaultTask to accept an array | 1420 // TODO(kaznacheev): refactor dispatchDefaultTask to accept an array |
1436 // of urls instead of a selection. This will remove the need to wait | 1421 // of urls instead of a selection. This will remove the need to wait |
1437 // until the selection is done. | 1422 // until the selection is done. |
1438 var self = this; | 1423 var self = this; |
1439 function onLoadedActivateLeaf() { | 1424 function onFileSelected() { |
1440 onLoaded(); | 1425 self.dispatchDefaultTask_(); |
1441 if (foundLeaf) { | 1426 setTimeout(removeShade, 1000); |
1442 self.dispatchDefaultTask_(); | |
1443 setTimeout(removeShade, 1000); | |
1444 } | |
1445 } | 1427 } |
1446 this.directoryModel_.setupPath(path, onLoadedActivateLeaf, onResolve); | 1428 this.directoryModel_.setupPath(path, onResolve, onFileSelected); |
1447 | |
1448 return; | 1429 return; |
1449 } | 1430 } |
1450 | 1431 |
1451 this.directoryModel_.setupPath(path, onLoaded); | 1432 this.directoryModel_.setupPath(path); |
1452 return; | 1433 return; |
1453 } | 1434 } |
1454 | 1435 |
1455 if (this.params_.defaultPath) { | 1436 if (this.params_.defaultPath) { |
1456 var path = this.params_.defaultPath; | 1437 var path = this.params_.defaultPath; |
1457 if (this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) { | 1438 if (this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) { |
1458 this.directoryModel_.setupPath(path, onLoaded, | 1439 this.directoryModel_.setupPath(path, function(basePath, leafName) { |
1459 function(basePath, leafName) { | 1440 this.filenameInput_.value = leafName; |
1460 this.filenameInput_.value = leafName; | 1441 this.selectDefaultPathInFilenameInput_(); |
1461 this.selectDefaultPathInFilenameInput_(); | 1442 }.bind(this)); |
1462 }.bind(this)); | |
1463 return; | 1443 return; |
1464 } | 1444 } |
1465 | 1445 |
1466 this.directoryModel_.setupPath(path, onLoaded); | 1446 this.directoryModel_.setupPath(path); |
1467 return; | 1447 return; |
1468 } | 1448 } |
1469 | 1449 |
1470 this.directoryModel_.setupDefaultPath(onLoaded); | 1450 this.directoryModel_.setupDefaultPath(); |
1471 }; | 1451 }; |
1472 | 1452 |
1473 /** | 1453 /** |
1474 * Tweak the UI to become a particular kind of dialog, as determined by the | 1454 * Tweak the UI to become a particular kind of dialog, as determined by the |
1475 * dialog type parameter passed to the constructor. | 1455 * dialog type parameter passed to the constructor. |
1476 */ | 1456 */ |
1477 FileManager.prototype.initDialogType_ = function() { | 1457 FileManager.prototype.initDialogType_ = function() { |
1478 var defaultTitle; | 1458 var defaultTitle; |
1479 var okLabel = str('OPEN_LABEL'); | 1459 var okLabel = str('OPEN_LABEL'); |
1480 | 1460 |
(...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2413 }); | 2393 }); |
2414 return; | 2394 return; |
2415 } | 2395 } |
2416 // Current durectory just unmounted. Move to the 'Downloads'. | 2396 // Current durectory just unmounted. Move to the 'Downloads'. |
2417 changeDirectoryTo = '/' + DirectoryModel.DOWNLOADS_DIRECTORY; | 2397 changeDirectoryTo = '/' + DirectoryModel.DOWNLOADS_DIRECTORY; |
2418 } | 2398 } |
2419 | 2399 |
2420 // Even if something failed root list should be rescanned. | 2400 // Even if something failed root list should be rescanned. |
2421 // Failed mounts can "give" us new devices which might be formatted, | 2401 // Failed mounts can "give" us new devices which might be formatted, |
2422 // so we have to refresh root list then. | 2402 // so we have to refresh root list then. |
2423 self.directoryModel_.updateRoots(function() { | 2403 self.directoryModel_.updateRoots(changeDirectoryTo); |
2424 if (changeDirectoryTo) { | |
2425 self.directoryModel_.changeDirectory(changeDirectoryTo); | |
2426 } | |
2427 }); | |
2428 }); | 2404 }); |
2429 }; | 2405 }; |
2430 | 2406 |
2431 /** | 2407 /** |
2432 * Event handler called when some internal task should be executed. | 2408 * Event handler called when some internal task should be executed. |
2433 */ | 2409 */ |
2434 FileManager.prototype.onFileTaskExecute_ = function(id, details) { | 2410 FileManager.prototype.onFileTaskExecute_ = function(id, details) { |
2435 var urls = details.urls; | 2411 var urls = details.urls; |
2436 if (id == 'play') { | 2412 if (id == 'play') { |
2437 var position = 0; | 2413 var position = 0; |
(...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3952 }); | 3928 }); |
3953 }, onError); | 3929 }, onError); |
3954 | 3930 |
3955 function onError(err) { | 3931 function onError(err) { |
3956 console.log('Error while checking free space: ' + err); | 3932 console.log('Error while checking free space: ' + err); |
3957 setTimeout(doCheck, 1000 * 60); | 3933 setTimeout(doCheck, 1000 * 60); |
3958 } | 3934 } |
3959 } | 3935 } |
3960 } | 3936 } |
3961 })(); | 3937 })(); |
OLD | NEW |