Commit 97148818 authored by Joel Einbinder's avatar Joel Einbinder Committed by Commit Bot

DevTools: Prevent browser behavior of shortcuts in extension panels

This patch calls preventDefault on all events that we forward from
extension panels into devtools. This would cancel too many events,
so a list of devtools global keyboard shortcuts are passed into the
extension.

Bug: 682068
Change-Id: Ide557dafed759e20dfc6698d8cdc33f932acbe83
Reviewed-on: https://chromium-review.googlesource.com/1159467Reviewed-by: default avatarAndrey Lushnikov <lushnikov@chromium.org>
Commit-Queue: Joel Einbinder <einbinder@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580011}
parent db24c026
...@@ -294,7 +294,7 @@ ...@@ -294,7 +294,7 @@
testPanel.onShown.removeListener(onPanelShown); testPanel.onShown.removeListener(onPanelShown);
output("Panel shown, now toggling console..."); output("Panel shown, now toggling console...");
panelWindow.addEventListener("resize", onPanelResized); panelWindow.addEventListener("resize", onPanelResized);
dispatchKeydownEvent({ key: "Escape" }); dispatchKeydownEvent({ key: "Escape", keyCode: 27 });
} }
function onPanelResized() { function onPanelResized() {
panelWindow.removeEventListener("resize", onPanelResized); panelWindow.removeEventListener("resize", onPanelResized);
......
...@@ -89,11 +89,13 @@ function defineCommonExtensionSymbols(apiPrivate) { ...@@ -89,11 +89,13 @@ function defineCommonExtensionSymbols(apiPrivate) {
* @param {!ExtensionDescriptor} extensionInfo * @param {!ExtensionDescriptor} extensionInfo
* @param {string} inspectedTabId * @param {string} inspectedTabId
* @param {string} themeName * @param {string} themeName
* @param {!Array<number>} keysToForward
* @param {number} injectedScriptId * @param {number} injectedScriptId
* @param {function(!Object, !Object)} testHook * @param {function(!Object, !Object)} testHook
* @suppressGlobalPropertiesCheck * @suppressGlobalPropertiesCheck
*/ */
function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, testHook, injectedScriptId) { function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, keysToForward, testHook, injectedScriptId) {
const keysToForwardSet = new Set(keysToForward);
const chrome = window.chrome || {}; const chrome = window.chrome || {};
const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools'); const devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, 'devtools');
if (devtools_descriptor) if (devtools_descriptor)
...@@ -637,14 +639,26 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, testHook ...@@ -637,14 +639,26 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, testHook
let forwardTimer = null; let forwardTimer = null;
function forwardKeyboardEvent(event) { function forwardKeyboardEvent(event) {
let modifiers = 0;
if (event.shiftKey)
modifiers |= 1;
if (event.ctrlKey)
modifiers |= 2;
if (event.altKey)
modifiers |= 4;
if (event.metaKey)
modifiers |= 8;
const num = (event.keyCode & 255) | (modifiers << 8);
// We only care about global hotkeys, not about random text // We only care about global hotkeys, not about random text
if (!event.ctrlKey && !event.altKey && !event.metaKey && !/^F\d+$/.test(event.key) && event.key !== 'Escape') if (!keysToForwardSet.has(num))
return; return;
event.preventDefault();
const requestPayload = { const requestPayload = {
eventType: event.type, eventType: event.type,
ctrlKey: event.ctrlKey, ctrlKey: event.ctrlKey,
altKey: event.altKey, altKey: event.altKey,
metaKey: event.metaKey, metaKey: event.metaKey,
shiftKey: event.shiftKey,
keyIdentifier: event.keyIdentifier, keyIdentifier: event.keyIdentifier,
key: event.key, key: event.key,
code: event.code, code: event.code,
...@@ -795,11 +809,12 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, testHook ...@@ -795,11 +809,12 @@ function injectedExtensionAPI(extensionInfo, inspectedTabId, themeName, testHook
* @param {!ExtensionDescriptor} extensionInfo * @param {!ExtensionDescriptor} extensionInfo
* @param {string} inspectedTabId * @param {string} inspectedTabId
* @param {string} themeName * @param {string} themeName
* @param {!Array<number>} keysToForward
* @param {function(!Object, !Object)|undefined} testHook * @param {function(!Object, !Object)|undefined} testHook
* @return {string} * @return {string}
*/ */
function buildExtensionAPIInjectedScript(extensionInfo, inspectedTabId, themeName, testHook) { function buildExtensionAPIInjectedScript(extensionInfo, inspectedTabId, themeName, keysToForward, testHook) {
const argumentsJSON = [extensionInfo, inspectedTabId || null, themeName].map(_ => JSON.stringify(_)).join(','); const argumentsJSON = [extensionInfo, inspectedTabId || null, themeName, keysToForward].map(_ => JSON.stringify(_)).join(',');
if (!testHook) if (!testHook)
testHook = () => {}; testHook = () => {};
return '(function(injectedScriptId){ ' + defineCommonExtensionSymbols.toString() + ';' + return '(function(injectedScriptId){ ' + defineCommonExtensionSymbols.toString() + ';' +
......
...@@ -560,8 +560,6 @@ Extensions.ExtensionServer = class extends Common.Object { ...@@ -560,8 +560,6 @@ Extensions.ExtensionServer = class extends Common.Object {
* @suppressGlobalPropertiesCheck * @suppressGlobalPropertiesCheck
*/ */
function handleEventEntry(entry) { function handleEventEntry(entry) {
if (!entry.ctrlKey && !entry.altKey && !entry.metaKey && !/^F\d+$/.test(entry.key) && entry.key !== 'Escape')
return;
// Fool around closure compiler -- it has its own notion of both KeyboardEvent constructor // Fool around closure compiler -- it has its own notion of both KeyboardEvent constructor
// and initKeyboardEvent methods and overriding these in externs.js does not have effect. // and initKeyboardEvent methods and overriding these in externs.js does not have effect.
const event = new window.KeyboardEvent(entry.eventType, { const event = new window.KeyboardEvent(entry.eventType, {
...@@ -703,6 +701,7 @@ Extensions.ExtensionServer = class extends Common.Object { ...@@ -703,6 +701,7 @@ Extensions.ExtensionServer = class extends Common.Object {
// See ExtensionAPI.js for details. // See ExtensionAPI.js for details.
const injectedAPI = buildExtensionAPIInjectedScript( const injectedAPI = buildExtensionAPIInjectedScript(
extensionInfo, this._inspectedTabId, UI.themeSupport.themeName(), extensionInfo, this._inspectedTabId, UI.themeSupport.themeName(),
UI.shortcutRegistry.globalShortcutKeys(),
Extensions.extensionServer['_extensionAPITestHook']); Extensions.extensionServer['_extensionAPITestHook']);
InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, injectedAPI); InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, injectedAPI);
this._registeredExtensions[extensionOrigin] = {name: name}; this._registeredExtensions[extensionOrigin] = {name: name};
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
"type": "action", "type": "action",
"category": "Drawer", "category": "Drawer",
"actionId": "main.toggle-drawer", "actionId": "main.toggle-drawer",
"className": "UI.InspectorView.DrawerToggleActionDelegate", "className": "UI.InspectorView.ActionDelegate",
"order": 101, "order": 101,
"title": "Toggle drawer", "title": "Toggle drawer",
"bindings": [ "bindings": [
...@@ -49,6 +49,36 @@ ...@@ -49,6 +49,36 @@
} }
] ]
}, },
{
"type": "action",
"actionId": "main.next-tab",
"className": "UI.InspectorView.ActionDelegate",
"bindings": [
{
"platform": "windows,linux",
"shortcut": "Ctrl+]"
},
{
"platform": "mac",
"shortcut": "Meta+]"
}
]
},
{
"type": "action",
"actionId": "main.previous-tab",
"className": "UI.InspectorView.ActionDelegate",
"bindings": [
{
"platform": "windows,linux",
"shortcut": "Ctrl+["
},
{
"platform": "mac",
"shortcut": "Meta+["
}
]
},
{ {
"type": "action", "type": "action",
"actionId": "main.debug-reload", "actionId": "main.debug-reload",
......
...@@ -284,16 +284,6 @@ UI.InspectorView = class extends UI.VBox { ...@@ -284,16 +284,6 @@ UI.InspectorView = class extends UI.VBox {
} }
} }
} }
if (event.key === '[') {
this._tabbedPane.selectPrevTab();
event.consume(true);
}
if (event.key === ']') {
this._tabbedPane.selectNextTab();
event.consume(true);
}
} }
/** /**
...@@ -358,7 +348,7 @@ UI.inspectorView; ...@@ -358,7 +348,7 @@ UI.inspectorView;
* @implements {UI.ActionDelegate} * @implements {UI.ActionDelegate}
* @unrestricted * @unrestricted
*/ */
UI.InspectorView.DrawerToggleActionDelegate = class { UI.InspectorView.ActionDelegate = class {
/** /**
* @override * @override
* @param {!UI.Context} context * @param {!UI.Context} context
...@@ -366,10 +356,20 @@ UI.InspectorView.DrawerToggleActionDelegate = class { ...@@ -366,10 +356,20 @@ UI.InspectorView.DrawerToggleActionDelegate = class {
* @return {boolean} * @return {boolean}
*/ */
handleAction(context, actionId) { handleAction(context, actionId) {
switch (actionId) {
case 'main.toggle-drawer':
if (UI.inspectorView.drawerVisible()) if (UI.inspectorView.drawerVisible())
UI.inspectorView._closeDrawer(); UI.inspectorView._closeDrawer();
else else
UI.inspectorView._showDrawer(true); UI.inspectorView._showDrawer(true);
return true; return true;
case 'main.next-tab':
UI.inspectorView._tabbedPane.selectNextTab();
return true;
case 'main.previous-tab':
UI.inspectorView._tabbedPane.selectPrevTab();
return true;
}
return false;
} }
}; };
...@@ -34,6 +34,20 @@ UI.ShortcutRegistry = class { ...@@ -34,6 +34,20 @@ UI.ShortcutRegistry = class {
return this._defaultKeyToActions.get(String(key)); return this._defaultKeyToActions.get(String(key));
} }
/**
* @return {!Array<number>}
*/
globalShortcutKeys() {
const keys = [];
for (const key of this._defaultKeyToActions.keysArray()) {
const actions = this._defaultKeyToActions.get(key).valuesArray();
const applicableActions = this._actionRegistry.applicableActions(actions, new UI.Context());
if (applicableActions.length)
keys.push(Number(key));
}
return keys;
}
/** /**
* @param {string} actionId * @param {string} actionId
* @return {!Array.<!UI.KeyboardShortcut.Descriptor>} * @return {!Array.<!UI.KeyboardShortcut.Descriptor>}
......
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