Commit 1d5ed471 authored by Joel Hockey's avatar Joel Hockey Committed by Commit Bot

FilesApp: Add Share with Plugin VM

 * Add share-with-plugin-vm and manage-plugin-vm-sharing commands
   These commands call through to the related FMP crostini commands
   and set vmName to PluginVm rather than termina.
 * Refactor crostini_share UI test to work for either crostini
   or Plugin VM

Bug: 946273
Change-Id: I66a2610f0fffc33c08ccedf38ca8a7efd0e9a678
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1556815
Commit-Queue: Joel Hockey <joelhockey@chromium.org>
Reviewed-by: default avatarLuciano Pacheco <lucmult@chromium.org>
Cr-Commit-Position: refs/heads/master@{#648571}
parent ce1b6a52
......@@ -12,6 +12,7 @@
#include "chrome/browser/chromeos/file_manager/file_manager_string_util.h"
#include "chrome/browser/chromeos/file_manager/open_with_browser.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
#include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/constants/chromeos_features.h"
......@@ -55,6 +56,11 @@ ExtensionFunction::ResponseAction FileManagerPrivateGetStringsFunction::Run() {
dict->SetBoolean(
"MY_FILES_VOLUME_ENABLED",
base::FeatureList::IsEnabled(chromeos::features::kMyFilesVolume));
dict->SetBoolean("PLUGIN_VM_ENABLED",
plugin_vm::IsPluginVmAllowedForProfile(
Profile::FromBrowserContext(browser_context())) &&
plugin_vm::IsPluginVmConfigured(
Profile::FromBrowserContext(browser_context())));
dict->SetString("UI_LOCALE", extension_l10n_util::CurrentLocaleOrDefault());
return RespondNow(OneArgument(std::move(dict)));
......
......@@ -514,6 +514,10 @@ std::unique_ptr<base::DictionaryValue> GetFileManagerStrings() {
IDS_FILE_BROWSER_FOLDER_SHARED_WITH_CROSTINI);
SET_STRING("FOLDER_SHARED_WITH_CROSTINI_PLURAL",
IDS_FILE_BROWSER_FOLDER_SHARED_WITH_CROSTINI_PLURAL);
SET_STRING("FOLDER_SHARED_WITH_PLUGIN_VM",
IDS_FILE_BROWSER_FOLDER_SHARED_WITH_PLUGIN_VM);
SET_STRING("FOLDER_SHARED_WITH_PLUGIN_VM_PLURAL",
IDS_FILE_BROWSER_FOLDER_SHARED_WITH_PLUGIN_VM_PLURAL);
SET_STRING("FORMATTING_FINISHED_FAILURE_MESSAGE",
IDS_FORMATTING_FINISHED_FAILURE_MESSAGE);
SET_STRING("FORMATTING_FINISHED_SUCCESS_MESSAGE",
......@@ -723,6 +727,10 @@ std::unique_ptr<base::DictionaryValue> GetFileManagerStrings() {
IDS_FILE_BROWSER_SHARE_WITH_LINUX_BUTTON_LABEL);
SET_STRING("MANAGE_LINUX_SHARING_BUTTON_LABEL",
IDS_FILE_BROWSER_MANAGE_LINUX_SHARING_BUTTON_LABEL);
SET_STRING("SHARE_WITH_PLUGIN_VM_BUTTON_LABEL",
IDS_FILE_BROWSER_SHARE_WITH_PLUGIN_VM_BUTTON_LABEL);
SET_STRING("MANAGE_PLUGIN_VM_SHARING_BUTTON_LABEL",
IDS_FILE_BROWSER_MANAGE_PLUGIN_VM_SHARING_BUTTON_LABEL);
SET_STRING("CHANGE_TO_LISTVIEW_BUTTON_LABEL",
IDS_FILE_BROWSER_CHANGE_TO_LISTVIEW_BUTTON_LABEL);
SET_STRING("CHANGE_TO_THUMBNAILVIEW_BUTTON_LABEL",
......
......@@ -87,6 +87,10 @@ IN_PROC_BROWSER_TEST_F(FileManagerUITest, Menu) {
RunTest("menu");
}
IN_PROC_BROWSER_TEST_F(FileManagerUITest, PluginVmShare) {
RunTest("pluginVmShare");
}
IN_PROC_BROWSER_TEST_F(FileManagerUITest, ProgressCenter) {
RunTest("progressCenter");
}
......
......@@ -23741,6 +23741,10 @@ Called by update_net_error_codes.py.-->
<int value="13" label="Manage Linux sharing menu"/>
<int value="14" label="Manage Linux sharing toast"/>
<int value="15" label="Manage Linux sharing toast startup"/>
<int value="16" label="Share with Plugin VM"/>
<int value="17" label="Manage Plugin VM sharing menu"/>
<int value="18" label="Manage Plugin VM sharing toast"/>
<int value="19" label="Manage Plugin VM sharing toast startup"/>
</enum>
<enum name="FileManagerQuickViewWayToOpen">
......@@ -543,6 +543,12 @@
<message name="IDS_FILE_BROWSER_MANAGE_LINUX_SHARING_BUTTON_LABEL" desc="Label for menu that will take users to the settings page where they can manage which files and folders are shared with the crostini Linux container.">
Manage Linux sharing
</message>
<message name="IDS_FILE_BROWSER_SHARE_WITH_PLUGIN_VM_BUTTON_LABEL" desc="Label for menu that will share a folder with the Plugin VM.">
Share with Plugin VM
</message>
<message name="IDS_FILE_BROWSER_MANAGE_PLUGIN_VM_SHARING_BUTTON_LABEL" desc="Label for menu that will take users to the settings page where they can manage which files and folders are shared with the Plugin VM.">
Manage Plugin VM sharing
</message>
<message name="IDS_FILE_BROWSER_TOGGLE_HIDDEN_FILES_COMMAND_LABEL" desc="Label for menu or button with checkmark that toggles visibility of hidden files.">
Show hidden files
</message>
......@@ -1078,6 +1084,12 @@
<message name="IDS_FILE_BROWSER_FOLDER_SHARED_WITH_CROSTINI_PLURAL" desc="Confirmation message shown when a user shares more than 1 folder with the crostini container.">
<ph name="NUMBER_OF_ITEMS">$1<ex>3</ex></ph> folders shared with Linux
</message>
<message name="IDS_FILE_BROWSER_FOLDER_SHARED_WITH_PLUGIN_VM" desc="Confirmation message shown when a user shares a folder with the Plugin VM.">
1 folder shared with Plugin VM
</message>
<message name="IDS_FILE_BROWSER_FOLDER_SHARED_WITH_PLUGIN_VM_PLURAL" desc="Confirmation message shown when a user shares more than 1 folder with the Plugin VM.">
<ph name="NUMBER_OF_ITEMS">$1<ex>3</ex></ph> folders shared with Plugin VM
</message>
<message name="IDS_FILE_BROWSER_FOLDER" desc="Folder entry type">
Folder
......
5d9c950adff3876f332a672cfff1e95a59ae6291
\ No newline at end of file
10f6eb2c0b3fda88e5e437aa7e1481140077f54d
\ No newline at end of file
48dfca6f7bfe238339d951318b922c6080c89348
\ No newline at end of file
......@@ -21,16 +21,18 @@ Crostini.prototype.init = function(volumeManager) {};
Crostini.prototype.listen = function() {};
/**
* Set from feature 'crostini-files'.
* Set whether the specified VM is enabled.
* @param {string} vmName
* @param {boolean} enabled
*/
Crostini.prototype.setEnabled = function(enabled) {};
Crostini.prototype.setEnabled = function(vmName, enabled) {};
/**
* Returns true if crostini is enabled.
* Returns true if the specified VM is enabled.
* @param {string} vmName
* @return {boolean}
*/
Crostini.prototype.isEnabled = function() {};
Crostini.prototype.isEnabled = function(vmName) {};
/**
* Registers an entry as a shared path for the specified VM.
......
......@@ -10,10 +10,10 @@
*/
function CrostiniImpl() {
/**
* True if crostini is enabled.
* @private {boolean}
* True if VM is enabled.
* @private {Object<boolean>}
*/
this.enabled_ = false;
this.enabled_ = {};
/**
* Maintains a list of paths shared with VMs.
......@@ -29,6 +29,12 @@ function CrostiniImpl() {
*/
CrostiniImpl.DEFAULT_VM = 'termina';
/**
* Plugin VM 'PluginVm'.
* @const
*/
CrostiniImpl.PLUGIN_VM = 'PluginVm';
/**
* Keep in sync with histograms.xml:FileBrowserCrostiniSharedPathsDepth
* histogram_suffix.
......@@ -80,19 +86,21 @@ CrostiniImpl.prototype.listen = function() {
};
/**
* Set from feature 'crostini-files'.
* Set whether the specified VM is enabled.
* @param {string} vmName
* @param {boolean} enabled
*/
CrostiniImpl.prototype.setEnabled = function(enabled) {
this.enabled_ = enabled;
CrostiniImpl.prototype.setEnabled = function(vmName, enabled) {
this.enabled_[vmName] = enabled;
};
/**
* Returns true if crostini is enabled.
* @param {string} vmName
* @return {boolean}
*/
CrostiniImpl.prototype.isEnabled = function() {
return this.enabled_;
CrostiniImpl.prototype.isEnabled = function(vmName) {
return this.enabled_[vmName];
};
/**
......@@ -216,7 +224,7 @@ CrostiniImpl.prototype.isPathShared = function(vmName, entry) {
* @param {boolean} persist If path is to be persisted.
*/
CrostiniImpl.prototype.canSharePath = function(vmName, entry, persist) {
if (vmName === CrostiniImpl.DEFAULT_VM && !this.enabled_) {
if (!this.enabled_[vmName]) {
return false;
}
......
......@@ -137,7 +137,7 @@ function testIsPathShared() {
* Tests disallowed and allowed shared paths.
*/
function testCanSharePath() {
crostini.setEnabled(true);
crostini.setEnabled('vm', true);
const mockFileSystem = new MockFileSystem('test');
const root = new MockDirectoryEntry(mockFileSystem, '/');
......
......@@ -83,3 +83,9 @@ constants.DRIVE_WELCOME_CSS = 'foreground/css/drive_welcome.css';
* @const
*/
constants.DEFAULT_CROSTINI_VM = 'termina';
/**
* Name of the Plugin VM.
* @const
*/
constants.PLUGIN_VM = 'PluginVm';
......@@ -1149,7 +1149,12 @@ FileManager.prototype = /** @struct */ {
assert(this.directoryModel_));
this.ui_.initDirectoryTree(directoryTree);
this.setCrostiniEnabled_(loadTimeData.getBoolean('CROSTINI_ENABLED'));
this.crostini_.setEnabled(
constants.DEFAULT_CROSTINI_VM,
loadTimeData.getBoolean('CROSTINI_ENABLED'));
this.crostini_.setEnabled(
constants.PLUGIN_VM, loadTimeData.getBoolean('PLUGIN_VM_ENABLED'));
this.setupCrostini_();
chrome.fileManagerPrivate.onCrostiniChanged.addListener(
this.onCrostiniChanged_.bind(this));
......@@ -1160,14 +1165,13 @@ FileManager.prototype = /** @struct */ {
};
/**
* Check if crostini is enabled to create linuxFilesItem.
* @param {boolean} enabled
* Setup crostini 'Linux files'.
* @private
*/
FileManager.prototype.setCrostiniEnabled_ = function(enabled) {
this.crostini_.setEnabled(enabled);
FileManager.prototype.setupCrostini_ = function() {
// Setup Linux files fake root.
this.directoryTree.dataModel.linuxFilesItem = enabled ?
this.directoryTree.dataModel.linuxFilesItem =
this.crostini_.isEnabled(constants.DEFAULT_CROSTINI_VM) ?
new NavigationModelFakeItem(
str('LINUX_FILES_ROOT_LABEL'), NavigationModelItemType.CROSTINI,
new FakeEntry(
......@@ -1177,37 +1181,61 @@ FileManager.prototype = /** @struct */ {
// Redraw the tree to ensure 'Linux files' is added/removed.
this.directoryTree.redraw(false);
if (!enabled) {
return;
}
// Load any existing shared paths.
// Only observe firstForSession when using full-page FilesApp.
// I.e., don't show toast in a dialog.
chrome.fileManagerPrivate.getCrostiniSharedPaths(
this.dialogType === DialogType.FULL_PAGE, constants.DEFAULT_CROSTINI_VM,
(entries, firstForSession) => {
for (let i = 0; i < entries.length; i++) {
this.crostini_.registerSharedPath(
constants.DEFAULT_CROSTINI_VM, entries[i]);
}
// Show 'Manage sharing' toast the first time FilesApp is opened.
if (firstForSession && entries.length >= 1) {
this.ui_.toast.show(
entries.length == 1 ?
str('FOLDER_SHARED_WITH_CROSTINI') :
strf('FOLDER_SHARED_WITH_CROSTINI_PLURAL', entries.length),
{
text: str('MANAGE_LINUX_SHARING_BUTTON_LABEL'),
callback: () => {
chrome.fileManagerPrivate.openSettingsSubpage(
'crostini/sharedPaths');
CommandHandler.recordMenuItemSelected(
CommandHandler.MenuCommandsForUMA
.MANAGE_LINUX_SHARING_TOAST_STARTUP);
}
});
}
let showToast = false;
const getSharedPaths = (vmName) => {
return new Promise(resolve => {
if (!this.crostini_.isEnabled(vmName)) {
return resolve(0);
}
chrome.fileManagerPrivate.getCrostiniSharedPaths(
this.dialogType === DialogType.FULL_PAGE, vmName,
(entries, firstForSession) => {
showToast = showToast || firstForSession;
for (let i = 0; i < entries.length; i++) {
this.crostini_.registerSharedPath(vmName, entries[i]);
}
resolve(entries.length);
});
});
};
const toast = (count, msgSingle, msgPlural, action, subPage, umaItem) => {
if (!showToast || count == 0) {
return;
}
this.ui_.toast.show(
count == 1 ? str(msgSingle) : strf(msgPlural, count), {
text: str(action),
callback: () => {
chrome.fileManagerPrivate.openSettingsSubpage(subPage);
CommandHandler.recordMenuItemSelected(umaItem);
}
});
};
Promise
.all([
getSharedPaths(constants.DEFAULT_CROSTINI_VM),
getSharedPaths(constants.PLUGIN_VM)
])
.then(([crostiniShareCount, pluginVmShareCount]) => {
toast(
crostiniShareCount, 'FOLDER_SHARED_WITH_CROSTINI',
'FOLDER_SHARED_WITH_CROSTINI_PLURAL',
'MANAGE_LINUX_SHARING_BUTTON_LABEL', 'crostini/sharedPaths',
CommandHandler.MenuCommandsForUMA
.MANAGE_LINUX_SHARING_TOAST_STARTUP);
// TODO(crbug.com/949356): UX to provide guidance for what to do
// when we have shared paths with both Linux and Plugin VM.
toast(
pluginVmShareCount, 'FOLDER_SHARED_WITH_PLUGIN_VM',
'FOLDER_SHARED_WITH_PLUGIN_VM_PLURAL',
'MANAGE_PLUGIN_VM_SHARING_BUTTON_LABEL', 'pluginVm/sharedPaths',
CommandHandler.MenuCommandsForUMA
.MANAGE_PLUGIN_VM_SHARING_TOAST_STARTUP);
});
};
......@@ -1217,9 +1245,11 @@ FileManager.prototype = /** @struct */ {
*/
FileManager.prototype.onCrostiniChanged_ = function(event) {
if (event.eventType === 'enable') {
this.setCrostiniEnabled_(true);
this.crostini_.setEnabled(event.vmName, true);
this.setupCrostini_();
} else if (event.eventType === 'disable') {
this.setCrostiniEnabled_(false);
this.crostini_.setEnabled(event.vmName, false);
this.setupCrostini_();
}
};
......
......@@ -453,6 +453,11 @@ CommandHandler.MenuCommandsForUMA = {
MANAGE_LINUX_SHARING: 'manage-linux-sharing',
MANAGE_LINUX_SHARING_TOAST: 'manage-linux-sharing-toast',
MANAGE_LINUX_SHARING_TOAST_STARTUP: 'manage-linux-sharing-toast-startup',
SHARE_WITH_PLUGIN_VM: 'share-with-plugin-vm',
MANAGE_PLUGIN_VM_SHARING: 'manage-plugin-vm-sharing',
MANAGE_PLUGIN_VM_SHARING_TOAST: 'manage-plugin-vm-sharing-toast',
MANAGE_PLUGIN_VM_SHARING_TOAST_STARTUP:
'manage-plugin-vm-sharing-toast-startup',
};
/**
......@@ -481,6 +486,10 @@ CommandHandler.ValidMenuCommandsForUMA = [
CommandHandler.MenuCommandsForUMA.MANAGE_LINUX_SHARING,
CommandHandler.MenuCommandsForUMA.MANAGE_LINUX_SHARING_TOAST,
CommandHandler.MenuCommandsForUMA.MANAGE_LINUX_SHARING_TOAST_STARTUP,
CommandHandler.MenuCommandsForUMA.SHARE_WITH_PLUGIN_VM,
CommandHandler.MenuCommandsForUMA.MANAGE_PLUGIN_VM_SHARING,
CommandHandler.MenuCommandsForUMA.MANAGE_PLUGIN_VM_SHARING_TOAST,
CommandHandler.MenuCommandsForUMA.MANAGE_PLUGIN_VM_SHARING_TOAST_STARTUP,
];
console.assert(
Object.keys(CommandHandler.MenuCommandsForUMA).length ===
......@@ -1818,7 +1827,7 @@ CommandHandler.COMMANDS_['manage-in-drive'] = /** @type {Command} */ ({
/**
* Shares the selected (single only) directory with the crostini container.
* Shares the selected (single only) directory with the default crostini VM.
* @type {Command}
*/
CommandHandler.COMMANDS_['share-with-linux'] = /** @type {Command} */ ({
......@@ -1890,7 +1899,7 @@ CommandHandler.COMMANDS_['share-with-linux'] = /** @type {Command} */ ({
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
// Must be single directory subfolder of Downloads not already shared.
// Must be single directory not already shared.
const entries = CommandUtil.getCommandEntries(event.target);
event.canExecute = entries.length === 1 && entries[0].isDirectory &&
!fileManager.crostini.isPathShared(
......@@ -1901,6 +1910,88 @@ CommandHandler.COMMANDS_['share-with-linux'] = /** @type {Command} */ ({
}
});
/**
* Shares the selected (single only) directory with the Plugin VM.
* @type {Command}
*/
CommandHandler.COMMANDS_['share-with-plugin-vm'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
const entry = CommandUtil.getCommandEntry(event.target);
if (!entry || !entry.isDirectory) {
return;
}
const dir = /** @type {!DirectoryEntry} */ (entry);
const info = fileManager.volumeManager.getLocationInfo(dir);
if (!info) {
return;
}
function share() {
// Always persist shares via right-click > Share with PluginVM.
chrome.fileManagerPrivate.sharePathsWithCrostini(
constants.PLUGIN_VM, [dir], true /* persist */, () => {
if (chrome.runtime.lastError) {
console.error(
'Error sharing with Plugin VM: ' +
chrome.runtime.lastError.message);
}
});
// Register the share and show the 'Manage PluginVM sharing' toast
// immediately, since the container may take 10s or more to start.
fileManager.crostini.registerSharedPath(constants.PLUGIN_VM, dir);
fileManager.ui.toast.show(str('FOLDER_SHARED_WITH_CROSTINI'), {
text: str('MANAGE_LINUX_SHARING_BUTTON_LABEL'),
callback: () => {
chrome.fileManagerPrivate.openSettingsSubpage('pluginvm/sharedPaths');
CommandHandler.recordMenuItemSelected(
CommandHandler.MenuCommandsForUMA.MANAGE_PLUGIN_VM_SHARING_TOAST);
}
});
}
// Show a confirmation dialog if we are sharing the root of a volume.
// Non-Drive volume roots are always '/'.
if (dir.fullPath == '/') {
fileManager.ui_.confirmDialog.showHtml(
strf('SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE'),
strf('SHARE_ROOT_FOLDER_WITH_CROSTINI', info.volumeInfo.label), share,
() => {});
} else if (
info.isRootEntry &&
(info.rootType == VolumeManagerCommon.RootType.DRIVE ||
info.rootType == VolumeManagerCommon.RootType.COMPUTERS_GRAND_ROOT ||
info.rootType ==
VolumeManagerCommon.RootType.SHARED_DRIVES_GRAND_ROOT)) {
// Only show the dialog for My Drive, Shared Drives Grand Root and
// Computers Grand Root. Do not show for roots of a single Shared Drive
// or Computer.
fileManager.ui_.confirmDialog.showHtml(
strf('SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE'),
strf('SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE'), share, () => {});
} else {
// This is not a root, share it without confirmation dialog.
share();
}
CommandHandler.recordMenuItemSelected(
CommandHandler.MenuCommandsForUMA.SHARE_WITH_PLUGIN_VM);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
// Must be single directory subfolder of Downloads not already shared.
const entries = CommandUtil.getCommandEntries(event.target);
event.canExecute = entries.length === 1 && entries[0].isDirectory &&
!fileManager.crostini.isPathShared(constants.PLUGIN_VM, entries[0]) &&
fileManager.crostini.canSharePath(
constants.PLUGIN_VM, entries[0], true /* persist */);
event.command.setHidden(!event.canExecute);
}
});
/**
* Link to settings page from gear menu. Allows the user to manage files and
* folders shared with the crostini container.
......@@ -1922,7 +2013,8 @@ CommandHandler.COMMANDS_['manage-linux-sharing-gear'] =
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
event.canExecute = fileManager.crostini.isEnabled();
event.canExecute =
fileManager.crostini.isEnabled(constants.DEFAULT_CROSTINI_VM);
event.command.setHidden(!event.canExecute);
}
});
......@@ -1955,6 +2047,59 @@ CommandHandler.COMMANDS_['manage-linux-sharing'] = /** @type {Command} */ ({
}
});
/**
* Link to settings page from gear menu. Allows the user to manage files and
* folders shared with the Plugin VM.
* @type {Command}
*/
CommandHandler.COMMANDS_['manage-plugin-vm-sharing-gear'] =
/** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
chrome.fileManagerPrivate.openSettingsSubpage('pluginvm/sharedPaths');
CommandHandler.recordMenuItemSelected(
CommandHandler.MenuCommandsForUMA.MANAGE_PLUGIN_VM_SHARING);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
event.canExecute = fileManager.crostini.isEnabled(constants.PLUGIN_VM);
event.command.setHidden(!event.canExecute);
}
});
/**
* Link to settings page from file context menus (not gear menu). Allows
* the user to manage files and folders shared with the Plugin VM.
* @type {Command}
*/
CommandHandler.COMMANDS_['manage-plugin-vm-sharing'] = /** @type {Command} */ ({
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
execute: function(event, fileManager) {
chrome.fileManagerPrivate.openSettingsSubpage('pluginvm/sharedPaths');
CommandHandler.recordMenuItemSelected(
CommandHandler.MenuCommandsForUMA.MANAGE_PLUGIN_VM_SHARING);
},
/**
* @param {!Event} event Command event.
* @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
*/
canExecute: function(event, fileManager) {
const entries = CommandUtil.getCommandEntries(event.target);
event.canExecute = entries.length === 1 && entries[0].isDirectory &&
fileManager.crostini.isPathShared(constants.PLUGIN_VM, entries[0]);
event.command.setHidden(!event.canExecute);
}
});
/**
* Creates a shortcut of the selected folder (single only).
* @type {Command}
......
......@@ -576,8 +576,8 @@ function testMaybeShareCrostiniOrShowDialog() {
const crostini = createCrostiniForTest();
crostini.init(volumeManagerDownloads);
crostini.setEnabled(true);
crostini.registerSharedPath('vm', sharedDir);
crostini.setEnabled('termina', true);
crostini.registerSharedPath('termina', sharedDir);
const notShared1 = new MockFileEntry(mockFsDownloads, '/notShared/file1');
const notShared2 = new MockFileEntry(mockFsDownloads, '/notShared/file2');
......@@ -627,12 +627,12 @@ function testMaybeShareCrostiniOrShowDialog() {
expect('No entries', [], true, '', '');
crostini.setEnabled(false);
crostini.setEnabled('termina', false);
expect(
'Single entry, crostini-files not enabled', [notShared1], false,
'UNABLE_TO_OPEN_CROSTINI_TITLE', 'UNABLE_TO_OPEN_CROSTINI');
crostini.setEnabled(true);
crostini.setEnabled('termina', true);
expect('Single entry, not shared', [notShared1], true, '', '');
......@@ -642,7 +642,7 @@ function testMaybeShareCrostiniOrShowDialog() {
'2 entries, not shared, same dir', [notShared1, notShared2], true, '',
'');
// Non-persistent shares should not be registered.
assertFalse(crostini.isPathShared('vm', notShared1));
assertFalse(crostini.isPathShared('termina', notShared1));
expect(
'2 entries, not shared, different dir', [notShared1, otherNotShared],
......
......@@ -173,6 +173,9 @@
<command id="share-with-linux" label="$i18n{SHARE_WITH_LINUX_BUTTON_LABEL}" disabled hidden>
<command id="manage-linux-sharing" label="$i18n{MANAGE_LINUX_SHARING_BUTTON_LABEL}" disabled hidden>
<command id="manage-linux-sharing-gear" label="$i18n{MANAGE_LINUX_SHARING_BUTTON_LABEL}" disabled hidden>
<command id="share-with-plugin-vm" label="$i18n{SHARE_WITH_PLUGIN_VM_BUTTON_LABEL}" disabled hidden>
<command id="manage-plugin-vm-sharing" label="$i18n{MANAGE_PLUGIN_VM_SHARING_BUTTON_LABEL}" disabled hidden>
<command id="manage-plugin-vm-sharing-gear" label="$i18n{MANAGE_PLUGIN_VM_SHARING_BUTTON_LABEL}" disabled hidden>
<command id="zoom-in" shortcut="=|Ctrl">
<command id="zoom-out" shortcut="-|Ctrl">
......@@ -218,6 +221,8 @@
<cr-menu-item command="#zip-selection"></cr-menu-item>
<cr-menu-item command="#share-with-linux"></cr-menu-item>
<cr-menu-item command="#manage-linux-sharing"></cr-menu-item>
<cr-menu-item command="#share-with-plugin-vm"></cr-menu-item>
<cr-menu-item command="#manage-plugin-vm-sharing"></cr-menu-item>
<cr-menu-item command="#set-wallpaper"></cr-menu-item>
<hr visibleif="saveas-file full-page" class="hide-on-toolbar">
<cr-menu-item command="#new-folder" visibleif="saveas-file full-page"
......@@ -233,6 +238,8 @@
<cr-menu-item command="#remove-folder-shortcut"></cr-menu-item>
<cr-menu-item command="#share-with-linux"></cr-menu-item>
<cr-menu-item command="#manage-linux-sharing"></cr-menu-item>
<cr-menu-item command="#share-with-plugin-vm"></cr-menu-item>
<cr-menu-item command="#manage-plugin-vm-sharing"></cr-menu-item>
</cr-menu>
<cr-menu id="directory-tree-context-menu" class="chrome-menu files-menu"
......@@ -242,6 +249,8 @@
<cr-menu-item command="#paste-into-folder" visibleif="full-page"></cr-menu-item>
<cr-menu-item command="#share-with-linux"></cr-menu-item>
<cr-menu-item command="#manage-linux-sharing"></cr-menu-item>
<cr-menu-item command="#share-with-plugin-vm"></cr-menu-item>
<cr-menu-item command="#manage-plugin-vm-sharing"></cr-menu-item>
<hr visibleif="full-page">
<cr-menu-item command="#format"></cr-menu-item>
<cr-menu-item command="#rename"></cr-menu-item>
......@@ -281,6 +290,8 @@
command="#toggle-hidden-android-folders"></cr-menu-item>
<cr-menu-item id="gear-menu-manage-linux-sharing"
command="#manage-linux-sharing-gear"></cr-menu-item>
<cr-menu-item id="gear-menu-manage-plugin-vm-sharing"
command="#manage-plugin-vm-sharing-gear"></cr-menu-item>
<cr-menu-item id="gear-menu-drive-sync-settings"
command="#drive-sync-settings"></cr-menu-item>
<hr id="help-separator">
......@@ -316,6 +327,8 @@
<cr-menu-item command="#share"></cr-menu-item>
<cr-menu-item command="#share-with-linux"></cr-menu-item>
<cr-menu-item command="#manage-linux-sharing"></cr-menu-item>
<cr-menu-item command="#share-with-plugin-vm"></cr-menu-item>
<cr-menu-item command="#manage-plugin-vm-sharing"></cr-menu-item>
<hr id="drive-share-separator">
<hr id="more-actions-separator">
<cr-menu-item command="#show-submenu"
......
......@@ -8,12 +8,12 @@ crostiniMount.testCrostiniNotEnabled = async (done) => {
const fakeRoot = '#directory-tree [root-type-icon="crostini"]';
await test.setupAndWaitUntilReady();
chrome.fileManagerPrivate.onCrostiniChanged.dispatchEvent(
{eventType: 'disable'});
{eventType: 'disable', vmName: 'termina'});
await test.waitForElementLost(fakeRoot);
// Reset crostini back to default enabled=true.
chrome.fileManagerPrivate.onCrostiniChanged.dispatchEvent(
{eventType: 'enable'});
{eventType: 'enable', vmName: 'termina'});
await test.waitForElement(fakeRoot);
done();
};
......
......@@ -16,6 +16,7 @@ Object.setPrototypeOf(loadTimeData.data_, {
'GOOGLE_DRIVE_OVERVIEW_URL':
'https://support.google.com/chromebook/?p=filemanager_drive',
'HIDE_SPACE_INFO': false,
'PLUGIN_VM_ENABLED': true,
'UI_LOCALE': 'en_US',
'language': 'en-US',
'textdirection': 'ltr',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment