diff options
9 files changed, 165 insertions, 194 deletions
diff --git a/chrome/browser/resources/file_manager/background/js/volume_manager.js b/chrome/browser/resources/file_manager/background/js/volume_manager.js index f63f02a..a2f63a6 100644 --- a/chrome/browser/resources/file_manager/background/js/volume_manager.js +++ b/chrome/browser/resources/file_manager/background/js/volume_manager.js @@ -657,22 +657,57 @@ VolumeManager.prototype.getLocationInfo = function(entry) { // TODO(hirono): Specify currect volume. this.getCurrentProfileVolumeInfo(RootType.DRIVE), entry.rootType, - true /* the entry points a root directory. */); + true /* the entry points a root directory. */, + true /* fake entries are read only. */); + } + + // TODO(mtomasz): Find by Entry instead. + var volumeInfo = this.volumeInfoList.findByPath(entry.fullPath); + if (!volumeInfo) + return null; + + var rootPath; + var rootType; + var isReadOnly; + if (volumeInfo.volumeType === util.VolumeType.DRIVE) { + // If the volume is drive, root path can be either mountPath + '/root' or + // mountPath + '/other'. + if ((entry.fullPath + '/').indexOf(volumeInfo.mountPath + '/root/') === 0) { + rootPath = volumeInfo.mountPath + '/root'; + rootType = RootType.DRIVE; + isReadOnly = volumeInfo.isReadOnly || + this.getDriveConnectionState().type === + util.DriveConnectionType.OFFLINE; + } else if ((entry.fullPath + '/').indexOf( + volumeInfo.mountPath + '/other/') === 0) { + rootPath = volumeInfo.mountPath + '/other'; + rootType = RootType.DRIVE_OTHER; + isReadOnly = true; + } else { + throw new Error(entry.fullPath + ' is an invalid drive path.'); + } } else { - return this.getLocationInfoByPath(entry.fullPath); + // Otherwise, root path is same with a mount path of the volume. + rootPath = volumeInfo.mountPath; + switch (volumeInfo.volumeType) { + case util.VolumeType.DOWNLOADS: + rootType = RootType.DOWNLOADS; + break; + case util.VolumeType.REMOVABLE: + rootType = RootType.REMOVABLE; + break; + case util.VolumeType.ARCHIVE: + rootType = RootType.ARCHIVE; + break; + default: + throw new Error('Invalid volume type: ' + volumeInfo.volumeType); + } + isReadOnly = volumeInfo.isReadOnly; } -}; + var isRootEntry = (entry.fullPath.substr(0, rootPath.length) || '/') === + entry.fullPath; -/** - * Obtains location information from a path. - * TODO(hirono): Remove the method before introducing separate file system. - * - * @param {string} path Path. - * @return {EntryLocation} Location information. - */ -VolumeManager.prototype.getLocationInfoByPath = function(path) { - var volumeInfo = this.volumeInfoList.findByPath(path); - return volumeInfo && PathUtil.getLocationInfo(volumeInfo, path); + return new EntryLocation(volumeInfo, rootType, isRootEntry, isReadOnly); }; /** @@ -748,3 +783,71 @@ VolumeManager.prototype.invokeRequestCallbacks_ = function(request, status, callEach(request.errorCallbacks, this, [status]); } }; + +/** + * Location information which shows where the path points in FileManager's + * file system. + * + * @param {!VolumeInfo} volumeInfo Volume information. + * @param {RootType} rootType Root type. + * @param {boolean} isRootEntry Whether the entry is root entry or not. + * @param {boolean} isReadOnly Whether the entry is read only or not. + * @constructor + */ +function EntryLocation(volumeInfo, rootType, isRootEntry, isReadOnly) { + /** + * Volume information. + * @type {!VolumeInfo} + */ + this.volumeInfo = volumeInfo; + + /** + * Root type. + * @type {RootType} + */ + this.rootType = rootType; + + /** + * Whether the entry is root entry or not. + * @type {boolean} + */ + this.isRootEntry = isRootEntry; + + /** + * Whether the location obtained from the fake entry correspond to special + * searches. + * @type {boolean} + */ + this.isSpecialSearchRoot = + this.rootType === RootType.DRIVE_OFFLINE || + this.rootType === RootType.DRIVE_SHARED_WITH_ME || + this.rootType === RootType.DRIVE_RECENT; + + /** + * Whether the location is under Google Drive or a special search root which + * represents a special search from Google Drive. + * @type {boolean} + */ + this.isDriveBased = + this.rootType === RootType.DRIVE || + this.rootType === RootType.DRIVE_SHARED_WITH_ME || + this.rootType === RootType.DRIVE_RECENT || + this.rootType === RootType.DRIVE_OFFLINE; + + /** + * Whether the given path can be a target path of folder shortcut. + * @type {boolean} + */ + this.isEligibleForFolderShortcut = + !this.isSpecialSearchRoot && + !this.isRootEntry && + this.isDriveBased; + + /** + * Whether the entry is read only or not. + * @type {boolean} + */ + this.isReadOnly = isReadOnly; + + Object.freeze(this); +} diff --git a/chrome/browser/resources/file_manager/common/js/path_util.js b/chrome/browser/resources/file_manager/common/js/path_util.js index 04c3b0d..e21c5f6 100644 --- a/chrome/browser/resources/file_manager/common/js/path_util.js +++ b/chrome/browser/resources/file_manager/common/js/path_util.js @@ -402,101 +402,3 @@ PathUtil.splitExtension = function(path) { return [filename, extension]; }; -/** - * Obtains location information from a path. - * - * @param {!VolumeInfo} volumeInfo Volume containing an entry pointed by path. - * @param {string} fullPath Full path. - * @return {EntryLocation} Location information. - */ -PathUtil.getLocationInfo = function(volumeInfo, fullPath) { - var rootPath; - var rootType; - if (volumeInfo.volumeType === util.VolumeType.DRIVE) { - // If the volume is drive, root path can be either mountPath + '/root' or - // mountPath + '/other'. - if ((fullPath + '/').indexOf(volumeInfo.mountPath + '/root/') === 0) { - rootPath = volumeInfo.mountPath + '/root'; - rootType = RootType.DRIVE; - } else if ((fullPath + '/').indexOf( - volumeInfo.mountPath + '/other/') === 0) { - rootPath = volumeInfo.mountPath + '/other'; - rootType = RootType.DRIVE_OTHER; - } else { - throw new Error(fullPath + ' is an invalid drive path.'); - } - } else { - // Otherwise, root path is same with a mount path of the volume. - rootPath = volumeInfo.mountPath; - switch (volumeInfo.volumeType) { - case util.VolumeType.DOWNLOADS: rootType = RootType.DOWNLOADS; break; - case util.VolumeType.REMOVABLE: rootType = RootType.REMOVABLE; break; - case util.VolumeType.ARCHIVE: rootType = RootType.ARCHIVE; break; - default: throw new Error( - 'Invalid volume type: ' + volumeInfo.volumeType); - } - } - var isRootEntry = (fullPath.substr(0, rootPath.length) || '/') === fullPath; - return new EntryLocation(volumeInfo, rootType, isRootEntry); -}; - -/** - * Location information which shows where the path points in FileManager's - * file system. - * - * @param {!VolumeInfo} volumeInfo Volume information. - * @param {RootType} rootType Root type. - * @param {boolean} isRootEntry Whether the entry is root entry or not. - * @constructor - */ -function EntryLocation(volumeInfo, rootType, isRootEntry) { - /** - * Volume information. - * @type {!VolumeInfo} - */ - this.volumeInfo = volumeInfo; - - /** - * Root type. - * @type {RootType} - */ - this.rootType = rootType; - - /** - * Whether the entry is root entry or not. - * @type {boolean} - */ - this.isRootEntry = isRootEntry; - - /** - * Whether the location obtained from the fake entry correspond to special - * searches. - * @type {boolean} - */ - this.isSpecialSearchRoot = - this.rootType === RootType.DRIVE_OFFLINE || - this.rootType === RootType.DRIVE_SHARED_WITH_ME || - this.rootType === RootType.DRIVE_RECENT; - - /** - * Whether the location is under Google Drive or a special search root which - * represents a special search from Google Drive. - * @type {boolean} - */ - this.isDriveBased = - this.rootType === RootType.DRIVE || - this.rootType === RootType.DRIVE_SHARED_WITH_ME || - this.rootType === RootType.DRIVE_RECENT || - this.rootType === RootType.DRIVE_OFFLINE; - - /** - * Whether the given path can be a target path of folder shortcut. - * @type {boolean} - */ - this.isEligibleForFolderShortcut = - !this.isSpecialSearchRoot && - !this.isRootEntry && - this.isDriveBased; - - Object.freeze(this); -} diff --git a/chrome/browser/resources/file_manager/common/js/util.js b/chrome/browser/resources/file_manager/common/js/util.js index 7eb7da3..0230c78 100644 --- a/chrome/browser/resources/file_manager/common/js/util.js +++ b/chrome/browser/resources/file_manager/common/js/util.js @@ -1076,7 +1076,7 @@ util.EntryChangedKind = Object.freeze({ /** * Obtains whether an entry is fake or not. - * @param {Entry|Object} entry Entry of fake entry. + * @param {!Entry|!Object} entry Entry or a fake entry. * @return {boolean} True if the given entry is fake. */ util.isFakeEntry = function(entry) { diff --git a/chrome/browser/resources/file_manager/foreground/js/directory_model.js b/chrome/browser/resources/file_manager/foreground/js/directory_model.js index 48529aa..f866d55 100644 --- a/chrome/browser/resources/file_manager/foreground/js/directory_model.js +++ b/chrome/browser/resources/file_manager/foreground/js/directory_model.js @@ -125,20 +125,12 @@ DirectoryModel.prototype.getCurrentMountPointUrl = function() { }; /** - * @return {boolean} on True if offline. - */ -DirectoryModel.prototype.isDriveOffline = function() { - var connection = this.volumeManager_.getDriveConnectionState(); - return connection.type == util.DriveConnectionType.OFFLINE; -}; - -/** - * TODO(haruki): This actually checks the current root. Fix the method name and - * related code. - * @return {boolean} True if the root for the current directory is read only. + * @return {boolean} True if the current directory is read only. If there is + * no entry set, then returns true. */ DirectoryModel.prototype.isReadOnly = function() { - return this.isPathReadOnly(this.getCurrentRootPath()); + return this.getCurrentDirEntry() ? this.volumeManager_.getLocationInfo( + this.getCurrentDirEntry()).isReadOnly : true; }; /** @@ -156,33 +148,6 @@ DirectoryModel.prototype.isSearching = function() { }; /** - * @param {string} path Path to check. - * @return {boolean} True if the |path| is read only. - */ -DirectoryModel.prototype.isPathReadOnly = function(path) { - // TODO(hidehiko): Migrate this into VolumeInfo. - switch (PathUtil.getRootType(path)) { - case RootType.REMOVABLE: - var volumeInfo = this.volumeManager_.getVolumeInfo(path); - // Returns true if the volume is actually read only, or if an error - // is found during the mounting. - // TODO(hidehiko): Remove "error" check here, by removing error'ed volume - // info from VolumeManager. - return volumeInfo && (volumeInfo.isReadOnly || !!volumeInfo.error); - case RootType.ARCHIVE: - return true; - case RootType.DOWNLOADS: - return false; - case RootType.DRIVE: - // TODO(haruki): Maybe add DRIVE_OFFLINE as well to allow renaming in the - // offline tab. - return this.isDriveOffline(); - default: - return true; - } -}; - -/** * Updates the selection by using the updateFunc and publish the change event. * If updateFunc returns true, it force to dispatch the change event even if the * selection index is not changed. @@ -1032,8 +997,9 @@ DirectoryModel.prototype.search = function(query, // A search initiated from directories in Drive or special search results // should trigger Drive search. var newDirContents; - if (!this.isDriveOffline() && - PathUtil.isDriveBasedPath(currentDirEntry.fullPath)) { + var isDriveOffline = this.volumeManager_.getDriveConnectionState().type === + util.DriveConnectionType.OFFLINE; + if (!isDriveOffline && PathUtil.isDriveBasedPath(currentDirEntry.fullPath)) { // Drive search is performed over the whole drive, so pass drive root as // |directoryEntry|. newDirContents = DirectoryContents.createForDriveSearch( diff --git a/chrome/browser/resources/file_manager/foreground/js/file_manager.js b/chrome/browser/resources/file_manager/foreground/js/file_manager.js index 7d83b96..793d423 100644 --- a/chrome/browser/resources/file_manager/foreground/js/file_manager.js +++ b/chrome/browser/resources/file_manager/foreground/js/file_manager.js @@ -390,7 +390,8 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; new FileTransferController(this.document_, this.fileOperationManager_, this.metadataCache_, - this.directoryModel_); + this.directoryModel_, + this.volumeManager_); controller.attachDragSource(this.table_.list); controller.attachFileListDropTarget(this.table_.list); controller.attachDragSource(this.grid_); @@ -1702,6 +1703,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; }; /** + * TODO(mtomasz): Move this to a utility function working on the root type. * @return {boolean} True if the current directory content is from Google * Drive. */ @@ -1827,28 +1829,10 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; }; /** - * Get the metered status of Drive connection. - * - * @return {boolean} Returns true if drive should limit the traffic because - * the connection is metered and the 'disable-sync-on-metered' setting is - * enabled. Otherwise, returns false. - */ - FileManager.prototype.isDriveOnMeteredConnection = function() { - var connection = this.volumeManager_.getDriveConnectionState(); - return connection.type == util.DriveConnectionType.METERED; - }; - - /** - * Get the online/offline status of drive. - * - * @return {boolean} Returns true if the connection is offline. Otherwise, - * returns false. + * Tells whether the current directory is read only. + * TODO(mtomasz): Remove and use EntryLocation directly. + * @return {boolean} True if read only, false otherwise. */ - FileManager.prototype.isDriveOffline = function() { - var connection = this.volumeManager_.getDriveConnectionState(); - return connection.type == util.DriveConnectionType.OFFLINE; - }; - FileManager.prototype.isOnReadonlyDirectory = function() { return this.directoryModel_.isReadOnly(); }; @@ -1869,7 +1853,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52; }; /** - * Show a modal-like file viewer/editor on top of the File Manager UI. + * Shows a modal-like file viewer/editor on top of the File Manager UI. * * @param {HTMLElement} popup Popup element. * @param {function()} closeCallback Function to call after the popup is diff --git a/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js b/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js index 89b83025..7360cd6 100644 --- a/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js +++ b/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js @@ -420,9 +420,9 @@ CommandHandler.COMMANDS_['format'] = { root = directoryModel.getCurrentDirEntry(); var location = root && fileManager.volumeManager.getLocationInfo(root); var removable = location && location.rootType === RootType.REMOVABLE; - // Don't check if the volume is read-only. Unformatted volume is - // considered read-only per directoryModel.isPathReadOnly(), but can be - // formatted. An error will be raised if formatting failed anyway. + // Don't check if the volume is read-only. Unformatted volume is considered + // read-only per VolumeInfo.isReadOnly, but can be formatted. An error will + // be raised if formatting failed anyway. event.canExecute = removable; event.command.setHidden(!removable); } @@ -720,8 +720,11 @@ CommandHandler.COMMANDS_['share'] = { }, canExecute: function(event, fileManager) { var selection = fileManager.getSelection(); + var isDriveOffline = + fileManager.volumeManager.getDriveConnectionState().type === + util.DriveConnectionType.OFFLINE; event.canExecute = fileManager.isOnDrive() && - !fileManager.isDriveOffline() && + !isDriveOffline && selection && selection.totalCount == 1; event.command.setHidden(!fileManager.isOnDrive()); } diff --git a/chrome/browser/resources/file_manager/foreground/js/file_selection.js b/chrome/browser/resources/file_manager/foreground/js/file_selection.js index 945a48b..5f45669 100644 --- a/chrome/browser/resources/file_manager/foreground/js/file_selection.js +++ b/chrome/browser/resources/file_manager/foreground/js/file_selection.js @@ -313,8 +313,10 @@ FileSelectionHandler.prototype.updateOkButton = function() { * available. */ FileSelectionHandler.prototype.isFileSelectionAvailable = function() { - return !this.fileManager_.isOnDrive() || - !this.fileManager_.isDriveOffline() || + var isDriveOffline = + this.fileManager_.volumeManager.getDriveConnectionState().type === + util.DriveConnectionType.OFFLINE; + return !this.fileManager_.isOnDrive() || !isDriveOffline || this.selection.allDriveFilesPresent; }; diff --git a/chrome/browser/resources/file_manager/foreground/js/file_tasks.js b/chrome/browser/resources/file_manager/foreground/js/file_tasks.js index 1c300a3..3e6bbd7 100644 --- a/chrome/browser/resources/file_manager/foreground/js/file_tasks.js +++ b/chrome/browser/resources/file_manager/foreground/js/file_tasks.js @@ -452,7 +452,10 @@ FileTasks.prototype.checkAvailability_ = function(callback) { var fm = this.fileManager_; var entries = this.entries_; - if (fm.isOnDrive() && fm.isDriveOffline()) { + var isDriveOffline = fm.volumeManager.getDriveConnectionState().type === + util.DriveConnectionType.OFFLINE; + + if (fm.isOnDrive() && isDriveOffline) { fm.metadataCache_.get(entries, 'drive', function(props) { if (areAll(props, 'availableOffline')) { callback(); @@ -475,7 +478,10 @@ FileTasks.prototype.checkAvailability_ = function(callback) { return; } - if (fm.isOnDrive() && fm.isDriveOnMeteredConnection()) { + var isOnMetered = fm.volumeManager.getDriveConnectionState().type === + util.DriveConnectionType.METERED; + + if (fm.isOnDrive() && isOnMetered) { fm.metadataCache_.get(entries, 'drive', function(driveProps) { if (areAll(driveProps, 'availableWhenMetered')) { callback(); diff --git a/chrome/browser/resources/file_manager/foreground/js/file_transfer_controller.js b/chrome/browser/resources/file_manager/foreground/js/file_transfer_controller.js index a1c2799..957f7ce 100644 --- a/chrome/browser/resources/file_manager/foreground/js/file_transfer_controller.js +++ b/chrome/browser/resources/file_manager/foreground/js/file_transfer_controller.js @@ -18,16 +18,19 @@ var DRAG_AND_DROP_GLOBAL_DATA = '__drag_and_drop_global_data'; * instance. * @param {MetadataCache} metadataCache Metadata cache service. * @param {DirectoryModel} directoryModel Directory model instance. + * @param {VolumeManagerWrapper} volumeManager Volume manager instance. * @constructor */ function FileTransferController(doc, fileOperationManager, metadataCache, - directoryModel) { + directoryModel, + volumeManager) { this.document_ = doc; this.fileOperationManager_ = fileOperationManager; this.metadataCache_ = metadataCache; this.directoryModel_ = directoryModel; + this.volumeManager_ = volumeManager; this.directoryModel_.getFileListSelection().addEventListener('change', this.onSelectionChanged_.bind(this)); @@ -575,8 +578,10 @@ FileTransferController.prototype = { * on drive is available to be copied. Otherwise, returns false. */ canCopyOrDrag_: function() { + var isDriveOffline = this.volumeManager_.getDriveConnectionState().type === + util.DriveConnectionType.OFFLINE; if (this.isOnDrive && - this.directoryModel_.isDriveOffline() && + isDriveOffline && !this.allDriveFilesAvailable) return false; return this.selectedEntries_.length > 0; @@ -661,11 +666,8 @@ FileTransferController.prototype = { canPasteOrDrop_: function(dataTransfer, destinationEntry) { if (!destinationEntry) return false; - - // TODO(mtomasz): Migrate from fullPath to LocationInformation. - if (this.directoryModel_.isPathReadOnly(destinationEntry.fullPath)) + if (this.volumeManager_.getLocationInfo(destinationEntry).isReadOnly) return false; - if (!dataTransfer.types || dataTransfer.types.indexOf('fs/tag') === -1) return false; // Unsupported type of content. @@ -747,8 +749,12 @@ FileTransferController.prototype = { // We consider directories not available offline for the purposes of // file transfer since we cannot afford to recursive traversal. this.allDriveFilesAvailable = - entries.filter(function(e) {return e.isDirectory}).length === 0 && - props.filter(function(p) {return !p.availableOffline}).length === 0; + entries.filter(function(e) { + return e.isDirectory; + }).length === 0 && + props.filter(function(p) { + return !p.availableOffline; + }).length === 0; // |Copy| is the only menu item affected by allDriveFilesAvailable. // It could be open right now, update its UI. this.copyCommand_.disabled = !this.canCopyOrDrag_(); @@ -830,9 +836,8 @@ FileTransferController.prototype = { * or copy') to the current modifiers status and the destination. */ selectDropEffect_: function(event, destinationEntry) { - // TODO(mtomasz): Migrate from fullPath to locationInformation. if (!destinationEntry || - this.directoryModel_.isPathReadOnly(destinationEntry.fullPath)) { + this.volumeManager_.getLocationInfo(destinationEntry).isReadOnly) { return 'none'; } if (event.dataTransfer.effectAllowed === 'copyMove' && |