1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * TODO(dzvorygin): Here we use this hack, since 'hidden' is standard
7 * attribute and we can't use it's setter as usual.
8 * @param {boolean} value New value of hidden property.
10 cr.ui.Command.prototype.setHidden = function(value) {
11 this.__lookupSetter__('hidden').call(this, value);
18 var Command = function() {};
21 * Handles the execute event.
22 * @param {!Event} event Command event.
23 * @param {!FileManager} fileManager FileManager.
25 Command.prototype.execute = function(event, fileManager) {};
28 * Handles the can execute event.
29 * @param {!Event} event Can execute event.
30 * @param {!FileManager} fileManager FileManager.
32 Command.prototype.canExecute = function(event, fileManager) {};
35 * Utility for commands.
40 * Extracts entry on which command event was dispatched.
42 * @param {EventTarget} element Element which is the command event's target.
43 * @return {Entry} Entry of the found node.
45 CommandUtil.getCommandEntry = function(element) {
46 if (element instanceof DirectoryTree) {
47 // element is a DirectoryTree.
48 return element.selectedItem ? element.selectedItem.entry : null;
49 } else if (element instanceof DirectoryItem ||
50 element instanceof VolumeItem ||
51 element instanceof ShortcutItem) {
52 // element are sub items in DirectoryTree.
54 } else if (element instanceof cr.ui.List) {
55 // element is a normal List (eg. the file list on the right panel).
56 var entry = element.selectedItem;
57 // Check if it is Entry or not by checking for toURL().
58 return entry && 'toURL' in entry ? entry : null;
65 * Obtains an entry from the give navigation model item.
66 * @param {!NavigationModelItem} item Navigation model item.
67 * @return {Entry} Related entry.
70 CommandUtil.getEntryFromNavigationModelItem_ = function(item) {
72 return item.volumeInfo.displayRoot;
79 * Checks if command can be executed on drive.
80 * @param {!Event} event Command event to mark.
81 * @param {!FileManager} fileManager FileManager to use.
83 CommandUtil.canExecuteEnabledOnDriveOnly = function(event, fileManager) {
84 event.canExecute = fileManager.isOnDrive();
88 * Sets the command as visible only when the current volume is drive and it's
89 * running as a normal app, not as a modal dialog.
90 * @param {!Event} event Command event to mark.
91 * @param {!FileManager} fileManager FileManager to use.
93 CommandUtil.canExecuteVisibleOnDriveInNormalAppModeOnly =
94 function(event, fileManager) {
95 var enabled = fileManager.isOnDrive() &&
96 !DialogType.isModal(fileManager.dialogType);
97 event.canExecute = enabled;
98 event.command.setHidden(!enabled);
102 * Sets as the command as always enabled.
103 * @param {!Event} event Command event to mark.
105 CommandUtil.canExecuteAlways = function(event) {
106 event.canExecute = true;
110 * Returns a single selected/passed entry or null.
111 * @param {!Event} event Command event.
112 * @param {!FileManager} fileManager FileManager to use.
113 * @return {FileEntry} The entry or null.
115 CommandUtil.getSingleEntry = function(event, fileManager) {
116 if (event.target.entry) {
117 return event.target.entry;
119 var selection = fileManager.getSelection();
120 if (selection.totalCount == 1) {
121 return selection.entries[0];
127 * Obtains target entries that can be pinned from the selection.
128 * If directories are included in the selection, it just returns an empty
129 * array to avoid confusing because pinning directory is not supported
132 * @return {Array.<Entry>} Target entries.
134 CommandUtil.getPinTargetEntries = function() {
135 var hasDirectory = false;
136 var results = fileManager.getSelection().entries.filter(function(entry) {
137 hasDirectory = hasDirectory || entry.isDirectory;
138 if (!entry || hasDirectory)
140 var metadata = fileManager.metadataCache_.getCached(entry, 'external');
141 if (!metadata || metadata.hosted)
143 entry.pinned = metadata.pinned;
146 return hasDirectory ? [] : results;
150 * Sets the default handler for the commandId and prevents handling
151 * the keydown events for this command. Not doing that breaks relationship
152 * of original keyboard event and the command. WebKit would handle it
153 * differently in some cases.
154 * @param {Node} node to register command handler on.
155 * @param {string} commandId Command id to respond to.
157 CommandUtil.forceDefaultHandler = function(node, commandId) {
158 var doc = node.ownerDocument;
159 var command = doc.querySelector('command[id="' + commandId + '"]');
160 node.addEventListener('keydown', function(e) {
161 if (command.matchesEvent(e)) {
162 // Prevent cr.ui.CommandManager of handling it and leave it
163 // for the default handler.
167 node.addEventListener('command', function(event) {
168 if (event.command.id !== commandId)
170 document.execCommand(event.command.id);
171 event.cancelBubble = true;
173 node.addEventListener('canExecute', function(event) {
174 if (event.command.id === commandId)
175 event.canExecute = document.queryCommandEnabled(event.command.id);
183 CommandUtil.defaultCommand = /** @type {Command} */ ({
185 * @param {!Event} event Command event.
186 * @param {!FileManager} fileManager FileManager to use.
188 execute: function(event, fileManager) {
189 fileManager.document.execCommand(event.command.id);
192 * @param {!Event} event Command event.
193 * @param {!FileManager} fileManager FileManager to use.
195 canExecute: function(event, fileManager) {
196 event.canExecute = fileManager.document.queryCommandEnabled(
202 * Creates the volume switch command with index.
203 * @param {number} index Volume index from 1 to 9.
204 * @return {Command} Volume switch command.
206 CommandUtil.createVolumeSwitchCommand = function(index) {
207 return /** @type {Command} */ ({
209 * @param {!Event} event Command event.
210 * @param {!FileManager} fileManager FileManager to use.
212 execute: function(event, fileManager) {
213 fileManager.directoryTree.selectByIndex(index - 1);
216 * @param {!Event} event Command event.
217 * @param {!FileManager} fileManager FileManager to use.
219 canExecute: function(event, fileManager) {
220 event.canExecute = index > 0 &&
221 index <= fileManager.directoryTree.items.length;
227 * Returns a directory entry when only one entry is selected and it is
228 * directory. Otherwise, returns null.
229 * @param {FileSelection} selection Instance of FileSelection.
230 * @return {?DirectoryEntry} Directory entry which is selected alone.
232 CommandUtil.getOnlyOneSelectedDirectory = function(selection) {
235 if (selection.totalCount !== 1)
237 if (!selection.entries[0].isDirectory)
239 return selection.entries[0];
243 * Handle of the command events.
244 * @param {!FileManager} fileManager FileManager.
247 var CommandHandler = function(fileManager) {
250 * @type {!FileManager}
253 this.fileManager_ = fileManager;
257 * @type {Object.<string, cr.ui.Command>}
264 // Decorate command tags in the document.
265 var commands = fileManager.document.querySelectorAll('command');
266 for (var i = 0; i < commands.length; i++) {
267 cr.ui.Command.decorate(commands[i]);
268 this.commands_[commands[i].id] = commands[i];
272 fileManager.document.addEventListener('command', this.onCommand_.bind(this));
273 fileManager.document.addEventListener('canExecute',
274 this.onCanExecute_.bind(this));
278 * Updates the availability of all commands.
280 CommandHandler.prototype.updateAvailability = function() {
281 for (var id in this.commands_) {
282 this.commands_[id].canExecuteChange();
287 * Checks if the handler should ignore the current event, eg. since there is
288 * a popup dialog currently opened.
290 * @return {boolean} True if the event should be ignored, false otherwise.
293 CommandHandler.prototype.shouldIgnoreEvents_ = function() {
294 // Do not handle commands, when a dialog is shown.
295 if (this.fileManager_.document.querySelector('.cr-dialog-container.shown'))
298 return false; // Do not ignore.
302 * Handles command events.
303 * @param {!Event} event Command event.
306 CommandHandler.prototype.onCommand_ = function(event) {
307 if (this.shouldIgnoreEvents_())
309 var handler = CommandHandler.COMMANDS_[event.command.id];
310 handler.execute.call(/** @type {Command} */ (this), event, this.fileManager_);
314 * Handles canExecute events.
315 * @param {!Event} event Can execute event.
318 CommandHandler.prototype.onCanExecute_ = function(event) {
319 if (this.shouldIgnoreEvents_())
321 var handler = CommandHandler.COMMANDS_[event.command.id];
322 handler.canExecute.call(/** @type {Command} */ (this), event,
328 * @type {Object.<string, Command>}
332 CommandHandler.COMMANDS_ = {};
335 * Unmounts external drive.
338 CommandHandler.COMMANDS_['unmount'] = /** @type {Command} */ ({
340 * @param {!Event} event Command event.
341 * @param {!FileManager} fileManager The file manager instance.
343 execute: function(event, fileManager) {
344 var root = CommandUtil.getCommandEntry(event.target);
346 console.warn('unmount command executed on an element which does not ' +
347 'have corresponding entry.');
350 var errorCallback = function() {
351 fileManager.alert.showHtml('', str('UNMOUNT_FAILED'));
353 var volumeInfo = fileManager.volumeManager.getVolumeInfo(root);
358 fileManager.volumeManager_.unmount(
364 * @param {!Event} event Command event.
365 * @this {CommandHandler}
367 canExecute: function(event, fileManager) {
368 var root = CommandUtil.getCommandEntry(event.target);
371 var locationInfo = this.fileManager_.volumeManager.getLocationInfo(root);
373 locationInfo && locationInfo.isRootEntry && locationInfo.rootType;
375 event.canExecute = (rootType == VolumeManagerCommon.RootType.ARCHIVE ||
376 rootType == VolumeManagerCommon.RootType.REMOVABLE ||
377 rootType == VolumeManagerCommon.RootType.PROVIDED);
378 event.command.setHidden(!event.canExecute);
381 case VolumeManagerCommon.RootType.ARCHIVE:
382 case VolumeManagerCommon.RootType.PROVIDED:
383 event.command.label = str('CLOSE_VOLUME_BUTTON_LABEL');
385 case VolumeManagerCommon.RootType.REMOVABLE:
386 event.command.label = str('UNMOUNT_DEVICE_BUTTON_LABEL');
393 * Formats external drive.
396 CommandHandler.COMMANDS_['format'] = /** @type {Command} */ ({
398 * @param {!Event} event Command event.
399 * @param {!FileManager} fileManager The file manager instance.
401 execute: function(event, fileManager) {
402 var directoryModel = fileManager.directoryModel;
403 var root = CommandUtil.getCommandEntry(event.target);
404 // If an entry is not found from the event target, use the current
405 // directory. This can happen for the format button for unsupported and
406 // unrecognized volumes.
408 root = directoryModel.getCurrentDirEntry();
410 var volumeInfo = fileManager.volumeManager.getVolumeInfo(root);
412 fileManager.confirm.show(
413 loadTimeData.getString('FORMATTING_WARNING'),
414 chrome.fileManagerPrivate.formatVolume.bind(null,
415 volumeInfo.volumeId));
419 * @param {!Event} event Command event.
420 * @param {!FileManager} fileManager The file manager instance.
422 canExecute: function(event, fileManager) {
423 var directoryModel = fileManager.directoryModel;
424 var root = CommandUtil.getCommandEntry(event.target);
425 // |root| is null for unrecognized volumes. Regard such volumes as writable
426 // so that the format command is enabled.
427 var isReadOnly = root && fileManager.isOnReadonlyDirectory();
428 // See the comment in execute() for why doing this.
430 root = directoryModel.getCurrentDirEntry();
431 var location = root && fileManager.volumeManager.getLocationInfo(root);
432 var removable = location && location.rootType ===
433 VolumeManagerCommon.RootType.REMOVABLE;
434 event.canExecute = removable && !isReadOnly;
435 event.command.setHidden(!removable);
440 * Initiates new folder creation.
443 CommandHandler.COMMANDS_['new-folder'] = /** @type {Command} */ ({
445 * @param {!Event} event Command event.
446 * @param {!FileManager} fileManager FileManager to use.
448 execute: function(event, fileManager) {
449 fileManager.createNewFolder();
452 * @param {!Event} event Command event.
453 * @param {!FileManager} fileManager FileManager to use.
455 canExecute: function(event, fileManager) {
456 var directoryModel = fileManager.directoryModel;
457 event.canExecute = !fileManager.isOnReadonlyDirectory() &&
458 !fileManager.namingController.isRenamingInProgress() &&
459 !directoryModel.isSearching() &&
460 !directoryModel.isScanning();
465 * Initiates new window creation.
468 CommandHandler.COMMANDS_['new-window'] = /** @type {Command} */ ({
470 * @param {!Event} event Command event.
471 * @param {!FileManager} fileManager FileManager to use.
473 execute: function(event, fileManager) {
474 chrome.fileManagerPrivate.getProfiles(
475 function(profiles, currentId, displayedId) {
476 fileManager.backgroundPage.launchFileManager({
477 currentDirectoryURL: fileManager.getCurrentDirectoryEntry() &&
478 fileManager.getCurrentDirectoryEntry().toURL(),
479 displayedId: currentId !== displayedId ? displayedId : undefined
484 * @param {!Event} event Command event.
485 * @param {!FileManager} fileManager FileManager to use.
487 canExecute: function(event, fileManager) {
489 fileManager.getCurrentDirectoryEntry() &&
490 (fileManager.dialogType === DialogType.FULL_PAGE);
495 * Toggles drive sync settings.
498 CommandHandler.COMMANDS_['drive-sync-settings'] = /** @type {Command} */ ({
500 * @param {!Event} event Command event.
501 * @param {!FileManager} fileManager FileManager to use.
503 execute: function(event, fileManager) {
504 fileManager.toggleDriveSyncSettings();
507 * @param {!Event} event Command event.
508 * @param {!FileManager} fileManager FileManager to use.
510 canExecute: function(event, fileManager) {
511 event.canExecute = fileManager.shouldShowDriveSettings() &&
512 fileManager.volumeManager.getDriveConnectionState().
513 hasCellularNetworkAccess;
514 event.command.setHidden(!event.canExecute);
519 * Toggles drive hosted settings.
522 CommandHandler.COMMANDS_['drive-hosted-settings'] = /** @type {Command} */ ({
524 * @param {!Event} event Command event.
525 * @param {!FileManager} fileManager FileManager to use.
527 execute: function(event, fileManager) {
528 fileManager.toggleDriveHostedSettings();
531 * @param {!Event} event Command event.
532 * @param {!FileManager} fileManager FileManager to use.
534 canExecute: function(event, fileManager) {
535 event.canExecute = fileManager.shouldShowDriveSettings();
536 event.command.setHidden(!event.canExecute);
541 * Deletes selected files.
544 CommandHandler.COMMANDS_['delete'] = /** @type {Command} */ ({
546 * @param {!Event} event Command event.
547 * @param {!FileManager} fileManager FileManager to use.
549 execute: function(event, fileManager) {
550 var entries = fileManager.getSelection().entries;
551 var message = entries.length == 1 ?
552 strf('GALLERY_CONFIRM_DELETE_ONE', entries[0].name) :
553 strf('GALLERY_CONFIRM_DELETE_SOME', entries.length);
554 fileManager.ui.deleteConfirmDialog.show(message, function() {
555 fileManager.fileOperationManager.deleteEntries(entries);
559 * @param {!Event} event Command event.
560 * @param {!FileManager} fileManager FileManager to use.
562 canExecute: function(event, fileManager) {
563 var selection = fileManager.getSelection();
564 event.canExecute = !fileManager.isOnReadonlyDirectory() &&
566 selection.totalCount > 0;
571 * Pastes files from clipboard.
574 CommandHandler.COMMANDS_['paste'] = /** @type {Command} */ ({
576 * @param {!Event} event Command event.
577 * @param {!FileManager} fileManager FileManager to use.
579 execute: function(event, fileManager) {
580 fileManager.document.execCommand(event.command.id);
583 * @param {!Event} event Command event.
584 * @param {!FileManager} fileManager FileManager to use.
586 canExecute: function(event, fileManager) {
587 var fileTransferController = fileManager.fileTransferController;
588 event.canExecute = (fileTransferController &&
589 fileTransferController.queryPasteCommandEnabled());
590 // Hide this command if only one folder is selected.
591 event.command.setHidden(!!CommandUtil.getOnlyOneSelectedDirectory(
592 fileManager.getSelection()));
597 * Pastes files from clipboard into the selected folder.
600 CommandHandler.COMMANDS_['paste-into-folder'] = /** @type {Command} */ ({
602 * @param {!Event} event Command event.
603 * @param {!FileManager} fileManager FileManager to use.
605 execute: function(event, fileManager) {
606 var selection = fileManager.getSelection();
607 var dest = CommandUtil.getOnlyOneSelectedDirectory(selection);
610 // This handler tweaks the Event object for 'paste' event so that
611 // the FileTransferController can distinguish this 'paste-into-folder'
612 // command and know the destination directory.
613 var handler = function(inEvent) {
614 inEvent.destDirectory = dest;
616 fileManager.document.addEventListener('paste', handler, true);
617 fileManager.document.execCommand('paste');
618 fileManager.document.removeEventListener('paste', handler, true);
621 * @param {!Event} event Command event.
622 * @param {!FileManager} fileManager FileManager to use.
624 canExecute: function(event, fileManager) {
625 var fileTransferController = fileManager.fileTransferController;
626 event.canExecute = (fileTransferController &&
627 fileTransferController.queryPasteCommandEnabled());
628 // Hide this command unless only one folder is selected.
629 event.command.setHidden(!CommandUtil.getOnlyOneSelectedDirectory(
630 fileManager.getSelection()));
634 CommandHandler.COMMANDS_['cut'] = CommandUtil.defaultCommand;
635 CommandHandler.COMMANDS_['copy'] = CommandUtil.defaultCommand;
638 * Initiates file renaming.
641 CommandHandler.COMMANDS_['rename'] = /** @type {Command} */ ({
643 * @param {!Event} event Command event.
644 * @param {!FileManager} fileManager FileManager to use.
646 execute: function(event, fileManager) {
647 fileManager.namingController.initiateRename();
650 * @param {!Event} event Command event.
651 * @param {!FileManager} fileManager FileManager to use.
653 canExecute: function(event, fileManager) {
654 var selection = fileManager.getSelection();
655 event.canExecute = !fileManager.namingController.isRenamingInProgress() &&
656 !fileManager.isOnReadonlyDirectory() &&
658 selection.totalCount == 1;
666 CommandHandler.COMMANDS_['volume-help'] = /** @type {Command} */ ({
668 * @param {!Event} event Command event.
669 * @param {!FileManager} fileManager FileManager to use.
671 execute: function(event, fileManager) {
672 if (fileManager.isOnDrive())
673 util.visitURL(str('GOOGLE_DRIVE_HELP_URL'));
675 util.visitURL(str('FILES_APP_HELP_URL'));
678 * @param {!Event} event Command event.
679 * @param {!FileManager} fileManager FileManager to use.
681 canExecute: function(event, fileManager) {
682 // Hides the help menu in modal dialog mode. It does not make much sense
683 // because after all, users cannot view the help without closing, and
684 // besides that the help page is about Files.app as an app, not about the
685 // dialog mode itself. It can also lead to hard-to-fix bug crbug.com/339089.
686 var hideHelp = DialogType.isModal(fileManager.dialogType);
687 event.canExecute = !hideHelp;
688 event.command.setHidden(hideHelp);
689 fileManager.document_.getElementById('help-separator').hidden = hideHelp;
694 * Opens drive buy-more-space url.
697 CommandHandler.COMMANDS_['drive-buy-more-space'] = /** @type {Command} */ ({
699 * @param {!Event} event Command event.
700 * @param {!FileManager} fileManager FileManager to use.
702 execute: function(event, fileManager) {
703 util.visitURL(str('GOOGLE_DRIVE_BUY_STORAGE_URL'));
705 canExecute: CommandUtil.canExecuteVisibleOnDriveInNormalAppModeOnly
709 * Opens drive.google.com.
712 CommandHandler.COMMANDS_['drive-go-to-drive'] = /** @type {Command} */ ({
714 * @param {!Event} event Command event.
715 * @param {!FileManager} fileManager FileManager to use.
717 execute: function(event, fileManager) {
718 util.visitURL(str('GOOGLE_DRIVE_ROOT_URL'));
720 canExecute: CommandUtil.canExecuteVisibleOnDriveInNormalAppModeOnly
724 * Displays open with dialog for current selection.
727 CommandHandler.COMMANDS_['open-with'] = /** @type {Command} */ ({
729 * @param {!Event} event Command event.
730 * @param {!FileManager} fileManager FileManager to use.
732 execute: function(event, fileManager) {
733 var tasks = fileManager.getSelection().tasks;
735 tasks.showTaskPicker(fileManager.defaultTaskPicker,
736 str('OPEN_WITH_BUTTON_LABEL'),
739 tasks.execute(task.taskId);
745 * @param {!Event} event Command event.
746 * @param {!FileManager} fileManager FileManager to use.
748 canExecute: function(event, fileManager) {
749 var tasks = fileManager.getSelection().tasks;
750 event.canExecute = tasks && tasks.size() > 1;
755 * Focuses search input box.
758 CommandHandler.COMMANDS_['search'] = /** @type {Command} */ ({
760 * @param {!Event} event Command event.
761 * @param {!FileManager} fileManager FileManager to use.
763 execute: function(event, fileManager) {
764 var element = fileManager.document.querySelector('#search-box input');
769 * @param {!Event} event Command event.
770 * @param {!FileManager} fileManager FileManager to use.
772 canExecute: function(event, fileManager) {
773 event.canExecute = !fileManager.namingController.isRenamingInProgress();
778 * Activates the n-th volume.
781 CommandHandler.COMMANDS_['volume-switch-1'] =
782 CommandUtil.createVolumeSwitchCommand(1);
783 CommandHandler.COMMANDS_['volume-switch-2'] =
784 CommandUtil.createVolumeSwitchCommand(2);
785 CommandHandler.COMMANDS_['volume-switch-3'] =
786 CommandUtil.createVolumeSwitchCommand(3);
787 CommandHandler.COMMANDS_['volume-switch-4'] =
788 CommandUtil.createVolumeSwitchCommand(4);
789 CommandHandler.COMMANDS_['volume-switch-5'] =
790 CommandUtil.createVolumeSwitchCommand(5);
791 CommandHandler.COMMANDS_['volume-switch-6'] =
792 CommandUtil.createVolumeSwitchCommand(6);
793 CommandHandler.COMMANDS_['volume-switch-7'] =
794 CommandUtil.createVolumeSwitchCommand(7);
795 CommandHandler.COMMANDS_['volume-switch-8'] =
796 CommandUtil.createVolumeSwitchCommand(8);
797 CommandHandler.COMMANDS_['volume-switch-9'] =
798 CommandUtil.createVolumeSwitchCommand(9);
801 * Flips 'available offline' flag on the file.
804 CommandHandler.COMMANDS_['toggle-pinned'] = /** @type {Command} */ ({
806 * @param {!Event} event
807 * @param {!FileManager} fileManager
809 execute: function(event, fileManager) {
810 var pin = !event.command.checked;
811 event.command.checked = pin;
812 var entries = CommandUtil.getPinTargetEntries();
813 if (entries.length == 0)
818 // Pick an entry and pin it.
820 // Check if all the entries are pinned or not.
821 if (entries.length == 0)
823 currentEntry = entries.shift();
824 chrome.fileManagerPrivate.pinDriveFile(
825 currentEntry.toURL(),
830 // Check the result of pinning
831 entryPinned: function() {
832 // Convert to boolean.
833 error = !!chrome.runtime.lastError;
835 fileManager.metadataCache_.getOne(
836 currentEntry, 'filesystem', steps.showError);
838 fileManager.metadataCache_.clear(currentEntry, 'external');
839 fileManager.metadataCache_.getOne(
840 currentEntry, 'external', steps.updateUI.bind(this));
843 // Update the user interface according to the cache state.
844 updateUI: function(drive /* not used */) {
845 fileManager.ui.listContainer.currentView.updateListItemsMetadata(
846 'external', [currentEntry]);
852 showError: function(filesystem) {
853 fileManager.alert.showHtml(str('DRIVE_OUT_OF_SPACE_HEADER'),
854 strf('DRIVE_OUT_OF_SPACE_MESSAGE',
855 unescape(currentEntry.name),
856 util.bytesToString(filesystem.size)));
861 var driveSyncHandler =
862 fileManager.backgroundPage.background.driveSyncHandler;
863 if (pin && driveSyncHandler.isSyncSuppressed())
864 driveSyncHandler.showDisabledMobileSyncNotification();
868 * @param {!Event} event Command event.
869 * @param {!FileManager} fileManager FileManager to use.
871 canExecute: function(event, fileManager) {
872 var entries = CommandUtil.getPinTargetEntries();
874 for (var i = 0; i < entries.length; i++) {
875 checked = checked && entries[i].pinned;
877 if (entries.length > 0) {
878 event.canExecute = true;
879 event.command.setHidden(false);
880 event.command.checked = checked;
882 event.canExecute = false;
883 event.command.setHidden(true);
889 * Creates zip file for current selection.
892 CommandHandler.COMMANDS_['zip-selection'] = /** @type {Command} */ ({
894 * @param {!Event} event Command event.
895 * @param {!FileManager} fileManager FileManager to use.
897 execute: function(event, fileManager) {
898 var dirEntry = fileManager.getCurrentDirectoryEntry();
901 var selectionEntries = fileManager.getSelection().entries;
902 fileManager.fileOperationManager_.zipSelection(
903 dirEntry, selectionEntries);
906 * @param {!Event} event Command event.
907 * @param {!FileManager} fileManager FileManager to use.
909 canExecute: function(event, fileManager) {
910 var dirEntry = fileManager.getCurrentDirectoryEntry();
911 var selection = fileManager.getSelection();
914 !fileManager.isOnReadonlyDirectory() &&
915 !fileManager.isOnDrive() &&
916 selection && selection.totalCount > 0;
921 * Shows the share dialog for the current selection (single only).
924 CommandHandler.COMMANDS_['share'] = /** @type {Command} */ ({
926 * @param {!Event} event Command event.
927 * @param {!FileManager} fileManager FileManager to use.
929 execute: function(event, fileManager) {
930 fileManager.shareSelection();
933 * @param {!Event} event Command event.
934 * @param {!FileManager} fileManager FileManager to use.
936 canExecute: function(event, fileManager) {
937 var selection = fileManager.getSelection();
939 fileManager.volumeManager.getDriveConnectionState().type ===
940 VolumeManagerCommon.DriveConnectionType.OFFLINE;
941 event.canExecute = fileManager.isOnDrive() &&
943 selection && selection.totalCount == 1;
944 event.command.setHidden(!fileManager.isOnDrive());
949 * Creates a shortcut of the selected folder (single only).
952 CommandHandler.COMMANDS_['create-folder-shortcut'] = /** @type {Command} */ ({
954 * @param {!Event} event Command event.
955 * @param {!FileManager} fileManager The file manager instance.
957 execute: function(event, fileManager) {
958 var entry = CommandUtil.getCommandEntry(event.target);
960 console.warn('create-folder-shortcut command executed on an element ' +
961 'which does not have corresponding entry.');
964 fileManager.createFolderShortcut(entry);
968 * @param {!Event} event Command event.
969 * @param {!FileManager} fileManager The file manager instance.
971 canExecute: function(event, fileManager) {
972 var entry = CommandUtil.getCommandEntry(event.target);
973 var folderShortcutExists = entry &&
974 fileManager.folderShortcutExists(entry);
976 var onlyOneFolderSelected = true;
977 // Only on list, user can select multiple files. The command is enabled only
978 // when a single file is selected.
979 if (event.target instanceof cr.ui.List) {
980 var items = event.target.selectedItems;
981 onlyOneFolderSelected = (items.length == 1 && items[0].isDirectory);
984 var location = entry && fileManager.volumeManager.getLocationInfo(entry);
985 var eligible = location && location.isEligibleForFolderShortcut;
987 eligible && onlyOneFolderSelected && !folderShortcutExists;
988 event.command.setHidden(!eligible || !onlyOneFolderSelected);
993 * Removes the folder shortcut.
996 CommandHandler.COMMANDS_['remove-folder-shortcut'] = /** @type {Command} */ ({
998 * @param {!Event} event Command event.
999 * @param {!FileManager} fileManager The file manager instance.
1001 execute: function(event, fileManager) {
1002 var entry = CommandUtil.getCommandEntry(event.target);
1004 console.warn('remove-folder-shortcut command executed on an element ' +
1005 'which does not have corresponding entry.');
1008 fileManager.removeFolderShortcut(entry);
1012 * @param {!Event} event Command event.
1013 * @param {!FileManager} fileManager The file manager instance.
1015 canExecute: function(event, fileManager) {
1016 var entry = CommandUtil.getCommandEntry(event.target);
1017 var location = entry && fileManager.volumeManager.getLocationInfo(entry);
1019 var eligible = location && location.isEligibleForFolderShortcut;
1020 var isShortcut = entry && fileManager.folderShortcutExists(entry);
1021 event.canExecute = isShortcut && eligible;
1022 event.command.setHidden(!event.canExecute);
1027 * Zoom in to the Files.app.
1030 CommandHandler.COMMANDS_['zoom-in'] = /** @type {Command} */ ({
1032 * @param {!Event} event Command event.
1033 * @param {!FileManager} fileManager FileManager to use.
1035 execute: function(event, fileManager) {
1036 chrome.fileManagerPrivate.zoom('in');
1038 canExecute: CommandUtil.canExecuteAlways
1042 * Zoom out from the Files.app.
1045 CommandHandler.COMMANDS_['zoom-out'] = /** @type {Command} */ ({
1047 * @param {!Event} event Command event.
1048 * @param {!FileManager} fileManager FileManager to use.
1050 execute: function(event, fileManager) {
1051 chrome.fileManagerPrivate.zoom('out');
1053 canExecute: CommandUtil.canExecuteAlways
1057 * Reset the zoom factor.
1060 CommandHandler.COMMANDS_['zoom-reset'] = /** @type {Command} */ ({
1062 * @param {!Event} event Command event.
1063 * @param {!FileManager} fileManager FileManager to use.
1065 execute: function(event, fileManager) {
1066 chrome.fileManagerPrivate.zoom('reset');
1068 canExecute: CommandUtil.canExecuteAlways
1072 * Open inspector for foreground page.
1075 CommandHandler.COMMANDS_['inspect-normal'] = /** @type {Command} */ ({
1077 * @param {!Event} event Command event.
1078 * @param {!FileManager} fileManager FileManager to use.
1080 execute: function(event, fileManager) {
1081 chrome.fileManagerPrivate.openInspector('normal');
1083 canExecute: CommandUtil.canExecuteAlways
1087 * Open inspector for foreground page and bring focus to the console.
1090 CommandHandler.COMMANDS_['inspect-console'] = /** @type {Command} */ ({
1092 * @param {!Event} event Command event.
1093 * @param {!FileManager} fileManager FileManager to use.
1095 execute: function(event, fileManager) {
1096 chrome.fileManagerPrivate.openInspector('console');
1098 canExecute: CommandUtil.canExecuteAlways
1102 * Open inspector for foreground page in inspect element mode.
1105 CommandHandler.COMMANDS_['inspect-element'] = /** @type {Command} */ ({
1107 * @param {!Event} event Command event.
1108 * @param {!FileManager} fileManager FileManager to use.
1110 execute: function(event, fileManager) {
1111 chrome.fileManagerPrivate.openInspector('element');
1113 canExecute: CommandUtil.canExecuteAlways
1117 * Open inspector for background page.
1120 CommandHandler.COMMANDS_['inspect-background'] = /** @type {Command} */ ({
1122 * @param {!Event} event Command event.
1123 * @param {!FileManager} fileManager FileManager to use.
1125 execute: function(event, fileManager) {
1126 chrome.fileManagerPrivate.openInspector('background');
1128 canExecute: CommandUtil.canExecuteAlways