Commit 40f27b9b authored by Joel Hockey's avatar Joel Hockey Committed by Commit Bot

Update FilesApp PluginVm sharing messages

Added tests for dialog messages, and refactored tests
by combining 2 similar tests together.
This should reduce overall overhead on the
bots and maybe help keep test time within
timeout limits.

Bug: 946273
Change-Id: I8f0c3ee98c308b45a3ce56eb6fb72931170ec477
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1616718Reviewed-by: default avatarLuciano Pacheco <lucmult@chromium.org>
Commit-Queue: Joel Hockey <joelhockey@chromium.org>
Cr-Commit-Position: refs/heads/master@{#661242}
parent e93ef5af
......@@ -755,6 +755,12 @@ std::unique_ptr<base::DictionaryValue> GetFileManagerStrings() {
IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI);
SET_STRING("SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE",
IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE);
SET_STRING("SHARE_ROOT_FOLDER_WITH_PLUGIN_VM_TITLE",
IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_PLUGIN_VM_TITLE);
SET_STRING("SHARE_ROOT_FOLDER_WITH_PLUGIN_VM",
IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_PLUGIN_VM);
SET_STRING("SHARE_ROOT_FOLDER_WITH_PLUGIN_VM_DRIVE",
IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_PLUGIN_VM_DRIVE);
SET_STRING("SIZE_BYTES", IDS_FILE_BROWSER_SIZE_BYTES);
SET_STRING("SIZE_COLUMN_LABEL", IDS_FILE_BROWSER_SIZE_COLUMN_LABEL);
SET_STRING("SIZE_GB", IDS_FILE_BROWSER_SIZE_GB);
......
......@@ -83,7 +83,7 @@
<message name="IDS_FILE_BROWSER_MEDIA_VIEW_AUDIO_ROOT_LABEL" desc="A label for the 'Audio' root of media views.">
Audio
</message>
<message name="IDS_FILE_BROWSER_PLUGIN_VM_DIRECTORY_LABEL" desc="PluginVm local directory label.">
<message name="IDS_FILE_BROWSER_PLUGIN_VM_DIRECTORY_LABEL" translateable="false" desc="PluginVm local directory label.">
Plugin VM
</message>
<message name="IDS_FILE_BROWSER_RECENT_ROOT_LABEL" desc="A label for the 'Recent' root which shows files recently modified by the user.">
......@@ -555,10 +555,10 @@
<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.">
<message name="IDS_FILE_BROWSER_SHARE_WITH_PLUGIN_VM_BUTTON_LABEL" translateable="false" 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.">
<message name="IDS_FILE_BROWSER_MANAGE_PLUGIN_VM_SHARING_BUTTON_LABEL" translateable="false" 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.">
......@@ -1081,10 +1081,10 @@
<message name="IDS_FILE_BROWSER_UNABLE_TO_OPEN_CROSTINI" desc="Message shown when a user tries to use a crostini app to open a file which cannot be shared with the crostini container (e.g. in Play or USB). This message will be removed once we support this action.">
To open files with <ph name="APP_NAME">$1<ex>Visual Studio Code</ex></ph>, first copy to Linux files folder.
</message>
<message name="IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE" desc="Message title shown when a user shares the root of a volume such as Downloads with the crostini container.">
<message name="IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_TITLE" desc="Message title shown when a user shares the root of a volume such as 'My files' with the crostini container.">
Share folder with Linux
</message>
<message name="IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI" desc="Confirmation message shown when a user shares the root of a volume such as Downloads with the crostini container.">
<message name="IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI" desc="Confirmation message shown when a user shares the root of a volume such as 'My files' with the crostini container.">
Give Linux apps permission to modify files in the <ph name="FOLDER_NAME">$1<ex>Downloads</ex></ph> folder
</message>
<message name="IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_CROSTINI_DRIVE" desc="Confirmation message shown when a user shares the root of a Drive volume (My Drive, Team Drives, Computers) with the crostini container.">
......@@ -1096,10 +1096,19 @@
<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.">
<message name="IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_PLUGIN_VM_TITLE" translateable="false" desc="Message title shown when a user shares the root of a volume such as 'My files' with the Plugin VM.">
Share folder with PluginVm
</message>
<message name="IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_PLUGIN_VM" translateable="false" desc="Confirmation message shown when a user shares the root of a volume such as 'My files' with the Plugin VM." >
Give Plugin VM permission to modify files in the <ph name="FOLDER_NAME">$1<ex>Downloads</ex></ph> folder
</message>
<message name="IDS_FILE_BROWSER_SHARE_ROOT_FOLDER_WITH_PLUGIN_VM_DRIVE" translateable="false" desc="Confirmation message shown when a user shares the root of a Drive volume (My Drive, Team Drives, Computers) with the Plugin VM.">
Give Plugin VM permission to modify files in your Google Drive. Changes will sync to your other devices.
</message>
<message name="IDS_FILE_BROWSER_FOLDER_SHARED_WITH_PLUGIN_VM" translateable="false" 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.">
<message name="IDS_FILE_BROWSER_FOLDER_SHARED_WITH_PLUGIN_VM_PLURAL" translateable="false" 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>
......
......@@ -2056,9 +2056,9 @@ CommandHandler.COMMANDS_['share-with-plugin-vm'] = /** @type {Command} */ ({
// 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,
() => {});
strf('SHARE_ROOT_FOLDER_WITH_PLUGIN_VM_TITLE'),
strf('SHARE_ROOT_FOLDER_WITH_PLUGIN_VM', info.volumeInfo.label),
share, () => {});
} else if (
info.isRootEntry &&
(info.rootType == VolumeManagerCommon.RootType.DRIVE ||
......@@ -2069,8 +2069,8 @@ CommandHandler.COMMANDS_['share-with-plugin-vm'] = /** @type {Command} */ ({
// 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, () => {});
strf('SHARE_ROOT_FOLDER_WITH_PLUGIN_VM_TITLE'),
strf('SHARE_ROOT_FOLDER_WITH_PLUGIN_VM_DRIVE'), share, () => {});
} else {
// This is not a root, share it without confirmation dialog.
share();
......
......@@ -18,8 +18,30 @@ const shareBase = {
const crostiniShare = {};
const pluginVmShare = {};
shareBase.testSharePathsSuccess =
async (vmName, vmNameSelector, enumUma, done) => {
// Right click clickTarget, ensure menuVisible is shown,
// Click menuTarget, ensure dialog is shown with expectedText.
shareBase.verifyShareWithDialog =
async (name, clickTarget, menuVisible, menuTarget, expectedText) => {
const dialog = '.cr-dialog-container';
const dialogVisible = '.cr-dialog-container.shown';
const dialogText = '.cr-dialog-container.shown .cr-dialog-text';
const dialogCancel = 'button.cr-dialog-cancel';
// Check 'Share with <VM>' is shown in menu.
assertTrue(test.fakeMouseRightClick(clickTarget), 'right-click ' + name);
await test.waitForElement(menuVisible);
// Click 'Share with <VM>', verify dialog and text.
assertTrue(test.fakeMouseClick(menuTarget, 'Share with <VM> ' + name));
await test.waitForElement(dialogVisible);
assertEquals(expectedText, document.querySelector(dialogText).innerText);
// Click Cancel button to close.
assertTrue(test.fakeMouseClick(dialogCancel));
await test.waitForElementLost(dialog);
};
shareBase.testSharePaths = async (vmName, vmNameSelector, enumUma, done) => {
const share = 'share-with-' + vmNameSelector;
const manage = 'manage-' + vmNameSelector + '-sharing';
const menuNoShareWith = '#file-context-menu:not([hidden]) ' +
......@@ -37,6 +59,18 @@ shareBase.testSharePathsSuccess =
'#directory-tree-context-menu [command="#' + share + '"]';
const photos = '#file-list [file-name="photos"]';
const myFilesDirTree = '#directory-tree [root-type-icon="my_files"]';
const removableRoot = '#directory-tree [volume-type-icon="removable"]';
const menuShareWithVolumeRoot = '#roots-context-menu:not([hidden]) ' +
'[command="#' + share + '"]:not([hidden]):not([disabled])';
const shareWithVolumeRoot = '#roots-context-menu [command="#' + share + '"]';
const fakeLinuxFiles = '#directory-tree [root-type-icon="crostini"]';
const googleDrive = '#directory-tree .tree-item [volume-type-icon="drive"]';
const menuHidden = '#file-context-menu[hidden]';
const androidRoot = '#directory-tree [volume-type-icon="android_files"]';
const shareLabel = {'termina': 'Linux apps', 'PluginVm': 'Plugin VM'};
const givePermission = `Give ${shareLabel[vmName]} permission to modify `;
const oldSharePaths = chrome.fileManagerPrivate.sharePathsWithCrostini;
let sharePathsCalled = false;
let sharePathsPersist;
......@@ -116,64 +150,11 @@ shareBase.testSharePathsSuccess =
assertTrue(test.fakeMouseRightClick(photos), 'right-click photos');
await test.waitForElement(menuShareWith);
// Verify dialog is shown for MyFiles root.
// Check 'Share with <VM>' is shown in menu.
assertTrue(test.fakeMouseRightClick(myFilesDirTree), 'right-click MyFiles');
await test.waitForElement(menuShareWithDirTree);
// Click 'Share with <VM>', verify dialog.
assertTrue(test.fakeMouseClick(shareWithDirTree, 'Share with <VM>'));
await test.waitForElement('.cr-dialog-container.shown');
// Click Cancel button to close.
assertTrue(test.fakeMouseClick('button.cr-dialog-cancel'));
await test.waitForElementLost('.cr-dialog-container');
// Verify share for MyFiles.
await shareBase.verifyShareWithDialog(
'MyFiles root', myFilesDirTree, menuShareWithDirTree, shareWithDirTree,
givePermission + 'files in the My files folder');
// Restore fmp.*.
chrome.fileManagerPrivate.sharePathsWithCrostini = oldSharePaths;
// Restore Crostini.unregisterSharedPath.
fileManager.crostini.unregisterSharedPath = oldCrostiniUnregister;
done();
};
crostiniShare.testSharePathsSuccess = done => {
shareBase.testSharePathsSuccess(
shareBase.vmNameTermina, shareBase.vmNameSelectorLinux,
shareBase.enumUmaShareWithLinux, done);
};
pluginVmShare.testSharePathsSuccess = done => {
shareBase.testSharePathsSuccess(
shareBase.vmNamePluginVm, shareBase.vmNameSelectorPluginVm,
shareBase.enumUmaShareWithPluginVm, done);
};
// Verify right-click menu with 'Share with <VM>' is not shown
// for:
// * Files (not directory).
// * Any folder already shared.
// * Root Downloads folder.
// * Any folder outside of downloads (e.g. crostini or drive).
// * Is shown for drive if DriveFS is enabled.
shareBase.testSharePathShown = async (vmName, vmNameSelector, done) => {
const share = 'share-with-' + vmNameSelector;
const myFiles = '#directory-tree .tree-item [root-type-icon="my_files"]';
const downloads = '#file-list li [file-type-icon="downloads"]';
const linuxFiles = '#directory-tree .tree-item [root-type-icon="crostini"]';
const googleDrive = '#directory-tree .tree-item [volume-type-icon="drive"]';
const menuHidden = '#file-context-menu[hidden]';
const menuNoShareWith = '#file-context-menu:not([hidden]) ' +
'[command="#' + share + '"][hidden][disabled="disabled"]';
const menuShareWith = '#file-context-menu:not([hidden]) ' +
'[command="#' + share + '"]:not([hidden]):not([disabled])';
const removableVolumeRoot = '#directory-tree [volume-type-icon="removable"]';
const menuShareWithDirTree = '#directory-tree-context-menu:not([hidden]) ' +
'[command="#' + share + '"]:not([hidden]):not([disabled])';
const menuShareWithVolumeRoot = '#roots-context-menu:not([hidden]) ' +
'[command="#' + share + '"]:not([hidden]):not([disabled])';
let alreadySharedPhotosDir;
await test.setupAndWaitUntilReady();
// Right-click 'hello.txt' file.
// Check 'Share with <VM>' is not shown in menu.
assertTrue(
......@@ -181,44 +162,17 @@ shareBase.testSharePathShown = async (vmName, vmNameSelector, done) => {
'right-click hello.txt');
await test.waitForElement(menuNoShareWith);
// Set a folder as already shared.
alreadySharedPhotosDir =
mockVolumeManager
.getCurrentProfileVolumeInfo(VolumeManagerCommon.VolumeType.DOWNLOADS)
.fileSystem.entries['/photos'];
fileManager.crostini.registerSharedPath(vmName, alreadySharedPhotosDir);
assertTrue(
test.fakeMouseRightClick('#file-list [file-name="photos"]'),
'right-click hello.txt');
await test.waitForElement(menuNoShareWith);
// Select 'My files' in directory tree to show Downloads in file list.
assertTrue(test.fakeMouseClick(myFiles), 'click My files');
await test.waitForElement(downloads);
// Right-click 'Downloads' directory.
// Check 'Share with <VM>' is shown in menu.
assertTrue(test.fakeMouseRightClick(downloads), 'right-click downloads');
await test.waitForElement(menuShareWith);
// Right-click 'MyFiles' in directory tree.
// Check 'Share with <VM>' is shown in menu.
assertTrue(test.fakeMouseRightClick(myFiles), 'MyFiles dirtree');
await test.waitForElement(menuShareWithDirTree);
// Select removable root.
// Verify share for removable root.
test.mountRemovable();
await test.waitForElement(removableVolumeRoot);
// Right-click 'MyUSB' removable root.
// Check 'Share with <VM>' is shown in menu.
assertTrue(test.fakeMouseRightClick(removableVolumeRoot), 'removable root');
await test.waitForElement(menuShareWithVolumeRoot);
await test.waitForElement(removableRoot);
await shareBase.verifyShareWithDialog(
'Removable root', removableRoot, menuShareWithVolumeRoot,
shareWithVolumeRoot, givePermission + 'files in the MyUSB folder');
// Select 'Linux files' in directory tree to show dir A in file list.
await test.waitForElement(linuxFiles);
await test.waitForElement(fakeLinuxFiles);
assertTrue(test.fakeMouseClick(linuxFiles), 'click Linux files');
assertTrue(test.fakeMouseClick(fakeLinuxFiles), 'click Linux files');
await test.waitForFiles(
test.TestEntryInfo.getExpectedRows(test.BASIC_CROSTINI_ENTRY_SET));
......@@ -238,41 +192,54 @@ shareBase.testSharePathShown = async (vmName, vmNameSelector, done) => {
test.TestEntryInfo.getExpectedRows(test.BASIC_DRIVE_ENTRY_SET));
// Check 'Share with <VM>' is not shown in menu.
assertTrue(
test.fakeMouseRightClick('#file-list [file-name="photos"]'),
'right-click photos');
assertTrue(test.fakeMouseRightClick(photos), 'right-click photos');
await test.waitForElement(menuNoShareWith);
// Close menu by clicking file-list.
assertTrue(test.fakeMouseClick('#file-list'));
await test.waitForElement(menuHidden);
// Set DRIVE_FS_ENABLED, and check that 'Share with <VM>' is shown.
// Set DRIVE_FS_ENABLED=true, and check that 'Share with <VM>' is shown.
loadTimeData.data_['DRIVE_FS_ENABLED'] = true;
// Check 'Share with <VM>' is not shown in menu.
assertTrue(
test.fakeMouseRightClick('#file-list [file-name="photos"]'),
'right-click photos');
// Check 'Share with <VM>' is shown in menu.
assertTrue(test.fakeMouseRightClick(photos), 'right-click photos');
await test.waitForElement(menuShareWith);
// Reset Linux files back to unmounted.
// Verify share with dialog for MyDrive.
await shareBase.verifyShareWithDialog(
'My Drive', googleDrive, menuShareWithVolumeRoot, shareWithVolumeRoot,
givePermission + 'files in your Google Drive. ' +
'Changes will sync to your other devices.');
// Verify share with dialog for Play files.
test.mountAndroidFiles();
await test.waitForElement(androidRoot);
await shareBase.verifyShareWithDialog(
'Android files', androidRoot, menuShareWithDirTree, shareWithDirTree,
givePermission + 'files in the Play files folder');
// Reset Linux files and Play files back to unmounted.
chrome.fileManagerPrivate.removeMount('crostini');
await test.waitForElement(
'#directory-tree .tree-item [root-type-icon="crostini"]');
await test.waitForElement(fakeLinuxFiles);
chrome.fileManagerPrivate.removeMount('android_files');
// Clear Crostini shared folders.
fileManager.crostini.unregisterSharedPath(vmName, alreadySharedPhotosDir);
// Restore fmp.*.
chrome.fileManagerPrivate.sharePathsWithCrostini = oldSharePaths;
// Restore Crostini.unregisterSharedPath.
fileManager.crostini.unregisterSharedPath = oldCrostiniUnregister;
done();
};
crostiniShare.testSharePathShown = done => {
shareBase.testSharePathShown(
shareBase.vmNameTermina, shareBase.vmNameSelectorLinux, done);
crostiniShare.testSharePaths = done => {
shareBase.testSharePaths(
shareBase.vmNameTermina, shareBase.vmNameSelectorLinux,
shareBase.enumUmaShareWithLinux, done);
};
pluginVmShare.testSharePathShown = done => {
shareBase.testSharePathShown(
shareBase.vmNamePluginVm, shareBase.vmNameSelectorPluginVm, done);
pluginVmShare.testSharePaths = done => {
shareBase.testSharePaths(
shareBase.vmNamePluginVm, shareBase.vmNameSelectorPluginVm,
shareBase.enumUmaShareWithPluginVm, done);
};
// Verify gear menu 'Manage ? sharing'.
......
......@@ -447,18 +447,28 @@ test.addEntries = function(downloads, drive, crostini) {
'MyUSB')
.fileSystem);
fsRemovable.populate([], true);
const fsAndroidFiles = /** @type {MockFileSystem} */ (
mockVolumeManager
.createVolumeInfo(
VolumeManagerCommon.VolumeType.ANDROID_FILES, 'android_files',
str('ANDROID_FILES_ROOT_LABEL'))
.fileSystem);
fsAndroidFiles.populate([], true);
};
/**
* Sends mount event for crostini volume.
* Sends mount event.
* @param {!VolumeManagerCommon.VolumeType} volumeType
* @param {string} volumeId
*/
test.mountCrostini = function() {
test.mount = function(volumeType, volumeId) {
chrome.fileManagerPrivate.onMountCompleted.dispatchEvent({
status: 'success',
eventType: 'mount',
volumeMetadata: {
volumeType: VolumeManagerCommon.VolumeType.CROSTINI,
volumeId: 'crostini',
volumeType: volumeType,
volumeId: volumeId,
isReadOnly: false,
iconSet: {},
profile: {isCurrentProfile: true, displayName: ''},
......@@ -470,19 +480,22 @@ test.mountCrostini = function() {
/**
* Sends mount event for crostini volume.
*/
test.mountCrostini = function() {
test.mount(VolumeManagerCommon.VolumeType.CROSTINI, 'crostini');
};
/**
* Sends mount event for removable volume.
*/
test.mountRemovable = function() {
chrome.fileManagerPrivate.onMountCompleted.dispatchEvent({
status: 'success',
eventType: 'mount',
volumeMetadata: {
volumeType: VolumeManagerCommon.VolumeType.REMOVABLE,
volumeId: 'removable:MyUSB',
isReadOnly: false,
iconSet: {},
profile: {isCurrentProfile: true, displayName: ''},
mountContext: 'user',
},
});
test.mount(VolumeManagerCommon.VolumeType.REMOVABLE, 'removable:MyUSB');
};
/**
* Sends mount event for android files volume.
*/
test.mountAndroidFiles = function() {
test.mount(VolumeManagerCommon.VolumeType.ANDROID_FILES, 'android_files');
};
/**
......
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