Как инициализировать событие клавиатуры с заданным char / keycode в расширении Chrome?

Я разрабатываю расширение Google Chrome, которое имитирует события клавиатуры на веб-странице.

Я обнаружил, что event.initKeyboardEvent() не работает должным образом из-за этой ошибки webkit, и я также нашел некоторые обходные пути, например SO-вопрос

Однако определение свойств объекта события не работает, потому что сценарий содержимого расширения имеет свой собственный «параллельный мир», поэтому свойства, определенные в сценарии содержимого, не видны сценарию веб-страницы.

Моя единственная и последняя надежда, что конструкторы событий DOM 4 работают в Google Chrome и можно будет правильно инициализировать событие клавиатуры через конструктор.

var event = new KeyboardEvent("keypress", {key: 'U+0041', char: 'a', ... })

К сожалению, это не удается:

TypeError: illegal constructor  

Мне не удалось найти документацию по поддерживаемым конструкторам событий в Chrome. Может ли кто-нибудь указать мне на какие-то документы / исходный код?

Есть ли другой способ имитировать события клавиатуры в расширении Google Chrome?

(обратите внимание, TextEvent не поможет, потому что многие реальные элементы управления специально слушают _4 _ / _ 5_)


person disya2    schedule 21.12.2012    source источник


Ответы (3)


Если у кого-то есть проблема, с которой я столкнулся, с запуском клавиатуры с определенным кодом клавиши. Это один способ.

Во-первых, я безуспешно попытался ответить @RobW выше. Код ключа не передается, всегда не определен.

Затем я просмотрел ответ @ disya2, который действительно сработал.

Итак, вот код: -

Манифест

"permissions": [
    "debugger"
  ],

ContentScript.js

chrome.runtime.sendMessage({ pressEnter: true });

Background.js

chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
    if(message.pressEnter){
        chrome.tabs.query({active: true}, function(tabs) {
            chrome.debugger.attach({ tabId: tabs[0].id }, "1.0");
            chrome.debugger.sendCommand({ tabId: tabs[0].id }, 'Input.dispatchKeyEvent', { type: 'keyUp', windowsVirtualKeyCode:13, nativeVirtualKeyCode : 13, macCharCode: 13  });
            chrome.debugger.sendCommand({ tabId: tabs[0].id }, 'Input.dispatchKeyEvent', { type: 'keyDown', windowsVirtualKeyCode:13, nativeVirtualKeyCode : 13, macCharCode: 13  });
            chrome.debugger.detach({ tabId: tabs[0].id });
        });
    }
});
person BenG    schedule 11.01.2016
comment
Это отлично работает, и для тех, кто хочет нажать ввод, как показано, а затем выбрать клавишу возврата (код 8) после ввода, это отлично работает! - person Rob; 20.06.2019
comment
Почему вы, кажется, отправляете keyUp, а затем keyDown? И не могли бы вы подтвердить, что это все еще работает ... (Chrome 80+)? - person manuell; 22.05.2020

Поскольку Chrome не сохраняет настраиваемые свойства, когда вы инициируете событие из сценария содержимого на странице (и наоборот), внедрите сценарий на страницу, чтобы выполнить это задание. Вот базовый пример, демонстрирующий идею. Его можно использовать, хотя свойства key и keyCode обрабатываются некорректно (их все равно использовать не следует).

// Example: Say, you've got a reference to a DOM element...    
var elem = document.body;
// And you want to "type" "A"
var charCode = 65;

// Now, you want to generate a key event...
triggerKeyEvent(elem, charCode);

// triggerKeyEvent is implemented as follows:
function triggerKeyEvent(element, charCode) {
    // We cannot pass object references, so generate an unique selector
    var attribute = 'robw_' + Date.now();
    element.setAttribute(attribute, '');
    var selector = element.tagName + '[' + attribute + ']';

    var s = document.createElement('script');
    s.textContent = '(' + function(charCode, attribute, selector) {
        // Get reference to element...
        var element = document.querySelector(selector);
        element.removeAttribute(attribute);

        // Create KeyboardEvent instance
        var event = document.createEvent('KeyboardEvents');
        event.initKeyboardEvent(
            /* type         */ 'keypress',
            /* bubbles      */ true,
            /* cancelable   */ false,
            /* view         */ window,
            /* keyIdentifier*/ '',
            /* keyLocation  */ 0,
            /* ctrlKey      */ false,
            /* altKey       */ false,
            /* shiftKey     */ false,
            /* metaKey      */ false,
            /* altGraphKey  */ false
        );
        // Define custom values
        // This part requires the script to be run in the page's context
        var getterCode = {get: function() {return charCode}};
        var getterChar = {get: function() {return String.fromCharCode(charCode)}};
        Object.defineProperties(event, {
            charCode: getterCode,
            which: getterCode,
            keyCode: getterCode, // Not fully correct
            key: getterChar,     // Not fully correct
            char: getterChar
        });

        element.dispatchEvent(event);
    } + ')(' + charCode + ', "' + attribute + '", "' + selector + '")';
    (document.head||document.documentElement).appendChild(s);
    s.parentNode.removeChild(s);
    // The script should have removed the attribute already.
    // Remove the attribute in case the script fails to run.
    s.removeAttribute(attribute);
}

Это простой пример, который запускает событие keypress для символа «A». Если вы хотите инициировать более релевантные ключевые события, не используйте triggerKeyEvent три раза (потому что это имеет небольшие накладные расходы). Вместо этого измените функцию triggerKeyEvent так, чтобы она запускала все события (keydown, keypress, keyup и / или input) с правильными параметрами.

Если вам нужно изменить altKey, shiftKey и т. Д., Просто измените функцию.
Итог: приведенный мной пример очень прост и может быть изменен в соответствии с вашими потребностями.

Читать далее

Если вы хотите изменить реализацию в соответствии со спецификацией, прочтите эти источники:

Если вы хотите узнать больше о концепции внедрения сценария в сценарий содержимого, см.:

person Rob W    schedule 22.12.2012
comment
Что ж ... У меня кое-что работает, например Теперь возможно перемещение слайдера JQuery с помощью клавиш со стрелками. Однако элементы управления вводом текста, похоже, не реагируют на нажатие клавиши (т.е. символ не вводится), и единственное событие нажатия клавиши, которое делает то, что ожидалось, - это Tab. Отправка события возврата в любой элемент управления вводом запускает переход браузера назад; Home, End и т. Д. Просто не работают. Я считаю, что это как-то связано с тем фактом, что событиям не доверяют, хотя я не вижу свойства .isTrusted, которое указывало бы на это (как в Firefox). - person disya2; 25.12.2012
comment
классно!! Спасибо!! Я сделал некоторые улучшения, чтобы исправить which и передать событие - person unobf; 09.01.2017

Я обнаружил, что протокол отладчика Chrome v1.1 - это однозначный ответ на имитацию событий клавиш и мыши из расширения Google Chrome. Часть протокола доступна через chrome.debugger API.

person disya2    schedule 22.12.2015
comment
Хотите добавить пример? Или, по крайней мере, ссылку на соответствующие документы протокола отладчика? - person Xan; 22.12.2015
comment
Соответствующие команды протокола можно найти здесь. chrome.debugger.sendCommand() - это как отправить. - person disya2; 23.12.2015
comment
Эти документы теперь находятся здесь. Протокол инструментов разработчика задокументирован здесь. Похоже, что Input.dispatchKeyEvent может быть тем, что вы использовали бы для отправки ключевого события на вкладку с помощью sendCommand(), но я еще не пробовал. - person jdunning; 19.09.2017