Commit b0178447 authored by Alexey Baskakov's avatar Alexey Baskakov Committed by Commit Bot

cros FilesApp: Disable context menus for input elements on touch events.

Use touchstart as a criterion to stop contextmenu propagation.

Bug: 812056
Cq-Include-Trybots: luci.chromium.try:closure_compilation
Change-Id: I2d6272b08c0f1ad8229fe340825607e8ef6df007
Reviewed-on: https://chromium-review.googlesource.com/1109668
Commit-Queue: Alexey Baskakov <loyso@chromium.org>
Reviewed-by: default avatarNoel Gordon <noel@chromium.org>
Reviewed-by: default avatarcalamity <calamity@chromium.org>
Cr-Commit-Position: refs/heads/master@{#570347}
parent 122d2818
...@@ -205,26 +205,26 @@ WRAPPED_INSTANTIATE_TEST_CASE_P( ...@@ -205,26 +205,26 @@ WRAPPED_INSTANTIATE_TEST_CASE_P(
WRAPPED_INSTANTIATE_TEST_CASE_P( WRAPPED_INSTANTIATE_TEST_CASE_P(
ContextMenu, /* context_menu.js */ ContextMenu, /* context_menu.js */
FilesAppBrowserTest, FilesAppBrowserTest,
::testing::Values( ::testing::Values(TestCase("checkDeleteEnabledForReadWriteFile"),
TestCase("checkDeleteEnabledForReadWriteFile"), TestCase("checkDeleteDisabledForReadOnlyDocument"),
TestCase("checkDeleteDisabledForReadOnlyDocument"), TestCase("checkDeleteDisabledForReadOnlyFile"),
TestCase("checkDeleteDisabledForReadOnlyFile"), TestCase("checkDeleteDisabledForReadOnlyFolder"),
TestCase("checkDeleteDisabledForReadOnlyFolder"), TestCase("checkRenameEnabledForReadWriteFile"),
TestCase("checkRenameEnabledForReadWriteFile"), TestCase("checkRenameDisabledForReadOnlyDocument"),
TestCase("checkRenameDisabledForReadOnlyDocument"), TestCase("checkRenameDisabledForReadOnlyFile"),
TestCase("checkRenameDisabledForReadOnlyFile"), TestCase("checkRenameDisabledForReadOnlyFolder"),
TestCase("checkRenameDisabledForReadOnlyFolder"), TestCase("checkCopyEnabledForReadWriteFile"),
TestCase("checkCopyEnabledForReadWriteFile"), TestCase("checkCopyEnabledForReadOnlyDocument"),
TestCase("checkCopyEnabledForReadOnlyDocument"), TestCase("checkCopyDisabledForStrictReadOnlyDocument"),
TestCase("checkCopyDisabledForStrictReadOnlyDocument"), TestCase("checkCopyEnabledForReadOnlyFile"),
TestCase("checkCopyEnabledForReadOnlyFile"), TestCase("checkCopyEnabledForReadOnlyFolder"),
TestCase("checkCopyEnabledForReadOnlyFolder"), TestCase("checkCutEnabledForReadWriteFile"),
TestCase("checkCutEnabledForReadWriteFile"), TestCase("checkCutDisabledForReadOnlyDocument"),
TestCase("checkCutDisabledForReadOnlyDocument"), TestCase("checkCutDisabledForReadOnlyFile"),
TestCase("checkCutDisabledForReadOnlyFile"), TestCase("checkCutDisabledForReadOnlyFolder"),
TestCase("checkCutDisabledForReadOnlyFolder"), TestCase("checkPasteIntoFolderEnabledForReadWriteFolder"),
TestCase("checkPasteIntoFolderEnabledForReadWriteFolder"), TestCase("checkPasteIntoFolderDisabledForReadOnlyFolder"),
TestCase("checkPasteIntoFolderDisabledForReadOnlyFolder"))); TestCase("checkContextMenusForInputElements")));
WRAPPED_INSTANTIATE_TEST_CASE_P( WRAPPED_INSTANTIATE_TEST_CASE_P(
Delete, /* delete.js */ Delete, /* delete.js */
......
...@@ -418,6 +418,35 @@ test.util.sync.fakeMouseRightClick = function(contentWindow, targetQuery) { ...@@ -418,6 +418,35 @@ test.util.sync.fakeMouseRightClick = function(contentWindow, targetQuery) {
return test.util.sync.sendEvent(contentWindow, targetQuery, contextMenuEvent); return test.util.sync.sendEvent(contentWindow, targetQuery, contextMenuEvent);
}; };
/**
* Simulates a fake touch event (touch start, touch end) on the element
* specified by |targetQuery|.
*
* @param {Window} contentWindow Window to be tested.
* @param {string} targetQuery Query to specify the element.
* @return {boolean} True if the event is sent to the target, false
* otherwise.
*/
test.util.sync.fakeTouchClick = function(contentWindow, targetQuery) {
var touchStartEvent = new TouchEvent('touchstart');
if (!test.util.sync.sendEvent(contentWindow, targetQuery, touchStartEvent)) {
return false;
}
var mouseDownEvent = new MouseEvent('mousedown', {bubbles: true, button: 2});
if (!test.util.sync.sendEvent(contentWindow, targetQuery, mouseDownEvent)) {
return false;
}
var touchEndEvent = new TouchEvent('touchend');
if (!test.util.sync.sendEvent(contentWindow, targetQuery, touchEndEvent)) {
return false;
}
var contextMenuEvent = new MouseEvent('contextmenu', {bubbles: true});
return test.util.sync.sendEvent(contentWindow, targetQuery, contextMenuEvent);
};
/** /**
* Simulates a fake double click event (left button) to the element specified by * Simulates a fake double click event (left button) to the element specified by
* |targetQuery|. * |targetQuery|.
......
...@@ -705,22 +705,13 @@ FileManager.prototype = /** @struct */ { ...@@ -705,22 +705,13 @@ FileManager.prototype = /** @struct */ {
for (var j = 0; j < commandButtons.length; j++) for (var j = 0; j < commandButtons.length; j++)
CommandButton.decorate(commandButtons[j]); CommandButton.decorate(commandButtons[j]);
var inputs = this.dialogDom_.querySelectorAll( var inputs = this.getDomInputs_();
'input[type=text], input[type=search], textarea');
for (var i = 0; i < inputs.length; i++) {
cr.ui.contextMenuHandler.setContextMenu(
inputs[i], this.ui_.textContextMenu);
this.registerInputCommands_(inputs[i]);
}
cr.ui.contextMenuHandler.setContextMenu(this.ui_.listContainer.renameInput, for (let input of inputs)
this.ui_.textContextMenu); this.setContextMenuForInput_(input);
this.registerInputCommands_(this.ui_.listContainer.renameInput);
cr.ui.contextMenuHandler.setContextMenu( this.setContextMenuForInput_(this.ui_.listContainer.renameInput);
this.directoryTreeNamingController_.getInputElement(), this.setContextMenuForInput_(
this.ui_.textContextMenu);
this.registerInputCommands_(
this.directoryTreeNamingController_.getInputElement()); this.directoryTreeNamingController_.getInputElement());
this.document_.addEventListener( this.document_.addEventListener(
...@@ -728,6 +719,40 @@ FileManager.prototype = /** @struct */ { ...@@ -728,6 +719,40 @@ FileManager.prototype = /** @struct */ {
this.ui_.listContainer.clearHover.bind(this.ui_.listContainer)); this.ui_.listContainer.clearHover.bind(this.ui_.listContainer));
}; };
/**
* Get input elements from root DOM element of this app.
* @private
*/
FileManager.prototype.getDomInputs_ = function() {
return this.dialogDom_.querySelectorAll(
'input[type=text], input[type=search], textarea');
};
/**
* Set context menu and handlers for an input element.
* @private
*/
FileManager.prototype.setContextMenuForInput_ = function(input) {
var touchInduced = false;
// stop contextmenu propagation for touch-induced events.
input.addEventListener('touchstart', (e) => {
touchInduced = true;
});
input.addEventListener('contextmenu', (e) => {
if (touchInduced) {
e.stopImmediatePropagation();
}
touchInduced = false;
});
input.addEventListener('click', (e) => {
touchInduced = false;
});
cr.ui.contextMenuHandler.setContextMenu(input, this.ui_.textContextMenu);
this.registerInputCommands_(input);
};
/** /**
* Registers cut, copy, paste and delete commands on input element. * Registers cut, copy, paste and delete commands on input element.
* *
......
...@@ -285,6 +285,74 @@ testcase.checkPasteIntoFolderDisabledForReadOnlyFolder = function() { ...@@ -285,6 +285,74 @@ testcase.checkPasteIntoFolderDisabledForReadOnlyFolder = function() {
}); });
}; };
/**
* Tests that text selection context menus are disabled in tablet mode.
*/
testcase.checkContextMenusForInputElements = function() {
let appId;
StepsRunner.run([
// Start FilesApp.
function() {
setupAndWaitUntilReady(null, RootPath.DOWNLOADS).then(this.next);
},
// Query all input elements.
function(results) {
appId = results.windowId;
remoteCall.callRemoteTestUtil(
'queryAllElements', appId,
['input[type=text], input[type=search], textarea'], this.next);
},
// Focus the search box.
function(elements) {
chrome.test.assertEq(2, elements.length);
for (let element of elements) {
chrome.test.assertEq(
'#text-context-menu', element.attributes.contextmenu);
}
remoteCall.callRemoteTestUtil(
'fakeEvent', appId, ['#search-box input', 'focus'], this.next);
},
// Input a text.
function(result) {
chrome.test.assertTrue(result);
remoteCall.callRemoteTestUtil(
'inputText', appId, ['#search-box input', 'test.pdf'], this.next);
},
// Notify the element of the input.
function() {
remoteCall.callRemoteTestUtil(
'fakeEvent', appId, ['#search-box input', 'input'], this.next);
},
// Do the touch.
function(result) {
chrome.test.assertTrue(result);
remoteCall.callRemoteTestUtil(
'fakeTouchClick', appId, ['#search-box input'], this.next);
},
// Context menu must be hidden if touch induced.
function(result) {
chrome.test.assertTrue(result);
remoteCall.waitForElement(appId, '#text-context-menu[hidden]')
.then(this.next);
},
// Do the right click.
function() {
remoteCall.callRemoteTestUtil(
'fakeMouseRightClick', appId, ['#search-box input'], this.next);
},
// Context menu must be visible if mouse induced.
function(result) {
chrome.test.assertTrue(result);
remoteCall.waitForElement(appId, '#text-context-menu:not([hidden])')
.then(this.next);
},
function() {
checkIfNoErrorsOccured(this.next);
},
]);
};
/** TODO(sashab): Add tests for copying to/from the directory tree on the LHS. /** TODO(sashab): Add tests for copying to/from the directory tree on the LHS.
*/ */
/** TODO(sashab): Add tests for pasting into the current directory. */ /** TODO(sashab): Add tests for pasting into the current directory. */
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