Разработчики компании Ekioh доработали браузер Flow для поддержки Google Docs. Движок этого браузера написан с нуля, и его качество уже допускает нормальное отображение многих других сайтов, но для сложных веб-приложений потребовались дополнительные усилия. Результат работы по исправлению ситуации компания описала в посте в своём блоге.
Flow — браузер с собственным, написанным с нуля, проприетарным движком рендеринга, который ставит целью производительность. Движок JavaScript, впрочем, Flow заимствует у Firefox — это SpiderMonkey. Первая бета-версия Flow вышла в конце 2020 года. Компания Ekioh видит свой браузер компонентом телевизионных приставок и встраиваемых систем. В том числе Flow разрабатывается под компьютеры Raspberry Pi и созданных для них ОС.
Разработка Flow для платформы Raspberry Pi ведётся на Raspberry Pi 400 — полноценном компьютере в ретроподобном форм-факторе клавиатуры. На этом компьютере из Flow разработчики успешно написали пост для блога в Google Docs, когда добились в браузере успешного запуска этого веб-приложения. Компания описывает, что это было сделать непросто.
За месяцы до текущих попыток Google Docs в Flow уже пытались открыть, но привело это лишь к непонятным исключениям в консоли. С тех пор в Flow много чего исправляли для других сайтов, что улучшило ситуацию в том числе для для Google Docs, но далеко не до конца.
Google Docs почти полностью состоит из обфусцированного JavaScript. Его структура HTML проста, хотя в ней присутствуют iframe
для различных целей — один для ввода с клавиатуры, а другой для расчета ширины слова и так далее. Со встраиванием Google Docs в Flow было выявлено более 30 различных проблем, требующих исправления.
Каждый из абзацев отображался как одна длинная строка, без переносов. Есть много способов рассчитать ширину букв или слов с помощью методов HTML, сanvas или даже SVG. После некоторой отладки разработчик выяснил, что проблема в реализации Element.getClientRects():
она игнорировала строчные элементы. Заодно исправление этой функции решило баг с положением курсора по щелчку мыши — теперь он приходил в правильную позицию. На этом этапе ввод текста всё ещё не работал.
Теперь Google Docs загружался, но с уведомлениями о неподдерживаемом браузере и отсутствующих шрифтах. Закрытие уведомления лишь приводило к перезагрузке всей страницы, уведомление появлялось вновь. Позднее выяснилось, что это происходило из-за того, как Google Docs обрабатывает фокус.
Уведомление имеет код HTMLAnchorElement
, где в атрибуте href
было указано значение #
. При его активации текущая страница перезагружалась. Баг скрывался в History.setURL()
. Предупреждение об отсутствующих шрифтах возникало в основном из-за того, что интерфейс FontFaceSet (documents.fonts
) в Flow не был установлен в set-alike. Догадываться об этом приходилось по загадочным исключениям в консоли вида «e.Lb(...).fonts.has is not a function
», но даже после исправлений проблема иногда повторялась. Редкие повторные появления бага оказались вызваны iframe
cо значением javascript:
атрибута src
. Flow устанавливал URL документа на javascript:
по запуску, а не инициализации документа. Веб-шрифты же указаны как относительные ссылки, поэтому вызывались по javascript: вместо https:. То, что этот баг появлялся лишь иногда — результат тайминга работы: иногда javascript:
в src
вызывался до document.open()
в другой части документа, что и приводило к отсутствию шрифтов.
Ввод текста по-прежнему не работал, потому что Google Docs обычно удерживает фокус в скрытом iframe
, а текст отображается в другом месте. Чтобы сохранить фокус в этом iframe
, Google Docs мониторит фокус. Flow отправлял события фокуса не в том порядке, особенно при переходе между фреймами. Баг был вызван легаси-фрагментами кода Flow, оставшимися с той поры, когда это был проект браузера для SVG, а не HTML. В спецификациях SVG 1.2 Tiny обработка фокуса сильно отличается от принятого в HTML: в частности, нельзя перемещать фокус в элемент, для которого отображение установлено в display:none
. После пересмотра кода фокуса Flow ввод с клавиатуры заработал, хотя для нормальной работы некоторых клавиш требовался еще значительный объем работы.
Один из багов вызывал настолько сильные проблемы, что усилия по совместимости чуть не закончились на нём. Хотя ввод работал корректно, нажатие некоторых клавиш на клавиатуре вводило соответствующий им символ дважды. Через несколько дней работы выяснилось, что такому подвержены (в алфавитном порядке) строчные буквы от p до z. Дальнейшее расследование кода показало, что это, видимо, было намеренное решение для обработки символов некоторых кодов ASCII. Смена user agent
на Firefox 68 вместо 62 помогла отключить этот «костыль».
Ещё один баг ввода символов приводил к тому, что при нажатии Ctrl + B вставлялась жирная буква b. Дело в том, что сразу после переключения на полужирный текст происходил ввод буквы. Для исправления бага ввод символов подавили до той поры, пока пользователь удерживает клавишу-модификатор.
Другие баги помельче часто касались производительности. Работа над ошибками включала оптимизацию анимации, чтобы не запускать рендеринг, когда анимация на самом деле не отображалась. Курсор при мигании затухает постепенно, но ⅔ кадров он либо отображается полностью, либо скрыт.
Для оптимизации Flow под Raspberry Pi размер текстур снизили до 2048×2048. Иконки для Google Docs приходят в картинке на 7208 пикселей высоты, которую Flow тут же жмёт до 2048 пикселей. Из-за этого иконки выглядели размытыми. Чтобы этого не происходило, крупные изображения обрабатываются в виде тайлов несколькими текстурами, если это необходимо.
Наконец, правая кнопка мыши не открывала меню. Это было исправлено путем добавления поддержки события contextmenu
.
В качестве доказательства поддержки Google Docs разработчики написали текст в этом офисном редакторе полностью в Flow на Raspberry Pi 400. Октябрьское обновление Flow также содержит поддержку Google Slides, но отдельных отчётов об обнаруженных проблемах команда не публиковала.
Комментариев нет:
Отправить комментарий