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,8 +205,7 @@ WRAPPED_INSTANTIATE_TEST_CASE_P(
WRAPPED_INSTANTIATE_TEST_CASE_P(
ContextMenu, /* context_menu.js */
FilesAppBrowserTest,
::testing::Values(
TestCase("checkDeleteEnabledForReadWriteFile"),
::testing::Values(TestCase("checkDeleteEnabledForReadWriteFile"),
TestCase("checkDeleteDisabledForReadOnlyDocument"),
TestCase("checkDeleteDisabledForReadOnlyFile"),
TestCase("checkDeleteDisabledForReadOnlyFolder"),
......@@ -224,7 +223,8 @@ WRAPPED_INSTANTIATE_TEST_CASE_P(
TestCase("checkCutDisabledForReadOnlyFile"),
TestCase("checkCutDisabledForReadOnlyFolder"),
TestCase("checkPasteIntoFolderEnabledForReadWriteFolder"),
TestCase("checkPasteIntoFolderDisabledForReadOnlyFolder")));
TestCase("checkPasteIntoFolderDisabledForReadOnlyFolder"),
TestCase("checkContextMenusForInputElements")));
WRAPPED_INSTANTIATE_TEST_CASE_P(
Delete, /* delete.js */
......
......@@ -418,6 +418,35 @@ test.util.sync.fakeMouseRightClick = function(contentWindow, targetQuery) {
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
* |targetQuery|.
......
......@@ -705,22 +705,13 @@ FileManager.prototype = /** @struct */ {
for (var j = 0; j < commandButtons.length; j++)
CommandButton.decorate(commandButtons[j]);
var inputs = this.dialogDom_.querySelectorAll(
'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]);
}
var inputs = this.getDomInputs_();
cr.ui.contextMenuHandler.setContextMenu(this.ui_.listContainer.renameInput,
this.ui_.textContextMenu);
this.registerInputCommands_(this.ui_.listContainer.renameInput);
for (let input of inputs)
this.setContextMenuForInput_(input);
cr.ui.contextMenuHandler.setContextMenu(
this.directoryTreeNamingController_.getInputElement(),
this.ui_.textContextMenu);
this.registerInputCommands_(
this.setContextMenuForInput_(this.ui_.listContainer.renameInput);
this.setContextMenuForInput_(
this.directoryTreeNamingController_.getInputElement());
this.document_.addEventListener(
......@@ -728,6 +719,40 @@ FileManager.prototype = /** @struct */ {
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.
*
......
......@@ -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 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