😵‍💫

開発したChrome拡張機能がArcだと動かない!?

に公開

こんにちは、つついです!

私は普段から業務・プライベートともに Arc を愛用しています。(最近は Dia に流れつつありますが...)

たまたま Chrome 拡張を開発する機会があり、Chrome では動作しているのに、Chromium をベースに開発された Arc では正常に動作しない事象がありました。
その原因調査をする中で Chrome と Arc の仕様の違いを見つけたので共有しようと思います!

Chromeでは動くのに、Arcでは動かない?

今回の事象を再現してみました。
ポップアップにボタンだけ配置されていて、クリックすると非同期処理が走るような挙動になっています。

以下のコードが Chrome では動作するのに Arc では動作しなかった原因のコードです。
どこがおかしいのでしょうか?

const handleClick = async () => {
  await doSomething();
  window.close();
};

Chrome でデバッグしてみると正しく動くので「まあ大丈夫だろう」と思いがちだと思います。

なぜ Arc では動かないのでしょうか?

その原因とは

Chrome では動作するのに Arc では動作しない原因は各ブラウザの仕様の違いにありました。

We fixed a bug preventing extension processes from exiting when their associated popups are closed
Source: Arc for Windows - 2023-2025 Release Notes

Arc のリリースノートにこのような記述がありました。
日本語に訳すと、「関連するポップアップを閉じた際に拡張機能のプロセスが終了しなくなる不具合を修正しました」となります。

つまり、Arc ではポップアップが閉じる時に何らかの処理が走っている場合、それを途中で終了させてしまう仕様になっていると解釈できます。

どうやら今回のケースではhandleClick関数内の非同期処理が終了させられているようです。

たとえ doSomthing() の後に window.close() を書こうが、非同期で処理されるため doSomething() の処理が終わる前にポップアップを閉じてしまい、Arc がそのプロセスを終了させてしまったので動作しなかったわけです。

Chromeはどうなの?

では一方で Chrome はどういう仕様なのでしょうか?

Chrome 拡張の拡張機能の中心的なイベントハンドラ(つまり、裏側で動く部分)をサービスワーカーと呼ぶようです。そのサービスワーカーの仕様は公式ブログによると、

The service worker terminates after 30 seconds of inactivity.
Source: Chrome for Developers Blog

日本語で訳すと、「サービスワーカーは30秒間何の動きもないと終了します」となります。

どうやら Chrome では30秒も待ってくれるようです。だからポップアップが閉じても非同期処理は走り続けてくれるんですね。

解決法

ということで原因がわかったのでコードを修正していきましょう。

修正は非常に簡単で、非同期処理が終わるのを待ってからポップアップを閉じるように変更しましょう。修正後のコードは以下のようになります。

const handleClick = async () => {
  await doSomething().finally(() => {
    window.close();
  });
};

これで無事 Arc でも動作するようになりました 🎉

さいごに

今回は、Chrome と Arc の拡張機能のライフサイクルの微妙な違いという落とし穴を実例とともに紹介しました。ただ先日 Arc の開発終了が発表され、新たなブラウザを模索する日々ではありますが、この記事が誰かの助けになれば幸いです!

Discussion