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() { ...@@ -683,6 +683,8 @@ std::unique_ptr<base::DictionaryValue> GetFileManagerStrings() {
SET_STRING("PASTE_BUTTON_LABEL", IDS_FILE_BROWSER_PASTE_BUTTON_LABEL); SET_STRING("PASTE_BUTTON_LABEL", IDS_FILE_BROWSER_PASTE_BUTTON_LABEL);
SET_STRING("PASTE_INTO_FOLDER_BUTTON_LABEL", SET_STRING("PASTE_INTO_FOLDER_BUTTON_LABEL",
IDS_FILE_BROWSER_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("PREPARING_LABEL", IDS_FILE_BROWSER_PREPARING_LABEL);
SET_STRING("QUICK_VIEW_CLOSE_BUTTON_LABEL", SET_STRING("QUICK_VIEW_CLOSE_BUTTON_LABEL",
IDS_FILE_BROWSER_QUICK_VIEW_CLOSE_BUTTON_LABEL); IDS_FILE_BROWSER_QUICK_VIEW_CLOSE_BUTTON_LABEL);
......
...@@ -87,6 +87,10 @@ IN_PROC_BROWSER_TEST_F(FileManagerUITest, Menu) { ...@@ -87,6 +87,10 @@ IN_PROC_BROWSER_TEST_F(FileManagerUITest, Menu) {
RunTest("menu"); RunTest("menu");
} }
IN_PROC_BROWSER_TEST_F(FileManagerUITest, PluginVm) {
RunTest("pluginVm");
}
IN_PROC_BROWSER_TEST_F(FileManagerUITest, PluginVmShare) { IN_PROC_BROWSER_TEST_F(FileManagerUITest, PluginVmShare) {
RunTest("pluginVmShare"); RunTest("pluginVmShare");
} }
......
...@@ -77,6 +77,9 @@ ...@@ -77,6 +77,9 @@
<message name="IDS_FILE_BROWSER_MEDIA_VIEW_AUDIO_ROOT_LABEL" desc="A label for the 'Audio' root of media views."> <message name="IDS_FILE_BROWSER_MEDIA_VIEW_AUDIO_ROOT_LABEL" desc="A label for the 'Audio' root of media views.">
Audio Audio
</message> </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."> <message name="IDS_FILE_BROWSER_RECENT_ROOT_LABEL" desc="A label for the 'Recent' root which shows files recently modified by the user.">
Recent Recent
</message> </message>
......
...@@ -620,6 +620,7 @@ FileType.getIconOverrides = (entry, opt_rootType) => { ...@@ -620,6 +620,7 @@ FileType.getIconOverrides = (entry, opt_rootType) => {
const overrides = { const overrides = {
[VolumeManagerCommon.RootType.DOWNLOADS]: { [VolumeManagerCommon.RootType.DOWNLOADS]: {
'/Downloads': VolumeManagerCommon.VolumeType.DOWNLOADS, '/Downloads': VolumeManagerCommon.VolumeType.DOWNLOADS,
'/PluginVm': 'plugin_vm',
}, },
}; };
const root = overrides[opt_rootType]; const root = overrides[opt_rootType];
......
...@@ -1151,11 +1151,15 @@ util.getEntryLabel = (locationInfo, entry) => { ...@@ -1151,11 +1151,15 @@ util.getEntryLabel = (locationInfo, entry) => {
return util.getRootTypeLabel(locationInfo); return util.getRootTypeLabel(locationInfo);
} }
// Special case for MyFiles/Downloads. // Special case for MyFiles/Downloads and MyFiles/PluginVm.
if (locationInfo && util.isMyFilesVolumeEnabled() && if (locationInfo &&
locationInfo.rootType == VolumeManagerCommon.RootType.DOWNLOADS && locationInfo.rootType == VolumeManagerCommon.RootType.DOWNLOADS) {
entry.fullPath == '/Downloads') { if (util.isMyFilesVolumeEnabled() && entry.fullPath == '/Downloads') {
return str('DOWNLOADS_DIRECTORY_LABEL'); return str('DOWNLOADS_DIRECTORY_LABEL');
}
if (util.isPluginVmEnabled() && entry.fullPath == '/PluginVm') {
return str('PLUGIN_VM_DIRECTORY_LABEL');
}
} }
return entry.name; return entry.name;
...@@ -1510,6 +1514,12 @@ util.isMyFilesVolumeEnabled = () => { ...@@ -1510,6 +1514,12 @@ util.isMyFilesVolumeEnabled = () => {
loadTimeData.getBoolean('MY_FILES_VOLUME_ENABLED'); 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 * Used for logs and debugging. It tries to tell what type is the entry, its
* path and URL. * path and URL.
......
...@@ -529,3 +529,11 @@ cr-menu-item[command='#install-new-extension'] .icon.start { ...@@ -529,3 +529,11 @@ cr-menu-item[command='#install-new-extension'] .icon.start {
url(../images/volumes/android_active.png) 1x, url(../images/volumes/android_active.png) 1x,
url(../images/volumes/2x/android_active.png) 2x); 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) => { ...@@ -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 {!VolumeManager} volumeManager
* @param {(Entry|FakeEntry)} entry Entry or a fake entry. * @param {(Entry|FakeEntry)} entry Entry or a fake entry.
* @return {boolean} * @return {boolean}
*/ */
CommandUtil.isDownloads = (volumeManager, entry) => { CommandUtil.isReadOnly = (volumeManager, entry) => {
if (!entry) { if (!entry) {
return false; return false;
} }
...@@ -295,10 +296,13 @@ CommandUtil.isDownloads = (volumeManager, entry) => { ...@@ -295,10 +296,13 @@ CommandUtil.isDownloads = (volumeManager, entry) => {
return false; return false;
} }
if (util.isMyFilesVolumeEnabled() && if (volumeInfo.volumeType === VolumeManagerCommon.RootType.DOWNLOADS) {
volumeInfo.volumeType === VolumeManagerCommon.RootType.DOWNLOADS && if (util.isMyFilesVolumeEnabled() && entry.fullPath === '/Downloads') {
entry.fullPath === '/Downloads') { return true;
return true; }
if (util.isPluginVmEnabled() && entry.fullPath === '/PluginVm') {
return true;
}
} }
return false; return false;
}; };
...@@ -1031,7 +1035,7 @@ CommandHandler.COMMANDS_['delete'] = (() => { ...@@ -1031,7 +1035,7 @@ CommandHandler.COMMANDS_['delete'] = (() => {
/** /**
* Returns True if any entry belongs to a read-only volume or is * 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 {!Array<!Entry>} entries
* @param {!CommandHandlerDeps} fileManager * @param {!CommandHandlerDeps} fileManager
* @return {boolean} True if entries contain read only entry. * @return {boolean} True if entries contain read only entry.
...@@ -1040,7 +1044,7 @@ CommandHandler.COMMANDS_['delete'] = (() => { ...@@ -1040,7 +1044,7 @@ CommandHandler.COMMANDS_['delete'] = (() => {
return entries.some(entry => { return entries.some(entry => {
const locationInfo = fileManager.volumeManager.getLocationInfo(entry); const locationInfo = fileManager.volumeManager.getLocationInfo(entry);
return (locationInfo && locationInfo.isReadOnly) || return (locationInfo && locationInfo.isReadOnly) ||
CommandUtil.isDownloads(fileManager.volumeManager, entry); CommandUtil.isReadOnly(fileManager.volumeManager, entry);
}); });
} }
}; };
...@@ -1195,7 +1199,7 @@ CommandHandler.COMMANDS_['rename'] = /** @type {Command} */ ({ ...@@ -1195,7 +1199,7 @@ CommandHandler.COMMANDS_['rename'] = /** @type {Command} */ ({
*/ */
execute: function(event, fileManager) { execute: function(event, fileManager) {
const entry = CommandUtil.getCommandEntry(fileManager, event.target); const entry = CommandUtil.getCommandEntry(fileManager, event.target);
if (CommandUtil.isDownloads(fileManager.volumeManager, entry)) { if (CommandUtil.isReadOnly(fileManager.volumeManager, entry)) {
return; return;
} }
if (event.target instanceof DirectoryTree || if (event.target instanceof DirectoryTree ||
...@@ -1270,7 +1274,7 @@ CommandHandler.COMMANDS_['rename'] = /** @type {Command} */ ({ ...@@ -1270,7 +1274,7 @@ CommandHandler.COMMANDS_['rename'] = /** @type {Command} */ ({
!CommandUtil.shouldShowMenuItemsForEntry( !CommandUtil.shouldShowMenuItemsForEntry(
fileManager.volumeManager, entries[0]) || fileManager.volumeManager, entries[0]) ||
entries.some( entries.some(
CommandUtil.isDownloads.bind(null, fileManager.volumeManager))) { CommandUtil.isReadOnly.bind(null, fileManager.volumeManager))) {
event.canExecute = false; event.canExecute = false;
event.command.setHidden(true); event.command.setHidden(true);
return; return;
......
...@@ -1430,7 +1430,7 @@ FileTransferController.prototype.canCutOrCopy_ = function(isMove) { ...@@ -1430,7 +1430,7 @@ FileTransferController.prototype.canCutOrCopy_ = function(isMove) {
} }
// For MyFiles/Downloads we only allow copy. // For MyFiles/Downloads we only allow copy.
if (isMove && this.isDownloads_(entry)) { if (isMove && this.isCopyOnly_(entry)) {
return false; return false;
} }
...@@ -1464,7 +1464,7 @@ FileTransferController.prototype.canCutOrCopy_ = function(isMove) { ...@@ -1464,7 +1464,7 @@ FileTransferController.prototype.canCutOrCopy_ = function(isMove) {
// For MyFiles/Downloads we only allow copy. // For MyFiles/Downloads we only allow copy.
if (isMove && if (isMove &&
this.selectionHandler_.selection.entries.some(this.isDownloads_, this)) { this.selectionHandler_.selection.entries.some(this.isCopyOnly_, this)) {
return false; return false;
} }
...@@ -1831,11 +1831,12 @@ FileTransferController.prototype.blinkSelection_ = function() { ...@@ -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. * @param {(!Entry|!FakeEntry)} entry Entry or a fake entry.
* @return {boolean} * @return {boolean}
*/ */
FileTransferController.prototype.isDownloads_ = function(entry) { FileTransferController.prototype.isCopyOnly_ = function(entry) {
if (util.isFakeEntry(entry)) { if (util.isFakeEntry(entry)) {
return false; return false;
} }
...@@ -1845,10 +1846,13 @@ FileTransferController.prototype.isDownloads_ = function(entry) { ...@@ -1845,10 +1846,13 @@ FileTransferController.prototype.isDownloads_ = function(entry) {
return false; return false;
} }
if (util.isMyFilesVolumeEnabled() && if (volumeInfo.volumeType === VolumeManagerCommon.RootType.DOWNLOADS) {
volumeInfo.volumeType === VolumeManagerCommon.RootType.DOWNLOADS && if (util.isMyFilesVolumeEnabled() && entry.fullPath === '/Downloads') {
entry.fullPath === '/Downloads') { return true;
return true; }
if (util.isPluginVmEnabled() && entry.fullPath === '/PluginVm') {
return true;
}
} }
return false; return false;
}; };
...@@ -43,6 +43,7 @@ js_type_check("closure_compile") { ...@@ -43,6 +43,7 @@ js_type_check("closure_compile") {
":crostini_share", ":crostini_share",
":crostini_tasks", ":crostini_tasks",
":menu", ":menu",
":plugin_vm",
":progress_center", ":progress_center",
":uma", ":uma",
] ]
...@@ -102,6 +103,13 @@ js_library("menu") { ...@@ -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") { js_library("progress_center") {
deps = [ deps = [
"js:test_util", "js:test_util",
......
...@@ -26,4 +26,4 @@ loadTimeData.overrideValues({ ...@@ -26,4 +26,4 @@ loadTimeData.overrideValues({
// Overwrite LoadTimeData.prototype.data setter as nop. // Overwrite LoadTimeData.prototype.data setter as nop.
// Default implementation throws errors when both background and // Default implementation throws errors when both background and
// foreground re-set loadTimeData.data. // foreground re-set loadTimeData.data.
Object.defineProperty(LoadTimeData.prototype, 'data', {set: () => {}}); Object.defineProperty(LoadTimeData.prototype, 'data', {set: () => {}});
\ No newline at end of file
...@@ -234,6 +234,15 @@ test.ENTRIES = { ...@@ -234,6 +234,15 @@ test.ENTRIES = {
linuxFiles: new test.TestEntryInfo( linuxFiles: new test.TestEntryInfo(
test.EntryType.DIRECTORY, '', 'Linux files', '', test.SharedOption.NONE, test.EntryType.DIRECTORY, '', 'Linux files', '', test.SharedOption.NONE,
'...', 'Linux files', '--', 'Folder'), '...', '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