Bing Chat 等の「文字変換!あっ、途中で送信された..orz」を防ぐChrome拡張を作ってみた
ニッチなChrome拡張を作ってみたので紹介です。
🛡️ 作ったもの
最近LLMサービスの台頭で、海外のチャット形式のサイトを触る機会が増えました。
ただ、その時に困るのがIMEの文字変換に対応しておらず、文字変換確定のEnterで入力内容が送信されることです。
代表的なものには Bing Chat やChatPDFです。MacのEdgeやChromeでBing Chatを使った人は何度もこの問題に遭遇したことがあると思います。
そこで、この問題を解決するIME Submit BlockerというChrome拡張を作ってみました。
以下動画のように、この拡張機能を入れるとどのようなサイトでもIMEの文字変換確定のEnterで入力内容が送信されなくなります。
Chrome Web StoreとEdge Add-onsにも公開しているのでぜひ使ってみてください。
(良かったらChrome Web StoreのレビューかGitHubのStarをもらえると泣いて喜びます😭)
🛠️ 実装のポイント
実装時の工夫を紹介します。
以下で説明するコードはすべてGitHubのリポジトリで公開しています。
Plasmo での爆速開発
今回はじめてPlasmoというフレームワークを使って、Chrome拡張機能を作ってみました。PlasmoはChrome拡張機能を効率的に開発するための各種ツールを提供してくれるフレームワークです。
Plasmoの特徴は以下の通りです。
- React, Vue, SvelteでのUI構築
- Chrome, Edge, Firefoxなど複数ブラウザへの対応
- HMRによる開発効率の向上
- MessagingやLocalStoreなどのブラウザの API を簡単に利用できるラッパーの提供
実際に開発してみて、はじめてRailsでWebアプリを使ったときのような快適さを感じました。Chrome拡張機能の開発は、地味に環境構築やAPIの理解に時間がかかるのですが、そこに時間を取られることなくスムーズに開発できて良かったです。
isComposing
でIMEの文字変換確定かどうかを判定
IMEの文字変換確定のEnterかどうかの判定は、isComposing
というAPIを使っています。
isComposingはKeyboardEventが持つReadonlyのプロパティで、IMEの文字変換中かどうかを表します。IMEの文字変換中のEnter の場合は、isComposingがtrueになります。それをdocumentのcapturingフェイズで判定して、stopPropagationとpreventDefaultを行うことで、IMEの文字変換中のEnterでの入力内容送信を防いでいます。
Shadow DOM を考慮したイベントの購読
Bing ChatのようなWebComponentsのShadow DOMを使っているサイトでは、通常のdocument.addEventListenerのみでは入力欄のイベントをすべて取得できません。そのため、Shadow DOMを考慮した実装を行う必要があります。
今回の実装ではWebComponentsをタグ名の正規表現で取得し、そのShadow Rootに存在するWebComponentsを再帰的に取得することで、すべてのRootNodeのkeyup
, keydown
イベントを購読しています。
そうすることでほぼすべてのサイトのすべての入力欄での誤送信を防ぎます。
chrome.history.onVisited.addListener
を利用した SPA 対応
SPAでのページ遷移時にも入力欄にイベントを再アタッチするために、chrome.history.onVisited.addListener
を利用しています。
これはExtensionのbackground Service Workerで登録しているのですが、ページ遷移の度に引数で渡したコールバック関数が呼び出されます。そこで、content scriptにメッセージを送信して、content script側でイベントを再アタッチするようにしています。
AbortSignal
を利用したキャンセルの実装
手動でもON/OFFを制御できるようにするために、 AbortSignal
を使っています。
AbortSignalはFetch APIの中断やEventListenerの購読停止に利用できます。今回は、グローバルに定義したAbortControllerのSignalを各EventListenerでのイベント登録時に引数で渡して、キャセルの実行時にAbortControllerのabortメソッドを呼び出すことで、イベントの購読を停止しています。
💁♂️ おわりに
以上「IME Submit Blocker」の紹介でした!使ってもらえると嬉しいです!!
何か不具合あれば、気軽にIssueを立ててください。
Plasmoを試してみたり、普段使わないAPIを使ったりと勉強になりました。Plasmoの開発体験はとても良かったので今後も使っていきたいです。
Discussion