自作 Chrome 拡張の使い勝手を詰める:未入力件数のバッジと、動画の保存先が違っていた話
明細190件が、15種にまとまった。
会計ソフトAの取引一覧に載せている自作拡張へ、明細の内容サマリを作らせた結果だ。 表示中の明細を内容ごとに集計して件数と金額を並べ、テーブルごと TSV でコピーできる。 あるカードの明細で試すと、内容のまとめをONにして15種、そのままなら24種になった。 190行を目で追う代わりに、15行を見ればいい。
なかでも効いたのは、未入力の件数がその場に出ることだった。
入力ステータスと勘定科目の列
続けて、「未入力」列を「入力ステータス / 勘定科目」に置き換えてもらった。 入力済みの明細は、仕訳の借方科目で数える。 1つの内容に複数の科目を使っていれば、その数だけ行が増える。 内容、件数、合計金額、内訳は rowspan で縦につながるようにさせた。
できたものを画面で見ていたら、注文が2つ出てきた。 1つは、サマリの上部がまだ空いていることだった。 せっかく領域があるのに、何も置いていない。 もう1つはバッジだった。
連携サービスの角に出す未入力件数
連携サービスの一覧には、口座ごとのカードが並ぶ。 そのカードの右上の角に小さい丸を1つ載せて、未入力の件数を数字だけ入れてほしい。 どの口座に何件残っているかを、一覧のまま知りたかった。
気にしたのは取得コストだった。
連携サービス別の未入力件数を数えるのに、口座の数だけリクエストを投げるようだと重い。
調べさせたら、1リクエストで全部取れることが分かった。
ある口座で1件と出て、画面の実数とも一致した。
注文は2つとも入り、その場でコミットとプッシュまで済ませた(63dbfa6)。
並び替えの優先順位
前日に入れてもらった機能で、1つ直してほしいところがあった。
この一覧は、ステータス(入力済み/未入力)でも日付でも並び替えられる。 ステータスで未入力に並べ替えてから、日付でもう一度並べ替える。 このとき第1キーになるのは、最後に押した日付のはずだ。 表計算ソフトならそう動く。
直させたら、最後にクリックした列が第1キーになり、もう一方は同値のときの第2キーとして残る形になった(d292ede)。
ある口座の115件(うち未入力1件)で確かめた。
直すたびに chrome-extension-reload で拡張を読み直させ、実機で見て確かめている。
セッションの残りを聞くと、4点挙がってきた。 一番効くのは、拡張をリロードしても開きっぱなしのタブが古いまま動く点だ。 ページを1回読み直さないと反映されない。 残りもまとめてコミットとプッシュをさせた。 学習ゲートはスキップでいい。
効かないダウンロードボタン
昼、動画の再生ページで「ダウンロード」ボタンを押した。 何も起きない。 自分でセットしたボタンなのに、どの拡張がそれを出しているのかも思い出せなくなっていた。 ライブラリの更新でどこかが噛み合わなくなったのだろう、というのが最初の見立てだった。
この拡張は、動画のページにボタンを1つ足すだけのものだ。 押すと Native Messaging でローカルのホストを叩き、yt-dlp が落としてくる。 X 向けに作ったものを、YouTube にも広げてあった。
調べさせると、まず設定ファイルを生成しているバッチの JSON エスケープが壊れていた。
\U や \n が不正なエスケープになる。
文字列置換をやめて Python で書き出す形に直させた。
続いて本命が出た。 yt-dlp が 2026.01.31 のままで、YouTube 側の仕様変更に対して HTTP 403 を返していた。
ここで、見立てが1つ外れていたことも分かった。 X 用と YouTube 用で別々の yt-dlp が入っていると思っていたが、実際は1本しかない。 どちらの拡張も同じバイナリを呼んでいて、両方が古いままだった。 X が動いていたのは、X の配信方式が変わっていなかったからだ。 YouTube 側だけが SABR-only streaming の実験を進めた結果、同じバイナリが YouTube でだけ 403 を返していた。 2026.08.19 に更新したので、X 拡張のほうも同時に新しくなった。
更新したあとに、もう1つ落とし穴が出た。
--trim-filenames は名前のとおりファイル名を切るのだと思っていたら、出力パス全体を切る。
そのままでは、意図しない場所に保存される。
ここも直させた。
それでも、ボタンからはまだ落とせていない、という報告が返ってきた。
秘密鍵の警告
拡張の一覧に出ていた警告も、このとき気になって聞いた。
拡張のフォルダに extension_private_key.pem が入っているが、おそらく必要ない、という文面だ。
なぜ入っているのかが分からなかった。
答えは、警告のほうが正しい、というものだった。
フォルダ読み込み(unpacked)で使う分には、秘密鍵は要らない。
鍵が要るのは、.crx にパッケージ化して配布するときだけだ。
作った経緯にも理由はあった。
拡張のIDはふつうフォルダのパスから決まるので、フォルダを移すとIDが変わる。
IDが変わると Native Messaging の allowed_origins が合わなくなって壊れる。
それを避けるためにIDを固定したくて鍵ペアを作り、公開鍵だけを manifest.json の "key" に入れていた。
IDを決めているのは公開鍵のほうなので、秘密鍵は生成時の副産物として残っていた。
フォルダごと誰かに渡せば、鍵も一緒に出ていく。 ホーム配下の別ディレクトリへ移させた。 拡張を読み直せば、警告は消える。
トーストに出す保存先のパス
ダウンロードが終わったあとの表示も注文した。 「保存しました」とだけ出ても、どこに入ったのか分からない。 X 拡張のほうでは保存先のフルパスを出しているので、同じものを YouTube 側にも出してほしい。
ページ内トーストにフルパスを表示し、「フォルダを開く」と「パスをコピー」を付ける形で実装させた。 このときは chrome-devtools MCP が落ちていて、描画までは確認できていない、と申告があった。
コミットの前にログを見せたら、実害のあるバグが1つ見つかり、直させて一緒に上げた。 同時に、良い知らせも出てきた。 12:36 に、最初に渡した動画(577MB)が拡張のボタン経由で落ちていた。 ボタンから native host を経て yt-dlp まで、経路は通っていた。
見当たらない保存先
ここで、自分が見ていたものとつながった。
クラウドドライブのマイドライブを開いても、そのファイルが無い。 代わりに、C ドライブのダウンロードディレクトリに落ちていた。 落ちてはいるのに、行き先が違う。
もう一度自分で実行して確かめることにした。 マイドライブに入れば、C ドライブに残ったほうを消すだけで済む。 実行の前に、拡張の再読み込みを押しておくよう念を押された。 押さないと古い background.js が動いたままで、また同じ場所に落ちる。
再読み込みして、実行した。 問題なかった。 13:21:11 に、クラウドドライブのマイドライブ配下へ 577MB のファイルが保存されていた。 ファイル名にも、投稿者名、タイトル、動画IDが入っている。
「ライブラリの更新でうまくいっていない」という最初の見立ては、403 の部分では当たっていた。 ただ、最後まで残っていたのは保存先の設定と、拡張を読み直していなかったことだった。
学びメモ
- 拡張のコードを直しても、開いたままのタブとロード済みの background.js は古いまま動く。拡張の再読み込みとページの読み直しまでが1セット
--trim-filenamesはファイル名ではなく出力パス全体を切る。意図しない場所に保存される- unpacked で使う拡張に秘密鍵は要らない。IDを決めているのは manifest の公開鍵で、秘密鍵はフォルダの外へ出す
- 「効かない」の原因は1つとは限らなかった。設定ファイルの生成、yt-dlp のバージョン、パスの切り詰め、ログから出たバグと、順に潰して、ようやくボタンから落とせた
- 件数を画面に出す機能は、取得コストを先に測ってから作らせる。1リクエストで済むなら、置ける場所はもっとある
同じ日に、2本とも同じところでつまずいた。 片方は開きっぱなしのタブ、もう片方は再読み込み前の background.js だ。 どちらも直したあとに、古いほうがそのまま動いていた。 読み直しを押し忘れたかどうかを画面から知る手立ては、いまのところ思いつかない。