Вопрос: Как написать расширение для браузера в виде dll?

Лучший ответ: Вопрос выглядит как типичная XY problem. Нужно исходить из реальных практических задач и под них искать инструменты, которые помогают их решить. Скажем, если нужно вырезать из страницы баннеры и кнопки интеграций фейсбука, добавить какие-то отсутствующие на сайте client-side функции (такие, как управление скоростью воспроизведения в тэге video), то это одни инструменты. Если надо автоматизированно без участия пользователя нажимать на кнопки, переходить по ссылкам, сохранять полезное содержимое страниц - другие. Если надо отслеживать актуальность сертификатов или контролировать доступность камеры - третьи и четвёртые. Кстати, для последнего в браузерах уже давно есть защита - никакому сайту не даёт получать доступ к камере без явного разрешения пользователя.

Далее, dll - это всего лишь формат загружаемых библиотек с возможностью вызова функций из них. Их кто-то должен куда-то загружать и как-то вызывать. Выбрать сразу dll без чёткого указания того, кто и как их будет использовать - это уже сразу неправильно. Конкретно в случае браузеров в принципе нет никакого интерфейса для взаимодействия с ними (NPAPI и PPAPI вроде уже наконец похоронили вместе с флешом [upd: NPAPI полностью удалён в Chrome 45 и Firefox 85, PPAPI в Chrome тоже планируется удалить]), не говоря уже о том, чтобы вызывать эти функции вообще при каждом чихе браузера.

Зачем в вопросе указаны три языка программирования? Это, кстати, нарушение правил сайта, так как вопрос к этим языкам ну вообще никак не относится. И да, если в браузерах принято использовать javascript, значит, надо использовать javascript. Если в научном мире принято говорить на English, а в медицине используется латинский, то нет смысла в них пользоваться суахили назло всем.

Худший ответ: NPAPI и PPAPI, которые упоминались, нужны для воплощения тегов object и embed, и это не ваш случай, это не про перехват. Вам нужны ActiveX и XPCOM, но на них сейчас уже практически невозможно делать расширения.

Так что для вашего случая подойдёт только WebExtensions. Там обязательно писать часть кода на JavaScript. Вы можете свой перехватчик написать в виде локального веб-сервера и общаться между браузером и перехватчиком по HTTP. Ну или WebSocket. Или даже чистый сокет, расширению можно их открывать. Если ваше расширение относительно тупое, а локальный веб-сервер умный, то локальный веб-сервер на чём угодно можно писать.

Это реальная практика. Например, Контур.Эльба состоит из двух частей, из агента (HTTP-сервер) и расширения. Для всяких пенсионных и страховых фондов нужно свои расширения и агенты ставить, чтоб до ЭЦП достучаться, вот они все примерно по одному принципу сейчас делаются.

При этом нужно иметь в виду, как сделаны расширения. Браузеры сейчас работают в несколько процессов и несколько потоков. У расширения есть возможность чего-нибудь повыполнять в самом главном потоке окна браузера, где живут дополнительные кнопки панели, но такой код стремятся свести к минимуму. Ещё у расширения есть невидимая вкладка, в которой исполняется background.js, и большинство кода, по идее, переносится в неё. Но из этой вкладки напрямую нельзя достучаться до DOM вкладок с сайтами, поэтому есть отдельный механизм, как забрасывать привилегированные скрипты во вкладки с сайтами. И потом разрозненные части расширения между разными потоками и процессами должны общаться сообщениями.

Чтоб перехватить нажатие клавиши, это как раз нужно забросить в чужую вкладку скрипт. Дальше начинается вопрос, что с этим делать. Ваш гипотетический умный HTTP-сервер на localhost должен получить сигнал о перехваченной клавише, среагировать и послать ответ. Но асинхронная модель исполнения браузера не позволит получить ответ сразу. А обработчик события клавиши должен принять какое-то решение. Впитать клавишу, не пропустить её обработку дальше, или пропустить. return false или return true. Тут либо в JavaScript закодировать принятие решения, либо использовать нерекомендуемый синхронный XHR.

Даже если пробить брешь, и как-нибудь через не хочу подгрузить библиотеку, есть такая особенность. В операционных системах есть API, чтобы лишить процесс привилегий, и рабочие процессы браузеров создаются как раз такими. Безправными и слепыми. Их доступ во внешний мир сделан через трубу с основным процессом браузера, через спроецированную память и так далее. Не имея доступа к этой трубе и не зная, как ей пользоваться, вы библиотекой там ничего особо не поделаете. Устройство DOM отличается у каждого браузера и переплетено со сборкой мусора JavaScript. Если разработчики не предоставили специального, совместимого со сборкой мусора, интерфейса, как это было раньше в Firefox и Internet Explorer, там никак стабильно и переносимо не подкопаться, кроме как через JavaScript.