Commit bdefcc2d authored by Joel Hockey's avatar Joel Hockey Committed by Commit Bot

PluginVm in FilesApp: set icon and read-only status

Bug: 955920
Change-Id: Iff3e97b187368683d89cbf7200d200046c73e095
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1580988Reviewed-by: default avatarLuciano Pacheco <lucmult@chromium.org>
Commit-Queue: Joel Hockey <joelhockey@chromium.org>
Cr-Commit-Position: refs/heads/master@{#654793}
parent 31976e73
......@@ -683,6 +683,8 @@ std::unique_ptr<base::DictionaryValue> GetFileManagerStrings() {
SET_STRING("PASTE_BUTTON_LABEL", IDS_FILE_BROWSER_PASTE_BUTTON_LABEL);
SET_STRING("PASTE_INTO_FOLDER_BUTTON_LABEL",
IDS_FILE_BROWSER_PASTE_INTO_FOLDER_BUTTON_LABEL);
SET_STRING("PLUGIN_VM_DIRECTORY_LABEL",
IDS_FILE_BROWSER_PLUGIN_VM_DIRECTORY_LABEL);
SET_STRING("PREPARING_LABEL", IDS_FILE_BROWSER_PREPARING_LABEL);
SET_STRING("QUICK_VIEW_CLOSE_BUTTON_LABEL",
IDS_FILE_BROWSER_QUICK_VIEW_CLOSE_BUTTON_LABEL);
......
......@@ -87,6 +87,10 @@ IN_PROC_BROWSER_TEST_F(FileManagerUITest, Menu) {
RunTest("menu");
}
IN_PROC_BROWSER_TEST_F(FileManagerUITest, PluginVm) {
RunTest("pluginVm");
}
IN_PROC_BROWSER_TEST_F(FileManagerUITest, PluginVmShare) {
RunTest("pluginVmShare");
}
......
......@@ -77,6 +77,9 @@
<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.">
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.">
Recent
</message>
......
......@@ -620,6 +620,7 @@ FileType.getIconOverrides = (entry, opt_rootType) => {
const overrides = {
[VolumeManagerCommon.RootType.DOWNLOADS]: {
'/Downloads': VolumeManagerCommon.VolumeType.DOWNLOADS,
'/PluginVm': 'plugin_vm',
},
};
const root = overrides[opt_rootType];
......
......@@ -1151,12 +1151,16 @@ util.getEntryLabel = (locationInfo, entry) => {
return util.getRootTypeLabel(locationInfo);
}
// Special case for MyFiles/Downloads.
if (locationInfo && util.isMyFilesVolumeEnabled() &&
locationInfo.rootType == VolumeManagerCommon.RootType.DOWNLOADS &&
entry.fullPath == '/Downloads') {
// Special case for MyFiles/Downloads and MyFiles/PluginVm.
if (locationInfo &&
locationInfo.rootType == VolumeManagerCommon.RootType.DOWNLOADS) {
if (util.isMyFilesVolumeEnabled() && entry.fullPath == '/Downloads') {
return str('DOWNLOADS_DIRECTORY_LABEL');
}
if (util.isPluginVmEnabled() && entry.fullPath == '/PluginVm') {
return str('PLUGIN_VM_DIRECTORY_LABEL');
}
}
return entry.name;
};
......@@ -1510,6 +1514,12 @@ util.isMyFilesVolumeEnabled = () => {
loadTimeData.getBoolean('MY_FILES_VOLUME_ENABLED');
};
/** @return {boolean} */
util.isPluginVmEnabled = () => {
return loadTimeData.valueExists('PLUGIN_VM_ENABLED') &&
loadTimeData.getBoolean('PLUGIN_VM_ENABLED');
};
/**
* Used for logs and debugging. It tries to tell what type is the entry, its
* path and URL.
......
......@@ -529,3 +529,11 @@ cr-menu-item[command='#install-new-extension'] .icon.start {
url(../images/volumes/android_active.png) 1x,
url(../images/volumes/2x/android_active.png) 2x);
}
[file-type-icon='plugin_vm'] {
background-image: url(../images/volumes/plugin_vm.svg);
}
.tree-row[selected] [file-type-icon='plugin_vm'] {
background-image: url(../images/volumes/plugin_vm_active.svg);
}
<svg xmlns="http://www.w3.org/2000/svg" fill="rgb(90,90,90)">
<path d="M7 12v4H4V4a1 1 0 0 1 1-1h8a3 3 0 0 1 3 3v3a3 3 0 0 1-3 3H7zm0-6v3h5a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1H7z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" fill="rgb(51,103,214)">
<path d="M7 12v4H4V4a1 1 0 0 1 1-1h8a3 3 0 0 1 3 3v3a3 3 0 0 1-3 3H7zm0-6v3h5a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1H7z"/>
</svg>
......@@ -272,12 +272,13 @@ CommandUtil.shouldShowMenuItemsForEntry = (volumeManager, entry) => {
};
/**
* If entry is MyFiles/Downloads, we don't allow cut/delete/rename.
* If entry is MyFiles/Downloads or MyFiles/PluginVm, we don't allow
* cut/delete/rename.
* @param {!VolumeManager} volumeManager
* @param {(Entry|FakeEntry)} entry Entry or a fake entry.
* @return {boolean}
*/
CommandUtil.isDownloads = (volumeManager, entry) => {
CommandUtil.isReadOnly = (volumeManager, entry) => {
if (!entry) {
return false;
}
......@@ -295,11 +296,14 @@ CommandUtil.isDownloads = (volumeManager, entry) => {
return false;
}
if (util.isMyFilesVolumeEnabled() &&
volumeInfo.volumeType === VolumeManagerCommon.RootType.DOWNLOADS &&
entry.fullPath === '/Downloads') {
if (volumeInfo.volumeType === VolumeManagerCommon.RootType.DOWNLOADS) {
if (util.isMyFilesVolumeEnabled() && entry.fullPath === '/Downloads') {
return true;
}
if (util.isPluginVmEnabled() && entry.fullPath === '/PluginVm') {
return true;
}
}
return false;
};
......@@ -1031,7 +1035,7 @@ CommandHandler.COMMANDS_['delete'] = (() => {
/**
* Returns True if any entry belongs to a read-only volume or is
* MyFiles>Downloads.
* forced to be read-only like MyFiles>Downloads.
* @param {!Array<!Entry>} entries
* @param {!CommandHandlerDeps} fileManager
* @return {boolean} True if entries contain read only entry.
......@@ -1040,7 +1044,7 @@ CommandHandler.COMMANDS_['delete'] = (() => {
return entries.some(entry => {
const locationInfo = fileManager.volumeManager.getLocationInfo(entry);
return (locationInfo && locationInfo.isReadOnly) ||
CommandUtil.isDownloads(fileManager.volumeManager, entry);
CommandUtil.isReadOnly(fileManager.volumeManager, entry);
});
}
};
......@@ -1195,7 +1199,7 @@ CommandHandler.COMMANDS_['rename'] = /** @type {Command} */ ({
*/
execute: function(event, fileManager) {
const entry = CommandUtil.getCommandEntry(fileManager, event.target);
if (CommandUtil.isDownloads(fileManager.volumeManager, entry)) {
if (CommandUtil.isReadOnly(fileManager.volumeManager, entry)) {
return;
}
if (event.target instanceof DirectoryTree ||
......@@ -1270,7 +1274,7 @@ CommandHandler.COMMANDS_['rename'] = /** @type {Command} */ ({
!CommandUtil.shouldShowMenuItemsForEntry(
fileManager.volumeManager, entries[0]) ||
entries.some(
CommandUtil.isDownloads.bind(null, fileManager.volumeManager))) {
CommandUtil.isReadOnly.bind(null, fileManager.volumeManager))) {
event.canExecute = false;
event.command.setHidden(true);
return;
......
......@@ -1430,7 +1430,7 @@ FileTransferController.prototype.canCutOrCopy_ = function(isMove) {
}
// For MyFiles/Downloads we only allow copy.
if (isMove && this.isDownloads_(entry)) {
if (isMove && this.isCopyOnly_(entry)) {
return false;
}
......@@ -1464,7 +1464,7 @@ FileTransferController.prototype.canCutOrCopy_ = function(isMove) {
// For MyFiles/Downloads we only allow copy.
if (isMove &&
this.selectionHandler_.selection.entries.some(this.isDownloads_, this)) {
this.selectionHandler_.selection.entries.some(this.isCopyOnly_, this)) {
return false;
}
......@@ -1831,11 +1831,12 @@ FileTransferController.prototype.blinkSelection_ = function() {
};
/**
* Returns True if entry is MyFiles>Downloads.
* Returns True if entry is folder which we enforce to be read-only
* or copy-only such as MyFiles>Downloads or MyFiles>PluginVm.
* @param {(!Entry|!FakeEntry)} entry Entry or a fake entry.
* @return {boolean}
*/
FileTransferController.prototype.isDownloads_ = function(entry) {
FileTransferController.prototype.isCopyOnly_ = function(entry) {
if (util.isFakeEntry(entry)) {
return false;
}
......@@ -1845,10 +1846,13 @@ FileTransferController.prototype.isDownloads_ = function(entry) {
return false;
}
if (util.isMyFilesVolumeEnabled() &&
volumeInfo.volumeType === VolumeManagerCommon.RootType.DOWNLOADS &&
entry.fullPath === '/Downloads') {
if (volumeInfo.volumeType === VolumeManagerCommon.RootType.DOWNLOADS) {
if (util.isMyFilesVolumeEnabled() && entry.fullPath === '/Downloads') {
return true;
}
if (util.isPluginVmEnabled() && entry.fullPath === '/PluginVm') {
return true;
}
}
return false;
};
......@@ -43,6 +43,7 @@ js_type_check("closure_compile") {
":crostini_share",
":crostini_tasks",
":menu",
":plugin_vm",
":progress_center",
":uma",
]
......@@ -102,6 +103,13 @@ js_library("menu") {
]
}
js_library("plugin_vm") {
deps = [
"js:test_util",
"//ui/webui/resources/js:webui_resource_test",
]
}
js_library("progress_center") {
deps = [
"js:test_util",
......
......@@ -234,6 +234,15 @@ test.ENTRIES = {
linuxFiles: new test.TestEntryInfo(
test.EntryType.DIRECTORY, '', 'Linux files', '', test.SharedOption.NONE,
'...', 'Linux files', '--', 'Folder'),
pluginVm: new test.TestEntryInfo(
test.EntryType.DIRECTORY, '', 'PluginVm', '', test.SharedOption.NONE,
'Jan 1, 2000, 1:00 AM', 'Plugin VM', '--', 'Folder'),
photosInPluginVm: new test.TestEntryInfo(
test.EntryType.DIRECTORY, '', 'PluginVm/photos', '',
test.SharedOption.NONE, 'Jan 1, 1980, 11:59 PM', 'photos', '--',
'Folder'),
};
/**
......
// Copyright 2019 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.
const pluginVm = {};
pluginVm.testLabelIconContextMenu = async (done) => {
const fileMenu = [
['#cut', false],
['#copy', true],
['#paste-into-folder', false],
['#get-info', true],
['#delete', false],
['#zip-selection', true],
['#share-with-linux', true],
['#manage-plugin-vm-sharing', true],
['#new-folder', true],
];
const fileMenuSubfolder = [
['#cut', true],
['#copy', true],
['#paste-into-folder', false],
['#get-info', true],
['#rename', true],
['#delete', true],
['#zip-selection', true],
['#share-with-linux', true],
['#manage-plugin-vm-sharing', true],
['#new-folder', true],
];
const pluginVmFolder = '#file-list [file-name="PluginVm"]';
const iconFolder =
'#file-list [file-name="PluginVm"] [file-type-icon="plugin_vm"]';
const fileMenuShown = '#file-context-menu:not([hidden])';
const iconDirTree = '#directory-tree [file-type-icon="plugin_vm"]';
const dirTreeMenuShown = '#directory-tree-context-menu:not([hidden])';
const itemsShown = ' cr-menu-item:not([hidden])';
async function menuItems(menuTypeShown) {
await test.waitForElement(menuTypeShown);
const list = document.querySelectorAll(menuTypeShown + itemsShown);
return Array.from(document.querySelectorAll(menuTypeShown + itemsShown))
.map(e => [e.attributes['command'].value, !e.disabled]);
}
// Verify that /PluginVm has label 'Plugin VM'.
await test.setupAndWaitUntilReady([], [], []);
test.addEntries(
[test.ENTRIES.pluginVm, test.ENTRIES.photosInPluginVm], [], []);
assertTrue(test.fakeMouseClick('#refresh-button'), 'click refresh');
await test.waitForFiles(test.TestEntryInfo.getExpectedRows(
[test.ENTRIES.pluginVm, test.ENTRIES.linuxFiles]));
// Register /PluginVm as shared.
const pluginVmEntry =
mockVolumeManager
.getCurrentProfileVolumeInfo(VolumeManagerCommon.VolumeType.DOWNLOADS)
.fileSystem.entries['/PluginVm'];
fileManager.crostini.registerSharedPath('PluginVm', pluginVmEntry);
// Verify folder icon.
await test.waitForElement(iconFolder);
// Verify /PluginVm folder context menu.
assertTrue(test.fakeMouseRightClick(pluginVmFolder));
let items = await menuItems(fileMenuShown);
assertEquals(JSON.stringify(fileMenu), JSON.stringify(items));
// Change to 'PluginVm' directory, photos folder is shown.
assertTrue(test.fakeMouseDoubleClick(pluginVmFolder));
await test.waitForFiles(
test.TestEntryInfo.getExpectedRows([test.ENTRIES.photos]));
// Verify /PluginVm/photos folder context menu.
assertTrue(test.fakeMouseRightClick('#file-list [file-name="photos"]'));
items = await menuItems(fileMenuShown);
assertEquals(JSON.stringify(fileMenuSubfolder), JSON.stringify(items));
done();
};
\ No newline at end of file
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