blob: b79bd363502f6256bdee5de3b04ff4f9e93d349f [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* Sets 'hidden' property of a cr.ui.Command instance and dispatches
* 'hiddenChange' event manually so that associated cr.ui.MenuItem can handle
* the event.
* TODO(fukino): Remove this workaround when crbug.com/481941 is fixed.
*
* @param {boolean} value New value of hidden property.
*/
cr.ui.Command.prototype.setHidden = function(value) {
if (value === this.hidden)
return;
var oldValue = this.hidden;
this.hidden = value;
cr.dispatchPropertyChange(this, 'hidden', value, oldValue);
};
/**
* A command.
* @interface
*/
var Command = function() {};
/**
* Handles the execute event.
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps.
*/
Command.prototype.execute = function(event, fileManager) {};
/**
* Handles the can execute event.
* @param {!Event} event Can execute event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps.
*/
Command.prototype.canExecute = function(event, fileManager) {};
/**
* Utility for commands.
*/
var CommandUtil = {};
/**
* Extracts entry on which command event was dispatched.
*
* @param {EventTarget} element Element which is the command event's target.
* @return {Entry} Entry of the found node.
*/
CommandUtil.getCommandEntry = function(element) {
var entries = CommandUtil.getCommandEntries(element);
return entries.length === 0 ? null : entries[0];
};
/**
* Extracts entries on which command event was dispatched.
*
* @param {EventTarget} element Element which is the command event's target.
* @return {!Array<!Entry>} Entries of the found node.
*/
CommandUtil.getCommandEntries = function(element) {
if (element instanceof DirectoryTree) {
// element is a DirectoryTree.
return element.selectedItem ? [element.selectedItem.entry] : [];
} else if (element instanceof DirectoryItem ||
element instanceof ShortcutItem) {
// element are sub items in DirectoryTree.
return element.entry ? [element.entry] : [];
} else if (element instanceof cr.ui.List) {
// element is a normal List (eg. the file list on the right panel).
var entries = element.selectedItems;
// Check if it is Entry or not by checking for toURL().
return entries.some(function(entry) { return !('toURL' in entry); }) ?
[] : entries;
} else {
return [];
}
};
/**
* Extracts a directory which contains entries on which command event was
* dispatched.
*
* @param {EventTarget} element Element which is the command event's target.
* @param {DirectoryModel} directoryModel
* @return {DirectoryEntry|FakeEntry} The extracted parent entry.
*/
CommandUtil.getParentEntry = function(element, directoryModel) {
if (element instanceof DirectoryTree) {
if (!element.selectedItem)
return null;
var parentItem = element.selectedItem.parentItem;
return parentItem ? parentItem.entry : null;
} else if (element instanceof DirectoryItem ||
element instanceof ShortcutItem) {
return element.parentItem ? element.parentItem.entry : null;
} else if (element instanceof cr.ui.List) {
return directoryModel ? directoryModel.getCurrentDirEntry() : null;
} else {
return null;
}
};
/**
* @param {EventTarget} element
* @param {!CommandHandlerDeps} fileManager
* @return {VolumeInfo}
*/
CommandUtil.getElementVolumeInfo = function(element, fileManager) {
if (element instanceof DirectoryTree && element.selectedItem)
return CommandUtil.getElementVolumeInfo(element.selectedItem, fileManager);
if (element instanceof VolumeItem)
return element.volumeInfo;
if (element instanceof ShortcutItem) {
return element.entry && fileManager.volumeManager.getVolumeInfo(
element.entry);
}
return null;
};
/**
* @param {!CommandHandlerDeps} fileManager
* @return {VolumeInfo}
*/
CommandUtil.getCurrentVolumeInfo = function(fileManager) {
var currentDirEntry = fileManager.directoryModel.getCurrentDirEntry();
return currentDirEntry ? fileManager.volumeManager.getVolumeInfo(
currentDirEntry) : null;
};
/**
* Obtains an entry from the give navigation model item.
* @param {!NavigationModelItem} item Navigation model item.
* @return {Entry} Related entry.
* @private
*/
CommandUtil.getEntryFromNavigationModelItem_ = function(item) {
switch (item.type) {
case NavigationModelItemType.VOLUME:
return /** @type {!NavigationModelVolumeItem} */ (
item).volumeInfo.displayRoot;
case NavigationModelItemType.SHORTCUT:
return /** @type {!NavigationModelShortcutItem} */ (item).entry;
}
return null;
};
/**
* Checks if command can be executed on drive.
* @param {!Event} event Command event to mark.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
CommandUtil.canExecuteEnabledOnDriveOnly = function(event, fileManager) {
event.canExecute = fileManager.directoryModel.isOnDrive();
};
/**
* Sets the command as visible only when the current volume is drive and it's
* running as a normal app, not as a modal dialog.
* @param {!Event} event Command event to mark.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
CommandUtil.canExecuteVisibleOnDriveInNormalAppModeOnly = function(
event, fileManager) {
var enabled = fileManager.directoryModel.isOnDrive() &&
!DialogType.isModal(fileManager.dialogType);
event.canExecute = enabled;
event.command.setHidden(!enabled);
};
/**
* Sets as the command as always enabled.
* @param {!Event} event Command event to mark.
*/
CommandUtil.canExecuteAlways = function(event) {
event.canExecute = true;
};
/**
* Sets the default handler for the commandId and prevents handling
* the keydown events for this command. Not doing that breaks relationship
* of original keyboard event and the command. WebKit would handle it
* differently in some cases.
* @param {Node} node to register command handler on.
* @param {string} commandId Command id to respond to.
*/
CommandUtil.forceDefaultHandler = function(node, commandId) {
var doc = node.ownerDocument;
var command = doc.querySelector('command[id="' + commandId + '"]');
node.addEventListener('keydown', function(e) {
if (command.matchesEvent(e)) {
// Prevent cr.ui.CommandManager of handling it and leave it
// for the default handler.
e.stopPropagation();
}
});
node.addEventListener('command', function(event) {
if (event.command.id !== commandId)
return;
document.execCommand(event.command.id);
event.cancelBubble = true;
});
node.addEventListener('canExecute', function(event) {
if (event.command.id !== commandId)
return;
event.canExecute = document.queryCommandEnabled(event.command.id);
event.command.setHidden(false);
});
};
/**
* Default command.
* @type {Command}
*/
CommandUtil.defaultCommand = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
fileManager.document.execCommand(event.command.id);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
event.canExecute = fileManager.document.queryCommandEnabled(
event.command.id);
}
});
/**
* Creates the volume switch command with index.
* @param {number} index Volume index from 1 to 9.
* @return {Command} Volume switch command.
*/
CommandUtil.createVolumeSwitchCommand = function(index) {
return /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
fileManager.directoryTree.activateByIndex(index - 1);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
event.canExecute = index > 0 &&
index <= fileManager.directoryTree.items.length;
}
});
};
/**
* Returns a directory entry when only one entry is selected and it is
* directory. Otherwise, returns null.
* @param {FileSelection} selection Instance of FileSelection.
* @return {?DirectoryEntry} Directory entry which is selected alone.
*/
CommandUtil.getOnlyOneSelectedDirectory = function(selection) {
if (!selection)
return null;
if (selection.totalCount !== 1)
return null;
if (!selection.entries[0].isDirectory)
return null;
return /** @type {!DirectoryEntry} */(selection.entries[0]);
};
/**
* Returns true if the given entry is the root entry of the volume.
* @param {VolumeManagerWrapper} volumeManager
* @param {(!Entry|!FakeEntry)} entry Entry or a fake entry.
* @return {boolean} True if the entry is a root entry.
*/
CommandUtil.isRootEntry = function(volumeManager, entry) {
if (!volumeManager || !entry)
return false;
var volumeInfo = volumeManager.getVolumeInfo(entry);
return !!volumeInfo && volumeInfo.displayRoot === entry;
};
/**
* Returns true if the given event was triggered by the selection menu button.
* @event {!Event} event Command event.
* @return {boolean} Ture if the event was triggered by the selection menu
* button.
*/
CommandUtil.isFromSelectionMenu = function(event) {
return event.target.id == 'selection-menu-button';
};
/**
* If entry is fake/invalid/root, we don't show menu items for regular entries.
* @param {VolumeManagerWrapper} volumeManager
* @param {(!Entry|!FakeEntry)} entry Entry or a fake entry.
* @return {boolean} True if we should show the menu items for regular entries.
*/
CommandUtil.shouldShowMenuItemsForEntry = function(volumeManager, entry) {
// If the entry is fake entry, hide context menu entries.
if (util.isFakeEntry(entry))
return false;
// If the entry is not a valid entry, hide context menu entries.
if (!volumeManager || !volumeManager.getVolumeInfo(entry))
return false;
// If the entry is root entry of its volume, hide context menu entries.
if (CommandUtil.isRootEntry(volumeManager, entry))
return false;
if (util.isTeamDrivesGrandRoot(entry) || util.isTeamDriveRoot(entry))
return false;
return true;
};
/**
* Handle of the command events.
* @param {!CommandHandlerDeps} fileManager Classes |CommandHalder| depends.
* @param {!FileSelectionHandler} selectionHandler
* @constructor
* @struct
*/
var CommandHandler = function(fileManager, selectionHandler) {
/**
* CommandHandlerDeps.
* @type {!CommandHandlerDeps}
* @private
*/
this.fileManager_ = fileManager;
/**
* Command elements.
* @type {Object<cr.ui.Command>}
* @private
*/
this.commands_ = {};
// Decorate command tags in the document.
var commands = fileManager.document.querySelectorAll('command');
for (var i = 0; i < commands.length; i++) {
cr.ui.Command.decorate(commands[i]);
this.commands_[commands[i].id] = commands[i];
}
// Register events.
fileManager.document.addEventListener('command', this.onCommand_.bind(this));
fileManager.document.addEventListener(
'canExecute', this.onCanExecute_.bind(this));
fileManager.directoryModel.addEventListener(
'directory-change', this.updateAvailability.bind(this));
fileManager.volumeManager.addEventListener(
'drive-connection-changed', this.updateAvailability.bind(this));
selectionHandler.addEventListener(
FileSelectionHandler.EventType.CHANGE_THROTTLED,
this.updateAvailability.bind(this));
chrome.commandLinePrivate.hasSwitch(
'enable-external-drive-rename', function(enabled) {
CommandHandler.IS_EXTERNAL_DISK_RENAME_ENABLED_ = enabled;
}.bind(this));
};
/**
* Supported disk file system types for renaming.
* @type {boolean}
* @private
*/
CommandHandler.IS_EXTERNAL_DISK_RENAME_ENABLED_ = false;
/**
* Supported disk file system types for renaming.
* @type {!Array<!VolumeManagerCommon.FileSystemType>}
* @const
* @private
*/
CommandHandler.RENAME_DISK_FILE_SYSYTEM_SUPPORT_ = [
VolumeManagerCommon.FileSystemType.EXFAT,
VolumeManagerCommon.FileSystemType.VFAT
];
/**
* Updates the availability of all commands.
*/
CommandHandler.prototype.updateAvailability = function() {
for (var id in this.commands_) {
this.commands_[id].canExecuteChange();
}
};
/**
* Checks if the handler should ignore the current event, eg. since there is
* a popup dialog currently opened.
*
* @return {boolean} True if the event should be ignored, false otherwise.
* @private
*/
CommandHandler.prototype.shouldIgnoreEvents_ = function() {
// Do not handle commands, when a dialog is shown. Do not use querySelector
// as it's much slower, and this method is executed often.
var dialogs = this.fileManager_.document.getElementsByClassName(
'cr-dialog-container');
if (dialogs.length !== 0 && dialogs[0].classList.contains('shown'))
return true;
return false; // Do not ignore.
};
/**
* Handles command events.
* @param {!Event} event Command event.
* @private
*/
CommandHandler.prototype.onCommand_ = function(event) {
if (this.shouldIgnoreEvents_())
return;
var handler = CommandHandler.COMMANDS_[event.command.id];
handler.execute.call(/** @type {Command} */ (handler), event,
this.fileManager_);
};
/**
* Handles canExecute events.
* @param {!Event} event Can execute event.
* @private
*/
CommandHandler.prototype.onCanExecute_ = function(event) {
if (this.shouldIgnoreEvents_())
return;
var handler = CommandHandler.COMMANDS_[event.command.id];
handler.canExecute.call(/** @type {Command} */ (handler), event,
this.fileManager_);
};
/**
* Commands.
* @type {Object<Command>}
* @const
* @private
*/
CommandHandler.COMMANDS_ = {};
/**
* Unmounts external drive.
* @type {Command}
*/
CommandHandler.COMMANDS_['unmount'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager The file manager instance.
*/
execute: function(event, fileManager) {
var errorCallback = function() {
fileManager.ui.alertDialog.showHtml(
'', str('UNMOUNT_FAILED'), null, null, null);
};
var volumeInfo =
CommandUtil.getElementVolumeInfo(event.target, fileManager) ||
CommandUtil.getCurrentVolumeInfo(fileManager);
if (!volumeInfo) {
errorCallback();
return;
}
fileManager.volumeManager.unmount(volumeInfo, function() {}, errorCallback);
},
/**
* @param {!Event} event Command event.
* @this {CommandHandler}
*/
canExecute: function(event, fileManager) {
var volumeInfo =
CommandUtil.getElementVolumeInfo(event.target, fileManager) ||
CommandUtil.getCurrentVolumeInfo(fileManager);
if (!volumeInfo) {
event.canExecute = false;
event.command.setHidden(true);
return;
}
var volumeType = volumeInfo.volumeType;
event.canExecute = (
volumeType === VolumeManagerCommon.VolumeType.ARCHIVE ||
volumeType === VolumeManagerCommon.VolumeType.REMOVABLE ||
volumeType === VolumeManagerCommon.VolumeType.PROVIDED);
event.command.setHidden(!event.canExecute);
switch (volumeType) {
case VolumeManagerCommon.VolumeType.ARCHIVE:
case VolumeManagerCommon.VolumeType.PROVIDED:
event.command.label = str('CLOSE_VOLUME_BUTTON_LABEL');
break;
case VolumeManagerCommon.VolumeType.REMOVABLE:
event.command.label = str('UNMOUNT_DEVICE_BUTTON_LABEL');
break;
}
}
});
/**
* Formats external drive.
* @type {Command}
*/
CommandHandler.COMMANDS_['format'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager The file manager instance.
*/
execute: function(event, fileManager) {
var directoryModel = fileManager.directoryModel;
var root = CommandUtil.getCommandEntry(event.target);
// If an entry is not found from the event target, use the current
// directory. This can happen for the format button for unsupported and
// unrecognized volumes.
if (!root)
root = directoryModel.getCurrentDirEntry();
var volumeInfo = fileManager.volumeManager.getVolumeInfo(root);
if (volumeInfo) {
fileManager.ui.confirmDialog.show(
loadTimeData.getString('FORMATTING_WARNING'),
chrome.fileManagerPrivate.formatVolume.bind(null,
volumeInfo.volumeId),
null, null);
}
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager The file manager instance.
*/
canExecute: function(event, fileManager) {
var directoryModel = fileManager.directoryModel;
var root = CommandUtil.getCommandEntry(event.target);
// |root| is null for unrecognized volumes. Enable format command for such
// volumes.
var isUnrecognizedVolume = (root == null);
// See the comment in execute() for why doing this.
if (!root)
root = directoryModel.getCurrentDirEntry();
var location = root && fileManager.volumeManager.getLocationInfo(root);
var writable = location && !location.isReadOnly;
var removable = location && location.rootType ===
VolumeManagerCommon.RootType.REMOVABLE;
event.canExecute = removable && (isUnrecognizedVolume || writable);
event.command.setHidden(!removable);
}
});
/**
* Initiates new folder creation.
* @type {Command}
*/
CommandHandler.COMMANDS_['new-folder'] = (function() {
/**
* @constructor
* @struct
*/
var NewFolderCommand = function() {};
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
NewFolderCommand.prototype.execute = function(event, fileManager) {
var targetDirectory;
var executedFromDirectoryTree;
if (event.target instanceof DirectoryTree) {
targetDirectory = event.target.selectedItem.entry;
executedFromDirectoryTree = true;
} else if (event.target instanceof DirectoryItem) {
targetDirectory = event.target.entry;
executedFromDirectoryTree = true;
} else {
targetDirectory = fileManager.directoryModel.getCurrentDirEntry();
executedFromDirectoryTree = false;
}
var directoryModel = fileManager.directoryModel;
var directoryTree = fileManager.ui.directoryTree;
var listContainer = fileManager.ui.listContainer;
this.generateNewDirectoryName_(targetDirectory).then(function(newName) {
if (!executedFromDirectoryTree)
listContainer.startBatchUpdates();
return new Promise(targetDirectory.getDirectory.bind(targetDirectory,
newName,
{create: true, exclusive: true})).then(function(newDirectory) {
metrics.recordUserAction('CreateNewFolder');
// Select new directory and start rename operation.
if (executedFromDirectoryTree) {
directoryTree.updateAndSelectNewDirectory(
targetDirectory, newDirectory);
fileManager.directoryTreeNamingController.attachAndStart(
assert(fileManager.ui.directoryTree.selectedItem), false,
null);
} else {
directoryModel.updateAndSelectNewDirectory(
newDirectory).then(function() {
listContainer.endBatchUpdates();
fileManager.namingController.initiateRename();
}, function() {
listContainer.endBatchUpdates();
});
}
}, function(error) {
if (!executedFromDirectoryTree)
listContainer.endBatchUpdates();
fileManager.ui.alertDialog.show(
strf('ERROR_CREATING_FOLDER',
newName,
util.getFileErrorString(error.name)),
null, null);
});
});
};
/**
* Generates new directory name.
* @param {!DirectoryEntry} parentDirectory
* @param {number=} opt_index
* @private
*/
NewFolderCommand.prototype.generateNewDirectoryName_ = function(
parentDirectory, opt_index) {
var index = opt_index || 0;
var defaultName = str('DEFAULT_NEW_FOLDER_NAME');
var newName = index === 0 ? defaultName :
defaultName + ' (' + index + ')';
return new Promise(parentDirectory.getDirectory.bind(
parentDirectory, newName, {create: false})).then(function(newEntry) {
return this.generateNewDirectoryName_(parentDirectory, index + 1);
}.bind(this)).catch(function() {
return newName;
});
};
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
NewFolderCommand.prototype.canExecute = function(event, fileManager) {
if (event.target instanceof DirectoryItem ||
event.target instanceof DirectoryTree) {
var entry = CommandUtil.getCommandEntry(event.target);
if (!entry || util.isFakeEntry(entry) ||
util.isTeamDrivesGrandRoot(entry)) {
event.canExecute = false;
event.command.setHidden(true);
return;
}
var locationInfo = fileManager.volumeManager.getLocationInfo(entry);
event.canExecute = locationInfo && !locationInfo.isReadOnly;
event.command.setHidden(
CommandUtil.isRootEntry(fileManager.volumeManager, entry));
} else {
var directoryModel = fileManager.directoryModel;
event.canExecute = !fileManager.directoryModel.isReadOnly() &&
!fileManager.namingController.isRenamingInProgress() &&
!directoryModel.isSearching() && !directoryModel.isScanning();
event.command.setHidden(false);
}
};
return new NewFolderCommand();
})();
/**
* Initiates new window creation.
* @type {Command}
*/
CommandHandler.COMMANDS_['new-window'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
fileManager.backgroundPage.launcher.launchFileManager({
currentDirectoryURL: fileManager.getCurrentDirectoryEntry() &&
fileManager.getCurrentDirectoryEntry().toURL()
});
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
event.canExecute =
fileManager.getCurrentDirectoryEntry() &&
(fileManager.dialogType === DialogType.FULL_PAGE);
}
});
CommandHandler.COMMANDS_['toggle-hidden-files'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
var isFilterHiddenOn = !fileManager.fileFilter.isFilterHiddenOn();
fileManager.fileFilter.setFilterHidden(isFilterHiddenOn);
event.command.checked = /* is show hidden files */!isFilterHiddenOn;
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: CommandUtil.canExecuteAlways
});
/**
* Toggles drive sync settings.
* @type {Command}
*/
CommandHandler.COMMANDS_['drive-sync-settings'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
// If checked, the sync is disabled.
var nowCellularDisabled =
fileManager.ui.gearMenu.syncButton.hasAttribute('checked');
var changeInfo = {cellularDisabled: !nowCellularDisabled};
chrome.fileManagerPrivate.setPreferences(changeInfo);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
event.canExecute = fileManager.directoryModel.isOnDrive() &&
fileManager.volumeManager.getDriveConnectionState()
.hasCellularNetworkAccess;
event.command.setHidden(!event.canExecute);
}
});
/**
* Toggles drive hosted settings.
* @type {Command}
*/
CommandHandler.COMMANDS_['drive-hosted-settings'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
// If checked, showing drive hosted files is enabled.
var nowHostedFilesEnabled =
fileManager.ui.gearMenu.hostedButton.hasAttribute('checked');
var nowHostedFilesDisabled = !nowHostedFilesEnabled;
/*
var changeInfo = {hostedFilesDisabled: !nowHostedFilesDisabled};
*/
var changeInfo = {};
changeInfo['hostedFilesDisabled'] = !nowHostedFilesDisabled;
chrome.fileManagerPrivate.setPreferences(changeInfo);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
event.canExecute = fileManager.directoryModel.isOnDrive();
event.command.setHidden(!event.canExecute);
}
});
/**
* Deletes selected files.
* @type {Command}
*/
CommandHandler.COMMANDS_['delete'] = (function() {
/**
* @constructor
* @implements {Command}
*/
var DeleteCommand = function() {};
DeleteCommand.prototype = {
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
var entries = CommandUtil.getCommandEntries(event.target);
// Execute might be called without a call of canExecute method,
// e.g. called directly from code. Double check here not to delete
// undeletable entries.
if (!entries.every(CommandUtil.shouldShowMenuItemsForEntry.bind(
null, fileManager.volumeManager)) ||
this.containsReadOnlyEntry_(entries, fileManager))
return;
var message = entries.length === 1 ?
strf('GALLERY_CONFIRM_DELETE_ONE', entries[0].name) :
strf('GALLERY_CONFIRM_DELETE_SOME', entries.length);
fileManager.ui.deleteConfirmDialog.show(message, function() {
fileManager.fileOperationManager.deleteEntries(entries);
}, null, null);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
var entries = CommandUtil.getCommandEntries(event.target);
// If entries contain fake or root entry, hide delete option.
if (!entries.every(CommandUtil.shouldShowMenuItemsForEntry.bind(
null, fileManager.volumeManager))) {
event.canExecute = false;
event.command.setHidden(true);
return;
}
event.canExecute = entries.length > 0 &&
!this.containsReadOnlyEntry_(entries, fileManager);
event.command.setHidden(false);
},
/**
* @param {!Array<!Entry>} entries
* @param {!CommandHandlerDeps} fileManager
* @return {boolean} True if entries contain read only entry.
*/
containsReadOnlyEntry_: function(entries, fileManager) {
return entries.some(function(entry) {
var locationInfo = fileManager.volumeManager.getLocationInfo(entry);
return locationInfo && locationInfo.isReadOnly;
});
}
};
return new DeleteCommand();
})();
/**
* Pastes files from clipboard.
* @type {Command}
*/
CommandHandler.COMMANDS_['paste'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
fileManager.document.execCommand(event.command.id);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
var fileTransferController = fileManager.fileTransferController;
event.canExecute = !!fileTransferController &&
fileTransferController.queryPasteCommandEnabled(
fileManager.directoryModel.getCurrentDirEntry());
// Hide this command if only one folder is selected.
event.command.setHidden(!!CommandUtil.getOnlyOneSelectedDirectory(
fileManager.getSelection()));
}
});
/**
* Pastes files from clipboard into the selected folder.
* @type {Command}
*/
CommandHandler.COMMANDS_['paste-into-folder'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
var entries = CommandUtil.getCommandEntries(event.target);
if (entries.length !== 1 || !entries[0].isDirectory ||
!CommandUtil.shouldShowMenuItemsForEntry(
fileManager.volumeManager, entries[0])) {
return;
}
// This handler tweaks the Event object for 'paste' event so that
// the FileTransferController can distinguish this 'paste-into-folder'
// command and know the destination directory.
var handler = function(inEvent) {
inEvent.destDirectory = entries[0];
};
fileManager.document.addEventListener('paste', handler, true);
fileManager.document.execCommand('paste');
fileManager.document.removeEventListener('paste', handler, true);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
var entries = CommandUtil.getCommandEntries(event.target);
// Show this item only when one directory is selected.
if (entries.length !== 1 || !entries[0].isDirectory ||
!CommandUtil.shouldShowMenuItemsForEntry(
fileManager.volumeManager, entries[0])) {
event.canExecute = false;
event.command.setHidden(true);
return;
}
var fileTransferController = fileManager.fileTransferController;
var directoryEntry = /** @type {DirectoryEntry|FakeEntry} */ (entries[0]);
event.canExecute = !!fileTransferController &&
fileTransferController.queryPasteCommandEnabled(directoryEntry);
event.command.setHidden(false);
}
});
CommandHandler.COMMANDS_['cut'] = CommandUtil.defaultCommand;
CommandHandler.COMMANDS_['copy'] = CommandUtil.defaultCommand;
/**
* Initiates file renaming.
* @type {Command}
*/
CommandHandler.COMMANDS_['rename'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
if (event.target instanceof DirectoryTree ||
event.target instanceof DirectoryItem) {
var isRemovableRoot = false;
var entry = CommandUtil.getCommandEntry(event.target);
if (entry) {
var volumeInfo = fileManager.volumeManager.getVolumeInfo(entry);
// Checks whether the target is actually external drive or just a folder
// inside the drive.
if (volumeInfo &&
CommandUtil.isRootEntry(fileManager.volumeManager, entry)) {
isRemovableRoot = true;
}
}
if (event.target instanceof DirectoryTree) {
var directoryTree = event.target;
assert(fileManager.directoryTreeNamingController)
.attachAndStart(
assert(directoryTree.selectedItem), isRemovableRoot,
volumeInfo);
} else if (event.target instanceof DirectoryItem) {
var directoryItem = event.target;
assert(fileManager.directoryTreeNamingController)
.attachAndStart(directoryItem, isRemovableRoot, volumeInfo);
}
} else {
fileManager.namingController.initiateRename();
}
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
// TODO(klemenko): Remove flag below when 274041 gets implemented.
if (CommandHandler.IS_EXTERNAL_DISK_RENAME_ENABLED_) {
// Check if it is removable drive
var root = CommandUtil.getCommandEntry(event.target);
// |root| is null for unrecognized volumes. Do not enable rename command
// for such volumes because they need to be formatted prior to rename.
if (root != null) {
var location = root && fileManager.volumeManager.getLocationInfo(root);
var volumeInfo = fileManager.volumeManager.getVolumeInfo(root);
var writable = location && !location.isReadOnly;
var removable = writable &&
location.rootType === VolumeManagerCommon.RootType.REMOVABLE;
var canExecute = removable && writable && volumeInfo &&
CommandHandler.RENAME_DISK_FILE_SYSYTEM_SUPPORT_.indexOf(
volumeInfo.diskFileSystemType) > -1;
event.canExecute = canExecute;
event.command.setHidden(!removable);
if (removable)
return;
}
}
// Check if it is file or folder
var renameTarget = CommandUtil.isFromSelectionMenu(event) ?
fileManager.ui.listContainer.currentList :
event.target;
var entries = CommandUtil.getCommandEntries(renameTarget);
if (entries.length === 0 ||
!CommandUtil.shouldShowMenuItemsForEntry(
fileManager.volumeManager, entries[0])) {
event.canExecute = false;
event.command.setHidden(true);
return;
}
var parentEntry =
CommandUtil.getParentEntry(renameTarget, fileManager.directoryModel);
var locationInfo = parentEntry ?
fileManager.volumeManager.getLocationInfo(parentEntry) : null;
event.canExecute =
entries.length === 1 && !!locationInfo && !locationInfo.isReadOnly;
event.command.setHidden(false);
}
});
/**
* Opens drive help.
* @type {Command}
*/
CommandHandler.COMMANDS_['volume-help'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
if (fileManager.directoryModel.isOnDrive())
util.visitURL(str('GOOGLE_DRIVE_HELP_URL'));
else
util.visitURL(str('FILES_APP_HELP_URL'));
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
// Hides the help menu in modal dialog mode. It does not make much sense
// because after all, users cannot view the help without closing, and
// besides that the help page is about the Files app as an app, not about
// the dialog mode itself. It can also lead to hard-to-fix bug
// crbug.com/339089.
var hideHelp = DialogType.isModal(fileManager.dialogType);
event.canExecute = !hideHelp;
event.command.setHidden(hideHelp);
fileManager.document.getElementById('help-separator').hidden = hideHelp;
}
});
/**
* Opens drive buy-more-space url.
* @type {Command}
*/
CommandHandler.COMMANDS_['drive-buy-more-space'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
util.visitURL(str('GOOGLE_DRIVE_BUY_STORAGE_URL'));
},
canExecute: CommandUtil.canExecuteVisibleOnDriveInNormalAppModeOnly
});
/**
* Opens drive.google.com.
* @type {Command}
*/
CommandHandler.COMMANDS_['drive-go-to-drive'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
util.visitURL(str('GOOGLE_DRIVE_ROOT_URL'));
},
canExecute: CommandUtil.canExecuteVisibleOnDriveInNormalAppModeOnly
});
/**
* Opens a file with default task.
* @type {Command}
*/
CommandHandler.COMMANDS_['default-task'] = /** @type {Command} */ ({
execute: function(event, fileManager) {
fileManager.taskController.executeDefaultTask();
},
canExecute: function(event, fileManager) {
var canExecute = fileManager.taskController.canExecuteDefaultTask();
event.canExecute = canExecute;
event.command.setHidden(!canExecute);
}
});
/**
* Displays "open with" dialog for current selection.
* @type {Command}
*/
CommandHandler.COMMANDS_['open-with'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
fileManager.taskController.getFileTasks()
.then(function(tasks) {
tasks.showTaskPicker(
fileManager.ui.defaultTaskPicker, str('OPEN_WITH_BUTTON_LABEL'),
'', function(task) {
tasks.execute(task.taskId);
}, FileTasks.TaskPickerType.OpenWith);
})
.catch(function(error) {
if (error)
console.error(error.stack || error);
});
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
var canExecute = fileManager.taskController.canExecuteOpenActions();
event.canExecute = canExecute;
event.command.setHidden(!canExecute);
}
});
/**
* Displays "More actions" dialog for current selection.
* @type {Command}
*/
CommandHandler.COMMANDS_['more-actions'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
fileManager.taskController.getFileTasks()
.then(function(tasks) {
tasks.showTaskPicker(
fileManager.ui.defaultTaskPicker,
str('MORE_ACTIONS_BUTTON_LABEL'), '', function(task) {
tasks.execute(task.taskId);
}, FileTasks.TaskPickerType.MoreActions);
})
.catch(function(error) {
if (error)
console.error(error.stack || error);
});
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
var canExecute = fileManager.taskController.canExecuteMoreActions();
event.canExecute = canExecute;
event.command.setHidden(!canExecute);
}
});
/**
* Displays QuickView for current selection.
* @type {Command}
*/
CommandHandler.COMMANDS_['get-info'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager fileManager to use.
*/
execute: function(event, fileManager) {
// 'get-info' command is executed by 'command' event handler in
// QuickViewController.
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
// QuickViewModel refers the file selection instead of event target.
var entries = fileManager.getSelection().entries;
if (entries.length === 0) {
event.canExecute = false;
event.command.setHidden(true);
return;
}
event.canExecute = entries.length === 1;
event.command.setHidden(false);
}
});
/**
* Focuses search input box.
* @type {Command}
*/
CommandHandler.COMMANDS_['search'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
// Cancel item selection.
fileManager.directoryModel.clearSelection();
// Focus the search box.
var element = fileManager.document.querySelector('#search-box input');
element.focus();
element.select();
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
event.canExecute = !fileManager.namingController.isRenamingInProgress();
}
});
/**
* Activates the n-th volume.
* @type {Command}
*/
CommandHandler.COMMANDS_['volume-switch-1'] =
CommandUtil.createVolumeSwitchCommand(1);
CommandHandler.COMMANDS_['volume-switch-2'] =
CommandUtil.createVolumeSwitchCommand(2);
CommandHandler.COMMANDS_['volume-switch-3'] =
CommandUtil.createVolumeSwitchCommand(3);
CommandHandler.COMMANDS_['volume-switch-4'] =
CommandUtil.createVolumeSwitchCommand(4);
CommandHandler.COMMANDS_['volume-switch-5'] =
CommandUtil.createVolumeSwitchCommand(5);
CommandHandler.COMMANDS_['volume-switch-6'] =
CommandUtil.createVolumeSwitchCommand(6);
CommandHandler.COMMANDS_['volume-switch-7'] =
CommandUtil.createVolumeSwitchCommand(7);
CommandHandler.COMMANDS_['volume-switch-8'] =
CommandUtil.createVolumeSwitchCommand(8);
CommandHandler.COMMANDS_['volume-switch-9'] =
CommandUtil.createVolumeSwitchCommand(9);
/**
* Flips 'available offline' flag on the file.
* @type {Command}
*/
CommandHandler.COMMANDS_['toggle-pinned'] = /** @type {Command} */ ({
/**
* @param {!Event} event
* @param {!CommandHandlerDeps} fileManager
*/
execute: function(event, fileManager) {
var actionsModel = fileManager.actionsController.getActionsModelFor(
event.target);
var saveForOfflineAction = actionsModel ? actionsModel.getAction(
ActionsModel.CommonActionId.SAVE_FOR_OFFLINE) : null;
var offlineNotNeededAction = actionsModel ? actionsModel.getAction(
ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY) : null;
// Saving for offline has a priority if both actions are available.
var action = saveForOfflineAction || offlineNotNeededAction;
if (action)
action.execute();
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
var actionsModel = fileManager.actionsController.getActionsModelFor(
event.target);
var saveForOfflineAction = actionsModel ? actionsModel.getAction(
ActionsModel.CommonActionId.SAVE_FOR_OFFLINE) : null;
var offlineNotNeededAction = actionsModel ? actionsModel.getAction(
ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY) : null;
var action = saveForOfflineAction || offlineNotNeededAction;
event.canExecute = action && action.canExecute();
// If model is not computed yet, then keep the previous visibility to avoid
// flickering.
if (actionsModel) {
event.command.setHidden(actionsModel && !action);
event.command.checked = !!offlineNotNeededAction;
}
}
});
/**
* Creates zip file for current selection.
* @type {Command}
*/
CommandHandler.COMMANDS_['zip-selection'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
var dirEntry = fileManager.getCurrentDirectoryEntry();
if (!dirEntry)
return;
var selectionEntries = fileManager.getSelection().entries;
fileManager.fileOperationManager.zipSelection(
/** @type {!DirectoryEntry} */ (dirEntry), selectionEntries);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
var dirEntry = fileManager.getCurrentDirectoryEntry();
var selection = fileManager.getSelection();
event.canExecute = dirEntry && !fileManager.directoryModel.isReadOnly() &&
!fileManager.directoryModel.isOnDrive() &&
!fileManager.directoryModel.isOnMTP() && selection &&
selection.totalCount > 0;
}
});
/**
* Shows the share dialog for the current selection (single only).
* @type {Command}
*/
CommandHandler.COMMANDS_['share'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
// To toolbar buttons are always related to the file list, even though the
// focus is on the navigation list. This assumption will break once we add
// Share to the context menu on the navigation list. crbug.com/530418
var actionsModel = fileManager.actionsController.getActionsModelForContext(
ActionsController.Context.FILE_LIST);
var action = actionsModel ? actionsModel.getAction(
ActionsModel.CommonActionId.SHARE) : null;
if (action)
action.execute();
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
var actionsModel = fileManager.actionsController.getActionsModelForContext(
ActionsController.Context.FILE_LIST);
var action = actionsModel ? actionsModel.getAction(
ActionsModel.CommonActionId.SHARE) : null;
event.canExecute = action && action.canExecute();
// If model is not computed yet, then keep the previous visibility to avoid
// flickering.
if (actionsModel)
event.command.setHidden(actionsModel && !action);
}
});
/**
* Creates a shortcut of the selected folder (single only).
* @type {Command}
*/
CommandHandler.COMMANDS_['create-folder-shortcut'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager The file manager instance.
*/
execute: function(event, fileManager) {
var actionsModel = fileManager.actionsController.getActionsModelFor(
event.target);
var action = actionsModel ? actionsModel.getAction(
ActionsModel.InternalActionId.CREATE_FOLDER_SHORTCUT) : null;
if (action)
action.execute();
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
var actionsModel = fileManager.actionsController.getActionsModelFor(
event.target);
var action = actionsModel ? actionsModel.getAction(
ActionsModel.InternalActionId.CREATE_FOLDER_SHORTCUT) : null;
event.canExecute = action && action.canExecute();
if (actionsModel)
event.command.setHidden(!action);
}
});
/**
* Removes the folder shortcut.
* @type {Command}
*/
CommandHandler.COMMANDS_['remove-folder-shortcut'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager The file manager instance.
*/
execute: function(event, fileManager) {
var actionsModel = fileManager.actionsController.getActionsModelFor(
event.target);
var action = actionsModel ? actionsModel.getAction(
ActionsModel.InternalActionId.REMOVE_FOLDER_SHORTCUT) : null;
if (action)
action.execute();
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
var actionsModel = fileManager.actionsController.getActionsModelFor(
event.target);
var action = actionsModel ? actionsModel.getAction(
ActionsModel.InternalActionId.REMOVE_FOLDER_SHORTCUT) : null;
event.canExecute = action && action.canExecute();
if (actionsModel)
event.command.setHidden(!action);
}
});
/**
* Zoom in to the Files app.
* @type {Command}
*/
CommandHandler.COMMANDS_['zoom-in'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
chrome.fileManagerPrivate.zoom('in');
},
canExecute: CommandUtil.canExecuteAlways
});
/**
* Zoom out from the Files app.
* @type {Command}
*/
CommandHandler.COMMANDS_['zoom-out'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
chrome.fileManagerPrivate.zoom('out');
},
canExecute: CommandUtil.canExecuteAlways
});
/**
* Reset the zoom factor.
* @type {Command}
*/
CommandHandler.COMMANDS_['zoom-reset'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
chrome.fileManagerPrivate.zoom('reset');
},
canExecute: CommandUtil.canExecuteAlways
});
/**
* Sort the file list by name (in ascending order).
* @type {Command}
*/
CommandHandler.COMMANDS_['sort-by-name'] = /** @type {Command} */ ({
execute: function(event, fileManager) {
if (fileManager.directoryModel.getFileList())
fileManager.directoryModel.getFileList().sort('name', 'asc');
},
canExecute: CommandUtil.canExecuteAlways
});
/**
* Sort the file list by size (in descending order).
* @type {Command}
*/
CommandHandler.COMMANDS_['sort-by-size'] = /** @type {Command} */ ({
execute: function(event, fileManager) {
if (fileManager.directoryModel.getFileList())
fileManager.directoryModel.getFileList().sort('size', 'desc');
},
canExecute: CommandUtil.canExecuteAlways
});
/**
* Sort the file list by type (in ascending order).
* @type {Command}
*/
CommandHandler.COMMANDS_['sort-by-type'] = /** @type {Command} */ ({
execute: function(event, fileManager) {
if (fileManager.directoryModel.getFileList())
fileManager.directoryModel.getFileList().sort('type', 'asc');
},
canExecute: CommandUtil.canExecuteAlways
});
/**
* Sort the file list by date-modified (in descending order).
* @type {Command}
*/
CommandHandler.COMMANDS_['sort-by-date'] = /** @type {Command} */ ({
execute: function(event, fileManager) {
if (fileManager.directoryModel.getFileList())
fileManager.directoryModel.getFileList().sort('modificationTime', 'desc');
},
canExecute: CommandUtil.canExecuteAlways
});
/**
* Open inspector for foreground page.
* @type {Command}
*/
CommandHandler.COMMANDS_['inspect-normal'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
chrome.fileManagerPrivate.openInspector('normal');
},
canExecute: CommandUtil.canExecuteAlways
});
/**
* Open inspector for foreground page and bring focus to the console.
* @type {Command}
*/
CommandHandler.COMMANDS_['inspect-console'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
chrome.fileManagerPrivate.openInspector('console');
},
canExecute: CommandUtil.canExecuteAlways
});
/**
* Open inspector for foreground page in inspect element mode.
* @type {Command}
*/
CommandHandler.COMMANDS_['inspect-element'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
chrome.fileManagerPrivate.openInspector('element');
},
canExecute: CommandUtil.canExecuteAlways
});
/**
* Open inspector for background page.
* @type {Command}
*/
CommandHandler.COMMANDS_['inspect-background'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
chrome.fileManagerPrivate.openInspector('background');
},
canExecute: CommandUtil.canExecuteAlways
});
/**
* Shows a suggest dialog with new services to be added to the left nav.
* @type {Command}
*/
CommandHandler.COMMANDS_['install-new-extension'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
fileManager.ui.suggestAppsDialog.showProviders(
function(result, itemId) {
// If a new provider is installed, then launch it so the configuration
// dialog is shown (if it's available).
if (result === SuggestAppsDialog.Result.SUCCESS)
fileManager.providersModel.requestMount(assert(itemId));
});
},
canExecute: function(event, fileManager) {
event.canExecute = fileManager.dialogType === DialogType.FULL_PAGE;
event.command.setHidden(!event.canExecute);
}
});
/**
* Opens the gear menu.
* @type {Command}
*/
CommandHandler.COMMANDS_['open-gear-menu'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
fileManager.ui.gearButton.showMenu(true);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
event.canExecute = CommandUtil.canExecuteAlways;
}
});
/**
* Configures the currently selected volume.
*/
CommandHandler.COMMANDS_['configure'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
var volumeInfo =
CommandUtil.getElementVolumeInfo(event.target, fileManager) ||
CommandUtil.getCurrentVolumeInfo(fileManager);
if (volumeInfo && volumeInfo.configurable)
fileManager.volumeManager.configure(volumeInfo);
},
canExecute: function(event, fileManager) {
var volumeInfo =
CommandUtil.getElementVolumeInfo(event.target, fileManager) ||
CommandUtil.getCurrentVolumeInfo(fileManager);
event.canExecute = volumeInfo && volumeInfo.configurable;
event.command.setHidden(!event.canExecute);
}
});
/**
* Refreshes the currently selected directory.
*/
CommandHandler.COMMANDS_['refresh'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
fileManager.directoryModel.rescan(true /* refresh */);
fileManager.spinnerController.blink();
},
canExecute: function(event, fileManager) {
var currentDirEntry = fileManager.directoryModel.getCurrentDirEntry();
var volumeInfo = currentDirEntry &&
fileManager.volumeManager.getVolumeInfo(currentDirEntry);
event.canExecute = volumeInfo && !volumeInfo.watchable;
event.command.setHidden(!event.canExecute ||
fileManager.directoryModel.getFileListSelection().getCheckSelectMode());
}
});
/**
* Refreshes the currently selected directory.
*/
CommandHandler.COMMANDS_['set-wallpaper'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
var entry = fileManager.getSelection().entries[0];
new Promise(function(resolve, reject) {
entry.file(resolve, reject);
}).then(function(blob) {
var fileReader = new FileReader();
return new Promise(function(resolve, reject) {
fileReader.onload = function() {
resolve(fileReader.result);
};
fileReader.onerror = function() {
reject(fileReader.error);
};
fileReader.readAsArrayBuffer(blob);
})
}).then(function(/** @type {!ArrayBuffer} */ arrayBuffer) {
return new Promise(function(resolve, reject) {
chrome.wallpaper.setWallpaper({
data: arrayBuffer,
layout: chrome.wallpaper.WallpaperLayout.CENTER_CROPPED,
filename: 'wallpaper'
}, function() {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
}else{
resolve(null);
}
});
});
}).catch(function() {
fileManager.ui.alertDialog.showHtml(
'', str('ERROR_INVALID_WALLPAPER'), null, null, null);
});
},
canExecute: function(event, fileManager) {
var entries = fileManager.getSelection().entries;
if (entries.length === 0) {
event.canExecute = false;
event.command.setHidden(true);
return;
}
var type = FileType.getType(entries[0]);
if (entries.length !== 1 || type.type !== 'image') {
event.canExecute = false;
event.command.setHidden(true);
return;
}
event.canExecute = type.subtype === 'JPEG' || type.subtype === 'PNG';
event.command.setHidden(false);
}
});