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 'use strict'; | 5 'use strict'; |
6 | 6 |
7 /** | 7 /** |
8 * FileManager constructor. | 8 * FileManager constructor. |
9 * | 9 * |
10 * FileManager objects encapsulate the functionality of the file selector | 10 * FileManager objects encapsulate the functionality of the file selector |
(...skipping 3465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3476 * | 3476 * |
3477 * @param {Event} event The click event. | 3477 * @param {Event} event The click event. |
3478 * @private | 3478 * @private |
3479 */ | 3479 */ |
3480 FileManager.prototype.onCancel_ = function(event) { | 3480 FileManager.prototype.onCancel_ = function(event) { |
3481 chrome.fileManagerPrivate.cancelDialog(); | 3481 chrome.fileManagerPrivate.cancelDialog(); |
3482 window.close(); | 3482 window.close(); |
3483 }; | 3483 }; |
3484 | 3484 |
3485 /** | 3485 /** |
3486 * Resolves selected file urls returned from an Open dialog. | |
3487 * | |
3488 * For drive files this involves some special treatment. | |
3489 * Starts getting drive files if needed. | |
3490 * | |
3491 * @param {Array.<string>} fileUrls Drive URLs. | |
3492 * @param {function(Array.<string>)} callback To be called with fixed URLs. | |
3493 * @private | |
3494 */ | |
3495 FileManager.prototype.resolveSelectResults_ = function(fileUrls, callback) { | |
3496 if (this.isOnDrive()) { | |
3497 chrome.fileManagerPrivate.getDriveFiles( | |
3498 fileUrls, | |
3499 function(localPaths) { | |
3500 callback(fileUrls); | |
3501 }); | |
3502 } else { | |
3503 callback(fileUrls); | |
3504 } | |
3505 }; | |
3506 | |
3507 /** | |
3508 * Closes this modal dialog with some files selected. | |
3509 * TODO(jamescook): Make unload handler work automatically, crbug.com/104811 | |
3510 * @param {Object} selection Contains urls, filterIndex and multiple fields. | |
3511 * @private | |
3512 */ | |
3513 FileManager.prototype.callSelectFilesApiAndClose_ = function(selection) { | |
3514 var self = this; | |
3515 function callback() { | |
3516 window.close(); | |
3517 } | |
3518 if (selection.multiple) { | |
3519 chrome.fileManagerPrivate.selectFiles( | |
3520 selection.urls, this.params_.shouldReturnLocalPath, callback); | |
3521 } else { | |
3522 var forOpening = (this.dialogType != DialogType.SELECT_SAVEAS_FILE); | |
3523 chrome.fileManagerPrivate.selectFile( | |
3524 selection.urls[0], selection.filterIndex, forOpening, | |
3525 this.params_.shouldReturnLocalPath, callback); | |
3526 } | |
3527 }; | |
3528 | |
3529 /** | |
3530 * Tries to close this modal dialog with some files selected. | 3486 * Tries to close this modal dialog with some files selected. |
3531 * Performs preprocessing if needed (e.g. for Drive). | 3487 * Performs preprocessing if needed (e.g. for Drive). |
3532 * @param {Object} selection Contains urls, filterIndex and multiple fields. | 3488 * @param {Object} selection Contains urls, filterIndex and multiple fields. |
3533 * @private | 3489 * @private |
3534 */ | 3490 */ |
3535 FileManager.prototype.selectFilesAndClose_ = function(selection) { | 3491 FileManager.prototype.selectFilesAndClose_ = function(selection) { |
3536 if (!this.isOnDrive() || | 3492 var callSelectFilesApiAndClose = function(callback) { |
3537 this.dialogType == DialogType.SELECT_SAVEAS_FILE) { | 3493 var onFileSelected = function() { |
3538 setTimeout(this.callSelectFilesApiAndClose_.bind(this, selection), 0); | 3494 callback(); |
| 3495 if (!chrome.runtime.lastError) { |
| 3496 // Call next method on a timeout, as it's unsafe to |
| 3497 // close a window from a callback. |
| 3498 setTimeout(window.close.bind(window), 0); |
| 3499 } |
| 3500 }; |
| 3501 if (selection.multiple) { |
| 3502 chrome.fileManagerPrivate.selectFiles( |
| 3503 selection.urls, |
| 3504 this.params_.shouldReturnLocalPath, |
| 3505 onFileSelected); |
| 3506 } else { |
| 3507 chrome.fileManagerPrivate.selectFile( |
| 3508 selection.urls[0], |
| 3509 selection.filterIndex, |
| 3510 this.dialogType != DialogType.SELECT_SAVEAS_FILE /* for opening */, |
| 3511 this.params_.shouldReturnLocalPath, |
| 3512 onFileSelected); |
| 3513 } |
| 3514 }.bind(this); |
| 3515 |
| 3516 if (!this.isOnDrive() || this.dialogType == DialogType.SELECT_SAVEAS_FILE) { |
| 3517 callSelectFilesApiAndClose(function() {}); |
3539 return; | 3518 return; |
3540 } | 3519 } |
3541 | 3520 |
3542 var shade = this.document_.createElement('div'); | 3521 var shade = this.document_.createElement('div'); |
3543 shade.className = 'shade'; | 3522 shade.className = 'shade'; |
3544 var footer = this.dialogDom_.querySelector('.button-panel'); | 3523 var footer = this.dialogDom_.querySelector('.button-panel'); |
3545 var progress = footer.querySelector('.progress-track'); | 3524 var progress = footer.querySelector('.progress-track'); |
3546 progress.style.width = '0%'; | 3525 progress.style.width = '0%'; |
3547 var cancelled = false; | 3526 var cancelled = false; |
3548 | 3527 |
3549 var progressMap = {}; | 3528 var progressMap = {}; |
3550 var filesStarted = 0; | 3529 var filesStarted = 0; |
3551 var filesTotal = selection.urls.length; | 3530 var filesTotal = selection.urls.length; |
3552 for (var index = 0; index < selection.urls.length; index++) { | 3531 for (var index = 0; index < selection.urls.length; index++) { |
3553 progressMap[selection.urls[index]] = -1; | 3532 progressMap[selection.urls[index]] = -1; |
3554 } | 3533 } |
3555 var lastPercent = 0; | 3534 var lastPercent = 0; |
3556 var bytesTotal = 0; | 3535 var bytesTotal = 0; |
3557 var bytesDone = 0; | 3536 var bytesDone = 0; |
3558 | 3537 |
3559 var onFileTransfersUpdated = function(status) { | 3538 var onFileTransfersUpdated = function(status) { |
3560 var escaped = encodeURI(status.fileUrl); | 3539 if (!(status.fileUrl in progressMap)) |
3561 var old = progressMap[escaped]; | 3540 return; |
| 3541 if (status.total == -1) |
| 3542 return; |
| 3543 |
| 3544 var old = progressMap[status.fileUrl]; |
3562 if (old == -1) { | 3545 if (old == -1) { |
3563 // -1 means we don't know file size yet. | 3546 // -1 means we don't know file size yet. |
3564 bytesTotal += status.total; | 3547 bytesTotal += status.total; |
3565 filesStarted++; | 3548 filesStarted++; |
3566 old = 0; | 3549 old = 0; |
3567 } | 3550 } |
3568 bytesDone += status.processed - old; | 3551 bytesDone += status.processed - old; |
3569 progressMap[escaped] = status.processed; | 3552 progressMap[status.fileUrl] = status.processed; |
3570 | 3553 |
3571 var percent = bytesTotal == 0 ? 0 : bytesDone / bytesTotal; | 3554 var percent = bytesTotal == 0 ? 0 : bytesDone / bytesTotal; |
3572 // For files we don't have information about, assume the progress is zero. | 3555 // For files we don't have information about, assume the progress is zero. |
3573 percent = percent * filesStarted / filesTotal * 100; | 3556 percent = percent * filesStarted / filesTotal * 100; |
3574 // Do not decrease the progress. This may happen, if first downloaded | 3557 // Do not decrease the progress. This may happen, if first downloaded |
3575 // file is small, and the second one is large. | 3558 // file is small, and the second one is large. |
3576 lastPercent = Math.max(lastPercent, percent); | 3559 lastPercent = Math.max(lastPercent, percent); |
3577 progress.style.width = lastPercent + '%'; | 3560 progress.style.width = lastPercent + '%'; |
3578 }.bind(this); | 3561 }.bind(this); |
3579 | 3562 |
3580 var setup = function() { | 3563 var setup = function() { |
3581 this.document_.querySelector('.dialog-container').appendChild(shade); | 3564 this.document_.querySelector('.dialog-container').appendChild(shade); |
3582 setTimeout(function() { shade.setAttribute('fadein', 'fadein') }, 100); | 3565 setTimeout(function() { shade.setAttribute('fadein', 'fadein'); }, 100); |
3583 footer.setAttribute('progress', 'progress'); | 3566 footer.setAttribute('progress', 'progress'); |
3584 this.cancelButton_.removeEventListener('click', this.onCancelBound_); | 3567 this.cancelButton_.removeEventListener('click', this.onCancelBound_); |
3585 this.cancelButton_.addEventListener('click', onCancel); | 3568 this.cancelButton_.addEventListener('click', onCancel); |
3586 chrome.fileManagerPrivate.onFileTransfersUpdated.addListener( | 3569 chrome.fileManagerPrivate.onFileTransfersUpdated.addListener( |
3587 onFileTransfersUpdated); | 3570 onFileTransfersUpdated); |
3588 }.bind(this); | 3571 }.bind(this); |
3589 | 3572 |
3590 var cleanup = function() { | 3573 var cleanup = function() { |
3591 shade.parentNode.removeChild(shade); | 3574 shade.parentNode.removeChild(shade); |
3592 footer.removeAttribute('progress'); | 3575 footer.removeAttribute('progress'); |
3593 this.cancelButton_.removeEventListener('click', onCancel); | 3576 this.cancelButton_.removeEventListener('click', onCancel); |
3594 this.cancelButton_.addEventListener('click', this.onCancelBound_); | 3577 this.cancelButton_.addEventListener('click', this.onCancelBound_); |
3595 chrome.fileManagerPrivate.onFileTransfersUpdated.removeListener( | 3578 chrome.fileManagerPrivate.onFileTransfersUpdated.removeListener( |
3596 onFileTransfersUpdated); | 3579 onFileTransfersUpdated); |
3597 }.bind(this); | 3580 }.bind(this); |
3598 | 3581 |
3599 var onCancel = function() { | 3582 var onCancel = function() { |
3600 cancelled = true; | |
3601 // According to API cancel may fail, but there is no proper UI to reflect | 3583 // According to API cancel may fail, but there is no proper UI to reflect |
3602 // this. So, we just silently assume that everything is cancelled. | 3584 // this. So, we just silently assume that everything is cancelled. |
3603 chrome.fileManagerPrivate.cancelFileTransfers( | 3585 chrome.fileManagerPrivate.cancelFileTransfers( |
3604 selection.urls, function(response) {}); | 3586 selection.urls, function(response) {}); |
3605 cleanup(); | |
3606 }.bind(this); | |
3607 | |
3608 var onResolved = function(resolvedUrls) { | |
3609 if (cancelled) return; | |
3610 cleanup(); | |
3611 selection.urls = resolvedUrls; | |
3612 // Call next method on a timeout, as it's unsafe to | |
3613 // close a window from a callback. | |
3614 setTimeout(this.callSelectFilesApiAndClose_.bind(this, selection), 0); | |
3615 }.bind(this); | 3587 }.bind(this); |
3616 | 3588 |
3617 var onProperties = function(properties) { | 3589 var onProperties = function(properties) { |
3618 for (var i = 0; i < properties.length; i++) { | 3590 for (var i = 0; i < properties.length; i++) { |
3619 if (!properties[i] || properties[i].present) { | 3591 if (!properties[i] || properties[i].present) { |
3620 // For files already in GCache, we don't get any transfer updates. | 3592 // For files already in GCache, we don't get any transfer updates. |
3621 filesTotal--; | 3593 filesTotal--; |
3622 } | 3594 } |
3623 } | 3595 } |
3624 this.resolveSelectResults_(selection.urls, onResolved); | 3596 callSelectFilesApiAndClose(cleanup); |
3625 }.bind(this); | 3597 }.bind(this); |
3626 | 3598 |
3627 setup(); | 3599 setup(); |
3628 | 3600 |
3629 // TODO(mtomasz): Use Entry instead of URLs, if possible. | 3601 // TODO(mtomasz): Use Entry instead of URLs, if possible. |
3630 util.URLsToEntries(selection.urls, function(entries) { | 3602 util.URLsToEntries(selection.urls, function(entries) { |
3631 this.metadataCache_.get(entries, 'external', onProperties); | 3603 this.metadataCache_.get(entries, 'external', onProperties); |
3632 }.bind(this)); | 3604 }.bind(this)); |
3633 }; | 3605 }; |
3634 | 3606 |
(...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4144 callback(this.preferences_); | 4116 callback(this.preferences_); |
4145 return; | 4117 return; |
4146 } | 4118 } |
4147 | 4119 |
4148 chrome.fileManagerPrivate.getPreferences(function(prefs) { | 4120 chrome.fileManagerPrivate.getPreferences(function(prefs) { |
4149 this.preferences_ = prefs; | 4121 this.preferences_ = prefs; |
4150 callback(prefs); | 4122 callback(prefs); |
4151 }.bind(this)); | 4123 }.bind(this)); |
4152 }; | 4124 }; |
4153 })(); | 4125 })(); |
OLD | NEW |