Chromium Code Reviews| Index: chrome/browser/resources/file_manager/js/file_manager.js |
| diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js |
| index 2285332c6f9952bf209bc5a0f5bd4cd3a2e038c3..7aa0c2f20c913ab35302bdee05687306bcba7140 100644 |
| --- a/chrome/browser/resources/file_manager/js/file_manager.js |
| +++ b/chrome/browser/resources/file_manager/js/file_manager.js |
| @@ -28,7 +28,6 @@ function FileManager(dialogDom) { |
| this.currentButter_ = null; |
| this.butterLastShowTime_ = 0; |
| - this.watchedDirectoryUrl_ = null; |
| this.filesystemObserverId_ = null; |
| this.gdataObserverId_ = null; |
| @@ -50,6 +49,7 @@ function FileManager(dialogDom) { |
| this.locale_ = new v8Locale(navigator.language); |
| this.initFileSystem_(); |
| + this.volumeManager_ = VolumeManager.getInstance(); |
| this.initDom_(); |
| this.initDialogType_(); |
| this.dialogDom_.style.opacity = '1'; |
| @@ -208,18 +208,6 @@ FileManager.prototype = { |
| return child_path.indexOf(parent_path) == 0; |
| } |
| - /** |
| - * Normalizes path not to start with / |
| - * |
| - * @param {string} path The file path. |
| - */ |
| - function normalizeAbsolutePath(x) { |
| - if (x[0] == '/') |
| - return x.slice(1); |
| - else |
| - return x; |
| - } |
| - |
| function removeChildren(element) { |
| element.textContent = ''; |
| } |
| @@ -254,6 +242,52 @@ FileManager.prototype = { |
| THUMBNAIL: 'thumb' |
| }; |
| + FileManager.FileWatcher = function(fileManager) { |
| + FileWatcher.call(this, |
| + fileManager.filesystem_.root, |
| + fileManager.directoryModel_, |
| + fileManager.volumeManager_); |
| + this.metadataCache_ = fileManager.metadataCache_; |
| + |
| + this.filesystemChanngeHandler_ = |
|
dgozman
2012/05/16 14:31:46
typo here and below: chaNNge
|
| + fileManager.updateMetadataInUI_.bind(fileManager, 'filesystem'); |
| + this.gdataChanngeHandler_ = |
| + fileManager.updateMetadataInUI_.bind(fileManager, 'gdata'); |
| + |
| + this.filesystemObserverId_ = null; |
| + this.gdataObserverId_ = null; |
| + }; |
| + |
| + FileManager.FileWatcher.prototype.__proto__ = FileWatcher.prototype; |
| + |
| + FileManager.FileWatcher.prototype.changeWatchedEntry = function(entry) { |
| + FileWatcher.prototype.changeWatchedEntry.call(this, entry); |
| + |
| + if (this.filesystemObserverId_) |
| + this.metadataCache_.removeObserver(this.filesystemObserverId_); |
| + if (this.gdataObserverId_) |
| + this.metadataCache_.removeObserver(this.gdataObserverId_); |
| + this.filesystemObserverId_ = null; |
| + this.gdataObserverId_ = null; |
| + if (!entry) |
| + return; |
| + |
| + this.filesystemObserverId_ = this.metadataCache_.addObserver( |
| + entry, |
| + MetadataCache.CHILDREN, |
| + 'filesystem', |
| + this.filesystemChanngeHandler_); |
| + |
| + if (DirectoryModel.getRootType(entry.fullPath) == |
| + DirectoryModel.RootType.GDATA) { |
| + this.gdataObserverId_ = this.metadataCache_.addObserver( |
| + entry, |
| + MetadataCache.CHILDREN, |
| + 'gdata', |
| + this.gdataChanngeHandler_); |
| + } |
| + }; |
| + |
| /** |
| * Load translated strings. |
| */ |
| @@ -284,31 +318,13 @@ FileManager.prototype = { |
| var self = this; |
| - // The list of active mount points to distinct them from other directories. |
| - chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) { |
| - self.setMountPoints_(mountPoints); |
| - onDone(); |
| - }); |
| - |
| - function onDone() { |
| - if (self.mountPoints_ && self.filesystem_) |
| - self.init_(); |
| - } |
| - |
| chrome.fileBrowserPrivate.requestLocalFileSystem(function(filesystem) { |
| metrics.recordInterval('Load.FileSystem'); |
| self.filesystem_ = filesystem; |
| - onDone(); |
| + self.init_(); |
| }); |
| }; |
| - FileManager.prototype.setMountPoints_ = function(mountPoints) { |
| - this.mountPoints_ = mountPoints; |
| - // Add gdata mount info if present. |
| - if (this.gdataMounted_) |
| - this.mountPoints_.push(this.gdataMountInfo_); |
| - }; |
| - |
| /** |
| * Continue initializing the file manager after resolving roots. |
| */ |
| @@ -340,37 +356,27 @@ FileManager.prototype = { |
| window.addEventListener('popstate', this.onPopState_.bind(this)); |
| window.addEventListener('unload', this.onUnload_.bind(this)); |
| - this.directoryModel_.addEventListener('directory-changed', |
| + var dm = this.directoryModel_; |
| + dm.addEventListener('directory-changed', |
| this.onDirectoryChanged_.bind(this)); |
| var self = this; |
| - this.directoryModel_.addEventListener('begin-update-files', function() { |
| + dm.addEventListener('begin-update-files', function() { |
| self.currentList_.startBatchUpdates(); |
| }); |
| - this.directoryModel_.addEventListener('end-update-files', function() { |
| + dm.addEventListener('end-update-files', function() { |
| self.restoreItemBeingRenamed_(); |
| self.currentList_.endBatchUpdates(); |
| }); |
| - this.directoryModel_.addEventListener('scan-started', |
| - this.showSpinnerLater_.bind(this)); |
| - this.directoryModel_.addEventListener('scan-completed', |
| - this.showSpinner_.bind(this, false)); |
| - this.directoryModel_.addEventListener('scan-completed', |
| - this.refreshCurrentDirectoryMetadata_.bind(this)); |
| - this.directoryModel_.addEventListener('rescan-completed', |
| - this.refreshCurrentDirectoryMetadata_.bind(this)); |
| + dm.addEventListener('scan-started', this.showSpinnerLater_.bind(this)); |
| + dm.addEventListener('scan-completed', this.showSpinner_.bind(this, false)); |
| + dm.addEventListener('scan-completed', |
| + this.refreshCurrentDirectoryMetadata_.bind(this)); |
| + dm.addEventListener('rescan-completed', |
| + this.refreshCurrentDirectoryMetadata_.bind(this)); |
| this.addEventListener('selection-summarized', |
| this.onSelectionSummarized_.bind(this)); |
| - // The list of archives requested to mount. We will show contents once |
| - // archive is mounted, but only for mounts from within this filebrowser tab. |
| - this.mountRequests_ = []; |
| - this.unmountRequests_ = []; |
| - chrome.fileBrowserPrivate.onMountCompleted.addListener( |
| - this.onMountCompleted_.bind(this)); |
| - |
| - chrome.fileBrowserPrivate.onFileChanged.addListener( |
| - this.onFileChanged_.bind(this)); |
| - |
| + this.setupCurrentDirectory_(true /* page loading */); |
| this.networkConnectionState_ = null; |
| var queryNetworkConnectionState = function() { |
| chrome.fileBrowserPrivate.getNetworkConnectionState( |
| @@ -380,29 +386,6 @@ FileManager.prototype = { |
| chrome.fileBrowserPrivate.onNetworkConnectionChanged. |
| addListener(queryNetworkConnectionState); |
| - var invokeHandler = !this.params_.selectOnly; |
| - if (this.isStartingOnGData_()) { |
| - // We are opening on a GData path. Mount GData and show |
| - // "Loading Google Docs" message until the directory content loads. |
| - this.dialogContainer_.setAttribute('unmounted', true); |
| - this.initGData_(true /* dirChanged */); |
| - // This is a one-time handler (will be nulled out on the first call). |
| - this.setupCurrentDirectoryPostponed_ = function(event) { |
| - this.directoryModel_.removeEventListener('directory-changed', |
| - this.setupCurrentDirectoryPostponed_); |
| - this.setupCurrentDirectoryPostponed_ = null; |
| - if (event) // If called as an event handler just exit silently. |
| - return; |
| - this.setupCurrentDirectory_( |
| - invokeHandler, false /* blankWhileOpeningAFile */); |
| - }.bind(this); |
| - this.directoryModel_.addEventListener('directory-changed', |
| - this.setupCurrentDirectoryPostponed_); |
| - } else { |
| - this.setupCurrentDirectory_( |
| - invokeHandler, true /* blankWhileOpeningAFile */); |
| - } |
| - |
| this.summarizeSelection_(); |
| var sortField = |
| @@ -516,7 +499,6 @@ FileManager.prototype = { |
| this.spinner_ = this.dialogDom_.querySelector('.spinner'); |
| this.showSpinner_(false); |
| this.butter_ = this.dialogDom_.querySelector('.butter-bar'); |
| - this.unmountedPanel_ = this.dialogDom_.querySelector('.unmounted-panel'); |
| cr.ui.decorate('#gdata-settings', cr.ui.MenuButton); |
| cr.ui.Table.decorate(this.table_); |
| @@ -566,11 +548,6 @@ FileManager.prototype = { |
| this.dialogDom_.querySelector('#thumbnail-view').addEventListener( |
| 'click', this.onThumbnailViewButtonClick_.bind(this)); |
| - // When we show the page for the first time we want to avoid |
| - // the GDrive settings button animation, so we set the attribute ASAP. |
| - if (this.isStartingOnGData_()) |
| - this.dialogContainer_.setAttribute('gdata', true); |
| - |
| this.syncButton = this.dialogDom_.querySelector('#gdata-sync-settings'); |
| this.syncButton.addEventListener('click', this.onGDataPrefClick_.bind( |
| this, 'cellularDisabled', false /* not inverted */)); |
| @@ -585,8 +562,9 @@ FileManager.prototype = { |
| this.onGDataPreferencesChanged_.bind(this)); |
| }.bind(this); |
| queryGDataPreferences(); |
| - chrome.fileBrowserPrivate.onGDataPreferencesChanged. |
| - addListener(queryGDataPreferences); |
| + // TODO(serya): uncomment |
| + //chrome.fileBrowserPrivate.onGDataPreferencesChanged. |
| + // addListener(queryGDataPreferences); |
| cr.ui.ComboButton.decorate(this.taskItems_); |
| this.taskItems_.addEventListener('select', |
| @@ -626,7 +604,11 @@ FileManager.prototype = { |
| this.filesystem_.root, |
| sigleSelection, |
| FileManager.isGDataEnabled(), |
| - this.metadataCache_); |
| + this.metadataCache_, |
| + this.volumeManager_); |
| + |
| + this.fileWatcher_ = new FileManager.FileWatcher(this); |
| + this.fileWatcher_.start(); |
| if (FileManager.isGDataEnabled()) |
| this.initGDataWelcomeBanners_(); |
| @@ -664,12 +646,14 @@ FileManager.prototype = { |
| this.setListType(listType); |
| this.textSearchState_ = {text: '', date: new Date()}; |
| + |
| + this.volumeManager_.addEventListener('gdata-status-changed', |
| + this.updateGDataStatus_.bind(this, 'status-change')); |
| }; |
| FileManager.prototype.initRootsList_ = function() { |
| this.rootsList_ = this.dialogDom_.querySelector('#roots-list'); |
| cr.ui.List.decorate(this.rootsList_); |
| - this.rootsList_.startBatchUpdates(); |
| var self = this; |
| this.rootsList_.itemConstructor = function(entry) { |
| @@ -681,115 +665,64 @@ FileManager.prototype = { |
| // TODO(dgozman): add "Add a drive" item. |
| this.rootsList_.dataModel = this.directoryModel_.getRootsList(); |
| - this.directoryModel_.updateRoots(function() { |
| - self.rootsList_.endBatchUpdates(); |
| - }, false); |
| }; |
| - /** |
| - * @param {boolean} dirChanged True if we just changed to GData directory, |
| - * False if "Retry" button clicked. |
| - */ |
| - FileManager.prototype.initGData_ = function(dirChanged) { |
| - this.initGDataUnmountedPanel_(); |
| - |
| - this.unmountedPanel_.removeAttribute('error'); |
| - if (dirChanged) { |
| - // When changing to GData directory we want to see a clear panel. |
| - this.unmountedPanel_.removeAttribute('retry'); |
| - if (this.gdataLoadingTimer_) { // Show immediately if already loading. |
| - this.unmountedPanel_.setAttribute('loading', true); |
| - } else { |
| - this.unmountedPanel_.removeAttribute('loading'); |
| - setTimeout(function() { |
| - if (this.gdataLoadingTimer_) { // Still loading. |
| - this.unmountedPanel_.setAttribute('loading', true); |
| - } |
| - }.bind(this), 500); |
| + FileManager.prototype.updateGDataStatus_ = function(reason) { |
| + var node = this.dialogContainer_; |
| + if (this.isOnGData()) { |
| + var status = this.volumeManager_.getGDataStatus(); |
| + if (status == VolumeManager.GDataStatus.MOUNTING || |
| + status == VolumeManager.GDataStatus.ERROR) { |
| + this.initGDataUnmountedPanel_(); |
| + var retryButton = this.document_.querySelector( |
| + '#unmounted-panel button.retry'); |
| + if (status == VolumeManager.GDataStatus.ERROR) |
| + retryButton.hidden = false; |
| + else if (reason == 'directory-change') |
| + retryButton.hidden = true; |
| } |
| + node.setAttribute('gdata', status); |
| } else { |
| - // When retrying we do not hide "Retry" and "Learn more". |
| - this.unmountedPanel_.setAttribute('loading', true); |
| - } |
| - |
| - // If the user changed to another directory and then back to GData we |
| - // re-enter this method while the timer is still active. In this case |
| - // we only update the UI but do not request the mount again. |
| - if (this.gdataLoadingTimer_) |
| - return; |
| - |
| - metrics.startInterval('Load.GData'); |
| - chrome.fileBrowserPrivate.addMount('', 'gdata', {}, |
| - function(sourcePath) {}); |
| - |
| - // This timer could fire before the mount succeeds. We will silently |
| - // replace the error message with the correct directory contents. |
| - this.gdataLoadingTimer_ = setTimeout(function() { |
| - this.gdataLoadingTimer_ = null; |
| - this.onGDataUnreachable_('GData load timeout'); |
| - }.bind(this), |
| - 15 * 60 * 1000); |
| - }; |
| - |
| - FileManager.prototype.clearGDataLoadingTimer_ = function(message) { |
| - if (this.gdataLoadingTimer_) { |
| - clearTimeout(this.gdataLoadingTimer_); |
| - this.gdataLoadingTimer_ = null; |
| - } |
| - }; |
| - |
| - FileManager.prototype.onGDataUnreachable_ = function(message) { |
| - console.warn(message); |
| - if (this.isOnGData()) { |
| - this.unmountedPanel_.removeAttribute('loading'); |
| - this.unmountedPanel_.setAttribute('error', true); |
| - this.unmountedPanel_.setAttribute('retry', true); |
| + node.removeAttribute('gdata'); |
| } |
| + console.log('gdata status: ', node.getAttribute('gdata')); |
| }; |
| FileManager.prototype.initGDataUnmountedPanel_ = function() { |
| - if (this.unmountedPanel_.firstElementChild) |
| + var panel = this.document_.querySelector('#unmounted-panel'); |
| + if (panel.firstElementChild) |
| return; |
| - var loading = this.document_.createElement('div'); |
| - loading.className = 'gdata loading'; |
| - loading.textContent = str('GDATA_LOADING'); |
| - this.unmountedPanel_.appendChild(loading); |
| - |
| - var spinnerBox = this.document_.createElement('div'); |
| - spinnerBox.className = 'spinner-box'; |
| - loading.appendChild(spinnerBox); |
| - |
| - var spinner = this.document_.createElement('div'); |
| - spinner.className = 'spinner'; |
| - spinnerBox.appendChild(spinner); |
| + function create(tag, className) { |
| + var div = panel.ownerDocument.createElement(tag); |
| + div.className = className; |
| + return div; |
| + } |
| - var progress = this.document_.createElement('div'); |
| - progress.className = 'gdata progress'; |
| - this.unmountedPanel_.appendChild(progress); |
| + function append(tag, className, opt_textContent) { |
| + var div = create(tag, className); |
| + div.textContent = opt_textContent || ''; |
| + panel.appendChild(div); |
| + return div; |
| + } |
| + append('div', 'gdata loading', str('GDATA_LOADING')); |
| + append('div', 'spinner-box').appendChild(create('div', 'spinner')); |
| + var progress = append('div', 'gdata progress'); |
| chrome.fileBrowserPrivate.onDocumentFeedFetched.addListener( |
| function(fileCount) { |
| progress.textContent = strf('GDATA_LOADING_PROGRESS', fileCount); |
| }); |
| - var error = this.document_.createElement('div'); |
| - error.className = 'gdata error'; |
| - error.textContent = strf('GDATA_CANNOT_REACH', str('GDATA_PRODUCT_NAME')); |
| - this.unmountedPanel_.appendChild(error); |
| + append('div', 'gdata error', strf('GDATA_CANNOT_REACH', |
| + str('GDATA_PRODUCT_NAME'))); |
| - var retry = this.document_.createElement('button'); |
| - retry.className = 'gdata retry'; |
| - retry.textContent = str('GDATA_RETRY'); |
| - retry.onclick = this.initGData_.bind(this, false /* retry */); |
| - this.unmountedPanel_.appendChild(retry); |
| + append('button', 'gdata retry', str('GDATA_RETRY')); |
| + // onclick = this.initGData_.bind(this, false); |
| - var learnMore = this.document_.createElement('div'); |
| - learnMore.className = 'gdata learn-more plain-link'; |
| - learnMore.textContent = str('GDATA_LEARN_MORE'); |
| - learnMore.addEventListener('click', |
| - this.onExternalLinkClick_.bind(this, GOOGLE_DRIVE_ERROR_HELP_URL)); |
| - this.unmountedPanel_.appendChild(learnMore); |
| + append('div', 'gdata learn-more plain-link', str('GDATA_LEARN_MORE')). |
| + onclick = this.onExternalLinkClick_.bind(this, |
| + GOOGLE_DRIVE_ERROR_HELP_URL); |
| }; |
| FileManager.prototype.onDataModelSplice_ = function(event) { |
| @@ -1340,7 +1273,8 @@ FileManager.prototype = { |
| return; |
| case 'unmount': |
| - this.unmountVolume_(this.directoryModel_.getCurrentRootDirEntry()); |
| + this.unmountVolume_( |
| + this.directoryModel_.getCurrentRootDirEntry()); |
| return; |
| case 'format': |
| @@ -1363,7 +1297,7 @@ FileManager.prototype = { |
| if (this.getPathFromUrlOrParams_() == |
| this.directoryModel_.getCurrentDirEntry().fullPath) |
| return; |
| - this.setupCurrentDirectory_(true /* invokeHandler */); |
| + this.setupCurrentDirectory_(false /* page loading */); |
| }; |
| FileManager.prototype.requestResize_ = function(timeout) { |
| @@ -1417,13 +1351,10 @@ FileManager.prototype = { |
| * Default path may also contain a file name. Freshly opened file manager |
| * window has neither. |
| * |
| - * @param {boolean} invokeHandler Whether to invoke the default handler on |
| - * the selected file. |
| - * @param {boolean} opt_blankWhileOpeningAFile Whether to show fade over |
| - * the file manager. |
| + * @param {boolean} pageLoading True if pase is loading, |
| + false if popping state. |
| */ |
| - FileManager.prototype.setupCurrentDirectory_ = |
| - function(invokeHandler, opt_blankWhileOpeningAFile) { |
| + FileManager.prototype.setupCurrentDirectory_ = function(pageLoading) { |
| var path = this.getPathFromUrlOrParams_(); |
| if (!path) { |
| @@ -1431,15 +1362,45 @@ FileManager.prototype = { |
| return; |
| } |
| + if (DirectoryModel.getRootType(path) == DirectoryModel.RootType.GDATA) { |
| + if (!FileManager.isGDataEnabled()) { |
| + this.directoryModel_.setupDefaultPath(); |
| + return; |
| + } |
| + |
| + // Reflect immediatelly in the UI we are on GData and display |
| + // mounting UI. |
| + this.directoryModel_.setupPath('/' + DirectoryModel.GDATA_DIRECTORY); |
| + |
| + var tracker = this.directoryModel_.createDirectoryChangeTracker(); |
| + // Expected finish of setupPath to GData. |
| + tracker.exceptInitialChange = true; |
| + tracker.start(); |
| + this.volumeManager_.mountGData(function() { |
| + tracker.stop(); |
| + if (!tracker.hasChanged) { |
| + this.finishSetupCurrentDirectory_(path, pageLoading); |
| + } |
| + }.bind(this), function(error) { |
| + tracker.stop(); |
| + }); |
| + } else { |
| + this.finishSetupCurrentDirectory_(path, pageLoading); |
| + } |
| + }; |
| + |
| + FileManager.prototype.finishSetupCurrentDirectory_ = function( |
| + path, pageLoading) { |
| + var invokeHandler = pageLoading && !this.params_.selectOnly; |
| // In the FULL_PAGE mode if the hash path points to a file we might have |
| // to invoke a task after selecting it. |
| // If the file path is in params_ we only want to select the file. |
| - if (invokeHandler && location.hash && |
| - this.dialogType_ == FileManager.DialogType.FULL_PAGE) { |
| + if (this.dialogType_ == FileManager.DialogType.FULL_PAGE && |
| + location.hash && invokeHandler) { |
| // To prevent the file list flickering for a moment before the action |
| // is executed we hide it under a white div. |
| var shade; |
| - if (opt_blankWhileOpeningAFile) { |
| + if (pageLoading) { |
| shade = this.document_.createElement('div'); |
| shade.className = 'overlay-pane'; |
| shade.style.backgroundColor = 'white'; |
| @@ -1775,43 +1736,37 @@ FileManager.prototype = { |
| var div = this.document_.createElement('div'); |
| div.className = 'root-label'; |
| - var icon = rootType; |
| - var deviceNumber = this.getDeviceNumber(entry); |
| - |
| - if (deviceNumber != undefined) { |
| - var mountCondition = this.mountPoints_[deviceNumber].mountCondition; |
| - if (mountCondition == 'unknown_filesystem' || |
| - mountCondition == 'unsupported_filesystem') |
| - icon = 'unreadable'; |
| - } |
| - |
| - div.setAttribute('icon', icon); |
| - |
| div.textContent = this.getRootLabel_(entry.fullPath); |
| li.appendChild(div); |
| if (rootType == DirectoryModel.RootType.ARCHIVE || |
| rootType == DirectoryModel.RootType.REMOVABLE) { |
| - if (entry.unmounting) { |
| - li.setAttribute('disabled', 'disabled'); |
| - } else { |
| - var eject = this.document_.createElement('div'); |
| - eject.className = 'root-eject'; |
| - eject.addEventListener('click', function(event) { |
| - event.stopPropagation(); |
| - this.unmountVolume_(entry); |
| - }.bind(this)); |
| - // Block other mouse handlers. |
| - eject.addEventListener('mouseup', function(e) { e.stopPropagation() }); |
| - eject.addEventListener('mousedown', function(e) { e.stopPropagation() }); |
| - li.appendChild(eject); |
| - |
| - cr.ui.contextMenuHandler.setContextMenu(li, this.rootsContextMenu_); |
| - } |
| + var eject = this.document_.createElement('div'); |
| + eject.className = 'root-eject'; |
| + eject.addEventListener('click', function(event) { |
| + event.stopPropagation(); |
| + this.unmountVolume_(entry); |
| + }.bind(this)); |
| + // Block other mouse handlers. |
| + eject.addEventListener('mouseup', function(e) { e.stopPropagation() }); |
| + eject.addEventListener('mousedown', function(e) { e.stopPropagation() }); |
| + li.appendChild(eject); |
| + |
| + cr.ui.contextMenuHandler.setContextMenu(li, this.rootsContextMenu_); |
| } |
| cr.defineProperty(li, 'lead', cr.PropertyKind.BOOL_ATTR); |
| cr.defineProperty(li, 'selected', cr.PropertyKind.BOOL_ATTR); |
| + |
| + var icon = rootType; |
| + var mountCondition = this.volumeManager_.getMountCondition(entry.fullPath); |
| + |
| + if (mountCondition == 'unknown_filesystem' || |
| + mountCondition == 'unsupported_filesystem') { |
| + icon = 'unreadable'; |
| + } |
| + div.setAttribute('icon', icon); |
| + |
| return li; |
| }; |
| @@ -1820,9 +1775,14 @@ FileManager.prototype = { |
| * @param {Entry} entry The entry to unmount. |
| */ |
| FileManager.prototype.unmountVolume_ = function(entry) { |
| - this.directoryModel_.prepareUnmount(entry.fullPath); |
| - this.unmountRequests_.push(entry.fullPath); |
| - chrome.fileBrowserPrivate.removeMount(entry.toURL()); |
| + listItem = this.rootsList_.getListItem(entry); |
| + listItem && listItem.setAttribute('disabled'); |
|
dgozman
2012/05/16 14:31:46
Don't like this syntax.
|
| + var self = this; |
| + this.volumeManager_.unmount(entry.fullPath, function() {}, |
| + function(error) { |
| + listItem && listItem.removeAttribute('disabled'); |
| + self.alert.show(strf('UNMOUNT_FAILED', error.message)); |
| + }); |
| }; |
| FileManager.prototype.updateGDataStyle_ = function( |
| @@ -2200,7 +2160,7 @@ FileManager.prototype = { |
| if (this.isOnGData()) { |
| this.metadataCache_.get(selection.urls, 'gdata', function(props) { |
| selection.allGDataFilesPresent = |
| - props.filter(function(p) {return !p.availableOffline}).length == 0; |
| + props.filter(function(p) {return p && !p.availableOffline}).length == 0; |
|
dgozman
2012/05/16 14:31:46
- long line
- this actually should be |!(p && p.av
|
| this.updateOkButton_(); |
| }.bind(this)); |
| } |
| @@ -2632,105 +2592,16 @@ FileManager.prototype = { |
| return this.directoryModel_.isReadOnly(); |
| }; |
| - /** |
| - * Event handler called when some volume was mounted or unmouted. |
| - */ |
| - FileManager.prototype.onMountCompleted_ = function(event) { |
| - var changeDirectoryTo = null; |
| - |
| - if (event && event.mountType == 'gdata') { |
| - var mounted = (event.eventType == 'mount'); |
| - metrics.recordInterval('Load.GData'); |
| - console.log('GData ' + (mounted ? 'mounted' : 'unmounted')); |
| - if (mounted && event.status == 'success') { |
| - this.gdataMounted_ = true; |
| - this.gdataMountInfo_ = { |
| - 'mountPath': event.mountPath, |
| - 'sourcePath': event.sourcePath, |
| - 'mountType': event.mountType, |
| - 'mountCondition': event.status |
| - }; |
| - // Not calling clearGDataLoadingTimer_ here because we want to keep |
| - // "Loading Google Docs" message until the directory loads. It is OK if |
| - // the timer fires after the mount because onDirectoryChanged_ will hide |
| - // the unmounted panel. |
| - if (this.setupCurrentDirectoryPostponed_) { |
| - this.setupCurrentDirectoryPostponed_(false /* execute */); |
| - } else if (this.isOnGData() && |
| - this.directoryModel_.getCurrentDirEntry().unmounted) { |
| - // We are currently on an unmounted GData directory, force a rescan. |
| - changeDirectoryTo = this.directoryModel_.getCurrentRootPath(); |
| - } |
| - } else { |
| - this.gdataMounted_ = false; |
| - this.gdataMountInfo_ = null; |
| - this.clearGDataLoadingTimer_(); |
| - this.onGDataUnreachable_('GData ' + |
| - (mounted ? ('mount failed: ' + event.status) : 'unmounted')); |
| - if (this.setupCurrentDirectoryPostponed_) { |
| - this.setupCurrentDirectoryPostponed_(true /* cancel */); |
| - // Change to unmounted GData root. |
| - changeDirectoryTo = '/' + DirectoryModel.GDATA_DIRECTORY; |
| - } |
| + // TODO(serya): close tab on unmount. |
| + FileManager.prototype.onVolumeUnmounted_ = function(event) { |
| + if (event.mountPath == dm.getCurrentRootPath()) { |
| + if (this.params_.mountTriggered && !event.requested) { |
| + // TODO(serya): What if 2 USB sticks plugged? |
| + chrome.tabs.getCurrent(function(tab) { |
| + chrome.tabs.remove(tab.id); |
| + }); |
| } |
| } |
| - |
| - chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) { |
| - this.setMountPoints_(mountPoints); |
| - |
| - if (event.eventType == 'mount') { |
| - // Mount request finished - remove it. |
| - // Currently we only request mounts for archive files. |
| - var index = this.mountRequests_.indexOf(event.sourcePath); |
| - if (index != -1) { |
| - this.mountRequests_.splice(index, 1); |
| - if (event.status == 'success') { |
| - // Successful mount requested from this tab, go to the drive root. |
| - changeDirectoryTo = event.mountPath; |
| - } else { |
| - // Request initiated from this tab failed, report the error. |
| - var fileName = event.sourcePath.split('/').pop(); |
| - this.alert.show( |
| - strf('ARCHIVE_MOUNT_FAILED', fileName, event.status)); |
| - } |
| - } |
| - } |
| - |
| - if (event.eventType == 'unmount') { |
| - // Unmount request finished - remove it. |
| - var index = this.unmountRequests_.indexOf(event.mountPath); |
| - if (index != -1) { |
| - this.unmountRequests_.splice(index, 1); |
| - if (event.status != 'success') |
| - this.alert.show(strf('UNMOUNT_FAILED', event.status)); |
| - } |
| - |
| - if (event.status == 'success' && |
| - event.mountPath == this.directoryModel_.getCurrentRootPath()) { |
| - if (this.params_.mountTriggered && index == -1) { |
| - // This device mount was the reason this File Manager instance was |
| - // created. Now the device is unmounted from another instance |
| - // or the user removed the device manually. Close this instance. |
| - // window.close() sometimes doesn't work. |
| - chrome.tabs.getCurrent(function(tab) { |
| - chrome.tabs.remove(tab.id); |
| - }); |
| - return; |
| - } |
| - // Current directory just unmounted. Move to the 'Downloads'. |
| - changeDirectoryTo = this.directoryModel_.getDefaultDirectory(); |
| - } |
| - } |
| - |
| - // Even if something failed root list should be rescanned. |
| - // Failed mounts can "give" us new devices which might be formatted, |
| - // so we have to refresh root list then. |
| - this.directoryModel_.updateRoots(function() { |
| - if (changeDirectoryTo) { |
| - this.directoryModel_.changeDirectory(changeDirectoryTo); |
| - } |
| - }.bind(this), this.gdataMounted_); |
| - }.bind(this)); |
| }; |
| /** |
| @@ -2749,14 +2620,24 @@ FileManager.prototype = { |
| chrome.mediaPlayerPrivate.play(urls, position); |
| } else if (id == 'mount-archive') { |
| var self = this; |
| + var tracker = this.directoryModel_.createDirectoryChangeTracker(); |
| + tracker.start(); |
| this.resolveSelectResults_(urls, function(urls) { |
| for (var index = 0; index < urls.length; ++index) { |
| - // Url in MountCompleted event won't be escaped, so let's make sure |
| - // we don't use escaped one in mountRequests_. |
| - var unescapedUrl = unescape(urls[index]); |
| - chrome.fileBrowserPrivate.addMount(unescapedUrl, 'file', {}, |
| - function(sourcePath) { |
| - self.mountRequests_.push(sourcePath); |
| + var path = /^filesystem:[\w-]*:\/\/[\w]*\/external(\/.*)$/. |
| + exec(urls[index])[1]; |
| + if (!path) |
| + continue; |
| + path = decodeURIComponent(path); |
| + self.volumeManager_.mountArchive(path, function(mountPath) { |
| + console.log('Mounted at: ', mountPath); |
| + tracker.stop(); |
| + if (!tracker.hasChanged) |
| + self.directoryModel_.changeDirectory(mountPath); |
| + }, function(error) { |
| + tracker.stop(); |
| + self.alert.show(strf('ARCHIVE_MOUNT_FAILED', |
| + error.fileName, error.message)); |
| }); |
| } |
| }); |
| @@ -2775,17 +2656,6 @@ FileManager.prototype = { |
| } |
| }; |
| - FileManager.prototype.getDeviceNumber = function(entry) { |
| - if (!entry.isDirectory) return undefined; |
| - for (var i = 0; i < this.mountPoints_.length; i++) { |
| - if (normalizeAbsolutePath(entry.fullPath) == |
| - normalizeAbsolutePath(this.mountPoints_[i].mountPath)) { |
| - return i; |
| - } |
| - } |
| - return undefined; |
| - }; |
| - |
| /** |
| * Show a modal-like file viewer/editor on top of the File Manager UI. |
| * |
| @@ -3383,14 +3253,10 @@ FileManager.prototype = { |
| }; |
| FileManager.prototype.onDirectoryAction = function(entry) { |
| - var deviceNumber = this.getDeviceNumber(entry); |
| - if (deviceNumber != undefined && |
| - this.mountPoints_[deviceNumber].mountCondition == |
| - 'unknown_filesystem') { |
| + var mountCondition = this.volumeManager_.getMountCondition(entry.fullPath); |
| + if (mountCondition == 'unknown_filesystem') { |
| return this.showButter(str('UNKNOWN_FILESYSTEM_WARNING')); |
| - } else if (deviceNumber != undefined && |
| - this.mountPoints_[deviceNumber].mountCondition == |
| - 'unsupported_filesystem') { |
| + } else if (mountCondition == 'unsupported_filesystem') { |
| return this.showButter(str('UNSUPPORTED_FILESYSTEM_WARNING')); |
| } else { |
| return this.directoryModel_.changeDirectory(entry.fullPath); |
| @@ -3464,69 +3330,7 @@ FileManager.prototype = { |
| this.checkFreeSpace_(this.getCurrentDirectory()); |
| this.updateTitle_(); |
| - |
| - if (this.filesystemObserverId_) |
| - this.metadataCache_.removeObserver(this.filesystemObserverId_); |
| - if (this.gdataObserverId_) |
| - this.metadataCache_.removeObserver(this.gdataObserverId_); |
| - |
| - this.filesystemObserverId_ = this.metadataCache_.addObserver( |
| - this.directoryModel_.getCurrentDirEntry(), |
| - MetadataCache.CHILDREN, |
| - 'filesystem', |
| - this.updateMetadataInUI_.bind(this, 'filesystem')); |
| - |
| - if (this.isOnGData()) { |
| - this.gdataObserverId_ = this.metadataCache_.addObserver( |
| - this.directoryModel_.getCurrentDirEntry(), |
| - MetadataCache.CHILDREN, |
| - 'gdata', |
| - this.updateMetadataInUI_.bind(this, 'gdata')); |
| - } |
| - |
| - var self = this; |
| - |
| - if (this.watchedDirectoryUrl_) { |
| - if (this.watchedDirectoryUrl_ != event.previousDirEntry.toURL()) { |
| - console.warn('event.previousDirEntry does not match File Manager state', |
| - event, this.watchedDirectoryUrl_); |
| - } |
| - chrome.fileBrowserPrivate.removeFileWatch(this.watchedDirectoryUrl_, |
| - function(result) { |
| - if (!result) { |
| - console.log('Failed to remove file watch'); |
| - } |
| - }); |
| - this.watchedDirectoryUrl_ = null; |
| - } |
| - |
| - if (event.newDirEntry.fullPath != '/' && !event.newDirEntry.unmounted) { |
| - this.watchedDirectoryUrl_ = event.newDirEntry.toURL(); |
| - chrome.fileBrowserPrivate.addFileWatch(this.watchedDirectoryUrl_, |
| - function(result) { |
| - if (!result) { |
| - console.log('Failed to add file watch'); |
| - this.watchedDirectoryUrl_ = null; |
| - } |
| - }.bind(this)); |
| - } |
| - |
| - if (event.newDirEntry.unmounted) |
| - this.dialogContainer_.setAttribute('unmounted', true); |
| - else { |
| - this.dialogContainer_.removeAttribute('unmounted'); |
| - // Need to resize explicitly because the list container had display:none. |
| - this.onResize_(); |
| - } |
| - |
| - if (this.isOnGData()) { |
| - this.dialogContainer_.setAttribute('gdata', true); |
| - if (event.newDirEntry.unmounted) { |
| - this.initGData_(true /* directory changed */); |
| - } |
| - } else { |
| - this.dialogContainer_.removeAttribute('gdata'); |
| - } |
| + this.updateGDataStatus_('directory-change'); |
| }; |
| FileManager.prototype.findListItemForEvent_ = function(event) { |
| @@ -3545,22 +3349,7 @@ FileManager.prototype = { |
| * return. |
| */ |
| FileManager.prototype.onUnload_ = function() { |
| - if (this.watchedDirectoryUrl_) { |
| - chrome.fileBrowserPrivate.removeFileWatch( |
| - this.watchedDirectoryUrl_, |
| - function(result) { |
| - if (!result) { |
| - console.log('Failed to remove file watch'); |
| - } |
| - }); |
| - this.watchedDirectoryUrl_ = null; |
| - } |
| - }; |
| - |
| - FileManager.prototype.onFileChanged_ = function(event) { |
| - // We receive a lot of events even in folders we are not interested in. |
| - if (encodeURI(event.fileUrl) == this.getCurrentDirectoryURL()) |
| - this.directoryModel_.rescanLater(); |
| + this.fileWatcher_.stop(); |
| }; |
| FileManager.prototype.initiateRename_ = function() { |
| @@ -4486,3 +4275,4 @@ FileManager.prototype = { |
| this.document_.head.appendChild(style); |
| }; |
| })(); |
| + |