Предисловие
В каждом объявлении о выходе нового релиза Selenium я рассказываю о том, в каких версиях браузера Firefox будут работать нативные события. Как правило это две последние версии браузера, а также две последние ESR-версии. Увы, недавно случилась неприятность. Производитель браузера Firefox удалил из интерфейса интеграции одну очень важную для нас функцию, и мы больше не можем обеспечивать поддержку нативных событий в последних версиях браузеров. Насколько это плохо? Как мы будем теперь жить, без нативных событий? И что это вообще такое, чёрт побери? Сейчас расскажу.
Уровень операционной системы
Что происходит, когда пользователь кликает мышкой по какому-нибудь элементу в браузере? Например, по ссылке. Например, в операционной системе Windows.
Это действие пользователя далеко не сразу доходит до браузера. Сначала операционная система через драйвер мыши определяет, какая кнопка была нажата и в каком месте экрана при этом находился курсор мыши.
После этого в операционной системе генерируется серия событий из группы Mouse Input Notifications. Причём генерируются не только события, связанные с кликом, но ещё и события перемещения мыши, ведь пользователь наверняка ещё и двигал её перед тем, как кликнуть.
Все эти события попадают в специальную очередь событий, происходящих в пользовательском интерфейсе, после чего они начинают обрабатываться. Особый модуль операционной системы хватает очередное событие из очереди и пытается определить, какому приложению оно предназначено. Координаты клика сопоставляются с расположением окон на экране, учитываются размеры окон, их взаимное расположение. В конце концов находится приложение, которому предназначается этот клик и событие направляется выбранному приложению. И теперь уже внутри приложения срабатывают обработчики, которые ассоциированы с этим событием.
Уровень браузера
Если приложение реализует пользовательский интерфейс, используя “стандартные” элементы (например, используя библиотеку WPF), то в нём уже есть стандартные обработчики, которые отреагируют на возникновение события, определят, какому элементу внутри приложения (кнопке, ссылке, пункту меню) адресовано событие, и вызовут подходящие функции-обработчики, связанные с нужным элементом.
Разработчики браузеров не используют “стандартные” элементы пользовательского интерфейса для отрисовки страниц (хотя могут использовать их для меню и диалогов). У них есть свой стандарт для элементов, который называется DOM, а посвящённая событиям часть этого стандарта называется DOM Events.
Однако там тоже есть обработчик, который реагирует на события уровня операционной системы. Вопрос – что он делает с ними? Во что преобразует?
Внутри браузера есть своя собственная очередь событий. Поэтому обработчик событий, приходящих от операционной системы, преобразует их во внутренний формат и помещает во внутреннюю очередь браузера. Ну и дальше они как-то доставляются браузером до нужных кнопок и ссылок.
Нативные и синтезированные события
Так вот, теперь пришло время объяснить, что такое нативные и синтезированные события.
Когда Selenium эмулирует действия пользователя, он эмулирует возникновение каких-то событий. И делать он это может либо на уровне операционной системы, либо на уровне браузера.
То есть либо эмулируются события операционной системы и помещаются в соответствующую очередь событий операционной системы. Либо эмулируются события браузера и помещаются сразу во внутреннюю очередь браузера, полностью минуя операционную систему.
Первый способ называется “реализация с использованием нативных событий”, а второй – “реализация с использованием синтезированных событий”.
Вот и вся разница.
И какой же способ лучше?
Да, я понимаю, что читателей наверняка интересуют не технические детали, а практический вопрос – какая из двух реализаций лучше?
Ответ: я считаю, что синтезированные события лучше. Почему? Про это я расскажу в следующем посте.