[{"data":1,"prerenderedAt":475},["ShallowReactive",2],{"content-/chrome-extension-click-area-and-pycache":3,"all-pages-for-dir":454,"related-/chrome-extension-click-area-and-pycache":455,"og-image-/chrome-extension-click-area-and-pycache":474},{"id":4,"title":5,"body":6,"category":434,"concepts":435,"description":436,"extension":437,"meta":438,"navigation":439,"ogImage":435,"path":440,"project_name":441,"published":442,"publishedAt":443,"seo":444,"source":445,"stem":446,"tags":447,"todo":435,"unpublished":442,"updatedAt":435,"__hash__":453},"pages/2026-08/2026-08-19/chrome-extension-click-area-and-pycache.md","Chrome拡張のクリック領域が行全体に広がるバグと、__pycache__ で拡張が無効化される罠",{"type":7,"value":8,"toc":426},"minimark",[9,14,18,21,24,27,43,61,64,164,168,171,174,177,192,195,203,226,241,251,254,257,260,269,272,275,285,299,305,355,370,381,384,387,408,423],[10,11,13],"h2",{"id":12},"リポストを押したら動画のダウンロードが走った","リポストを押したら、動画のダウンロードが走った",[15,16,17],"p",{},"X のタイムラインで、動画付きの投稿にリポストを押した。\n動画のダウンロードが始まった。",[15,19,20],{},"自分で入れた拡張が、押してもいないボタンの仕事をしている。\nダウンロードボタンは右端のブックマークのすぐ左に1個だけ置いたはずで、指が触れたのはそこから離れたリポストの位置だった。\nだとすれば当たりは1つしかない。\nボタンのクリック判定領域が、置いた場所を越えて広がっている。",[15,22,23],{},"スクリーンショットを撮り、その見立てと一緒に Claude Code へ渡した。\nボタン生成まわりのコードを読ませ、実機で領域を実測させる。",[10,25,26],{"id":26},"クリック判定はどこから広がっていたか",[15,28,29,30,34,35,38,39,42],{},"読ませてみると、ボタンの外枠には X のハッシュ化クラス（",[31,32,33],"code",{},"css-175oi2r"," など）をそのまま流用していた。\n中には X のホバー用オーバーレイ div も1枚借りていた。\n",[31,36,37],{},"position: absolute; inset: 0; margin: -8px"," を当てて「ボタンより一回り大きい当たり判定」を作る部品で、外枠が ",[31,40,41],{},"position: relative"," であることを前提にしている。",[15,44,45,46,48,49,52,53,56,57,60],{},"その前提が、X 側のリリースで外れていた。\nベースのクラス名が ",[31,47,33],{}," から ",[31,50,51],{},"css-g5y9jx"," へ変わり、借りていた外枠は ",[31,54,55],{},"position: static"," に戻る。\n",[31,58,59],{},"absolute"," の基準は最も近い配置済みの祖先へ移り、オーバーレイはボタンの周囲8pxではなく、アクション行そのものを覆った。\nリポストのクリックは、そこで横取りされていた。",[15,62,63],{},"方針は、借りるのをやめることだった。\nハッシュ化クラスへの依存を捨て、オーバーレイの div を消し、外枠を自前のスタイルで閉じさせた。",[65,66,71],"pre",{"className":67,"code":68,"language":69,"meta":70,"style":70},"language-js shiki shiki-themes vitesse-light vitesse-light","button.className = \"twitter-video-downloader-button\";\nbutton.style.position = \"relative\";\nbutton.style.display = \"flex\";\n// padding 8px + 20px の SVG だけで枠を決める\n","js","",[31,72,73,106,132,157],{"__ignoreMap":70},[74,75,78,82,86,89,92,96,100,103],"span",{"class":76,"line":77},"line",1,[74,79,81],{"class":80},"s4oTP","button",[74,83,85],{"class":84},"shFtX",".",[74,87,88],{"class":80},"className",[74,90,91],{"class":84}," =",[74,93,95],{"class":94},"sMJiu"," \"",[74,97,99],{"class":98},"sdGka","twitter-video-downloader-button",[74,101,102],{"class":94},"\"",[74,104,105],{"class":84},";\n",[74,107,109,111,113,116,118,121,123,125,128,130],{"class":76,"line":108},2,[74,110,81],{"class":80},[74,112,85],{"class":84},[74,114,115],{"class":80},"style",[74,117,85],{"class":84},[74,119,120],{"class":80},"position",[74,122,91],{"class":84},[74,124,95],{"class":94},[74,126,127],{"class":98},"relative",[74,129,102],{"class":94},[74,131,105],{"class":84},[74,133,135,137,139,141,143,146,148,150,153,155],{"class":76,"line":134},3,[74,136,81],{"class":80},[74,138,85],{"class":84},[74,140,115],{"class":80},[74,142,85],{"class":84},[74,144,145],{"class":80},"display",[74,147,91],{"class":84},[74,149,95],{"class":94},[74,151,152],{"class":98},"flex",[74,154,102],{"class":94},[74,156,105],{"class":84},[74,158,160],{"class":76,"line":159},4,[74,161,163],{"class":162},"sxvE3","// padding 8px + 20px の SVG だけで枠を決める\n",[10,165,167],{"id":166},"直したはずのボタンが丸ごと消えた","直したはずのボタンが、丸ごと消えた",[15,169,170],{},"拡張をリロードして、X のタブを読み直した。\nボタンが無い。",[15,172,173],{},"消えたのはダウンロードボタンだけではなかった。\n背景を濃いグレーに置き換える CSS も、Spaces 用のボタンも、まとめて画面から落ちていた。",[15,175,176],{},"いったんは自分の修正を疑ったが、消え方が広すぎる。\nボタンを1つ作る関数を書き替えて、別機能の CSS まで巻き添えにする筋道はない。\n拡張そのものが動いていないのではないかと見当をつけて、状態を調べさせた。",[15,178,179,180,183,184,187,188,191],{},"拡張は無効化されていた。\n",[31,181,182],{},"disableReasons.reloading: true"," を抱えたまま、",[31,185,186],{},"DISABLED"," から戻ってこない。\nruntime のエラー一覧には ",[31,189,190],{},"Unable to download all specified images."," の1行しか出ておらず、これは今回と関係がなかった。",[15,193,194],{},"一覧ではなくロードエラーのダイアログを開かせたら、本文にそのまま書いてあった。",[65,196,201],{"className":197,"code":199,"language":200},[198],"language-text","Cannot load extension with file or directory name __pycache__.\nFilenames starting with \"_\" are reserved for use by the system.\n","text",[31,202,199],{"__ignoreMap":70},[15,204,205,206,209,210,213,214,217,218,221,222,225],{},"拡張フォルダの直下に ",[31,207,208],{},"__pycache__/native_host.cpython-311.pyc"," が居座っていた。\n生成されたのは6日前の 2026-08-13 である。\nChrome は拡張ルートの直下に ",[31,211,212],{},"_"," で始まる名前があるとロードを拒否する（",[31,215,216],{},"_locales"," と ",[31,219,220],{},"_metadata"," だけが例外になる）。\nしかもチェックがかかるのはトップレベルだけで、サブディレクトリの奥にある ",[31,223,224],{},"__pycache__"," は何の影響も及ぼさない。",[15,227,228,229,232,233,236,237,240],{},"厄介なのは、この ",[31,230,231],{},".pyc"," が ",[31,234,235],{},".gitignore"," 済みだった点だ。\n",[31,238,239],{},"git status"," は何も言わない。\n置かれてから6日たった今日、リロードを押して踏んだだけだった。",[15,242,243,246,247,250],{},[31,244,245],{},"rm -rf __pycache__"," のあとダイアログの「再読み込み」を押させると、",[31,248,249],{},"ENABLED"," に復帰した。\n消えていた3つの機能も一緒に戻ってきた。",[15,252,253],{},"復帰した拡張で、あらためてクリック領域を実測させる。\nダウンロードボタンが拾うのは本体の 36×36px だけになり、リポストの位置を押しても拡張には届かなくなった。\nここでようやく、最初の症状の裏が取れた。",[10,255,256],{"id":256},"再発防止として残したもの",[15,258,259],{},"次に同じところで止まったときのために、2つ残させた。",[15,261,262,263,265,266,268],{},"1つは拡張リロードのスキルへの追記で、",[31,264,212],{}," 始まりの名前が拡張ルート直下にあるとロードが拒否されるという注意点を入れた。\nもう1つは issue ファイルで、症状とエラー文、",[31,267,245],{}," での復帰までを書かせた。",[15,270,271],{},"書き足したかったのは、原因そのものより読む順番のほうだった。\n拡張が消えたときは runtime のエラー一覧を眺めても答えが出ない。\n今回の犯人は、その一覧に1行も出ていなかった。",[10,273,274],{"id":274},"未コミットの変更をどの粒度で切るか",[15,276,277,280,281,284],{},[31,278,279],{},"content.js"," と issue ファイルを ",[31,282,283],{},"354a0cd"," でコミットさせた。\n学習ゲートは、理由を付けてスキップさせた。",[15,286,287,288,291,292,217,295,298],{},"そのとき「元からあった ",[31,289,290],{},"native_host.*"," の未コミット変更は残します」と報告が来た。\nどこの話なのか分からなかったので、聞き返した。\n複数のリポジトリを行き来していると、こういう「元からあった変更」がどのディレクトリのものか見失う。\n返ってきた答えは、拡張リポジトリ自身の ",[31,293,294],{},"native_host.py",[31,296,297],{},"native_host_powershell.bat"," だった。",[15,300,301,302,304],{},"自分のディレクトリの話なら片付けたい。\nただし1コミットに丸めるのは違うので、中身を読んで粒度を決めろと指示した。\n返ってきたのは ",[31,303,294],{}," の9ハンクのうち8番目だけを切り離す案で、全体で3コミットになった。",[306,307,308,321],"table",{},[309,310,311],"thead",{},[312,313,314,318],"tr",{},[315,316,317],"th",{},"コミット",[315,319,320],{},"内容",[322,323,324,335,345],"tbody",{},[312,325,326,332],{},[327,328,329],"td",{},[31,330,331],{},"823217d",[327,333,334],{},"起動バッチを PATH 非依存にし、PowerShell ラッパーを廃止",[312,336,337,342],{},[327,338,339],{},[31,340,341],{},"1f09ab2",[327,343,344],{},"yt-dlp を PATH に頼らず解決し、起動時と失敗時のログを追加",[312,346,347,352],{},[327,348,349],{},[31,350,351],{},"549040c",[327,353,354],{},"フォルダを開くときの explorer の出力を捕捉",[15,356,357,358,361,362,365,366,369],{},"前の2つは似て見えて層が違う。\nChrome から起動される native host は、Chrome 起動時点の PATH をそのまま引き継ぐ。\nだから Python を PATH に登録するより前から Chrome が動いていると、",[31,359,360],{},"python"," が見つからない。\nそのとき拡張側に出るのは native messaging host との通信エラーだけで、何も分からない。\nバッチ側は python.exe を絶対パスで解決する。\nPython 側は ",[31,363,364],{},"shutil.which","、同じ Python の Scripts、別バージョンの Python、最後に ",[31,367,368],{},"python -m yt_dlp"," の順で yt-dlp を探す。",[15,371,372,373,376,377,380],{},"3つ目を別にしたのは、原因が同じで対象が違うからだ。\nnative messaging は4バイトの長さと JSON でフレームを組むため、stdout に1バイトでも余計な出力が混ざると壊れる。\nPowerShell ラッパーを捨てたのも、",[31,374,375],{},"explorer"," の出力を ",[31,378,379],{},"capture_output=True"," で吸い込んだのも、同じ理由で別の穴を塞いだ話になる。",[15,382,383],{},"プッシュまで終えて、作業ツリーはクリーンになり、origin との差分も消えた。",[10,385,386],{"id":386},"学び",[388,389,390,394,397,400],"ul",{},[391,392,393],"li",{},"ホスト側のハッシュ化クラスに乗ると、相手のリリースがそのままこちらの不具合になる。今回はクラス名が1つ変わっただけで、当たり判定がアクション行の全体まで広がった",[391,395,396],{},"「消えた」の原因が、直前に自分が触った箇所とは限らない。消えた範囲と、修正の影響が届く範囲を比べると早く切り分けられる",[391,398,399],{},"Chrome 拡張のリロードが通らないときは、runtime のエラー一覧よりロードエラーのダイアログを先に読む",[391,401,402,404,405,407],{},[31,403,235],{}," 済みのファイルは ",[31,406,239],{}," に出ない。拡張フォルダの直下だけは、git とは別の目で見る必要がある",[15,409,410,412,413,415,416,418,419,422],{},[31,411,224],{}," が8月13日に生えた理由は、まだ分かっていない。\n",[31,414,294],{}," はスクリプトとして直接叩くので、普段は ",[31,417,231],{}," を残さない。\nどこかから ",[31,420,421],{},"import native_host"," した覚えがあるはずなのに、それがいつだったのか思い出せていない。",[115,424,425],{},"html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":70,"searchDepth":108,"depth":108,"links":427},[428,429,430,431,432,433],{"id":12,"depth":108,"text":13},{"id":26,"depth":108,"text":26},{"id":166,"depth":108,"text":167},{"id":256,"depth":108,"text":256},{"id":274,"depth":108,"text":274},{"id":386,"depth":108,"text":386},"dev",null,"動画付き投稿でリポストを押すとダウンロードが走る不具合を追ったら、原因はX側のクラス名変更だった。直した直後に拡張のボタンが丸ごと消え、そちらは拡張フォルダ直下の __pycache__ が犯人だった一日の記録。","md",{},true,"/chrome-extension-click-area-and-pycache","chrome-extension-x",false,"2026-08-19T00:00:00.000Z",{"title":5,"description":436},"make-diary","2026-08/2026-08-19/chrome-extension-click-area-and-pycache",[448,449,450,451,452],"Chrome拡張","JavaScript","CSS","デバッグ","Git","hKMXYkAI10iK2ezJ2GvKJf0GUxGbshRFyEddtC7LOCM",[],[456,460,464,468,471],{"title":457,"path":458,"publishedAt":459},"自作Chrome拡張のXの動画ダウンロードボタンが消えた——DOM構造の変化を追って復活させた","/x-video-download-button-fix","2026-07-05T00:00:00.000Z",{"title":461,"path":462,"publishedAt":463},"連結精算表のUI改善とデータバグ修正 - 矢印線・多列テーブル・貸借バランス","/consolidated-worksheet-ui-data-fixes-2026-02-02","2026-02-02T00:00:00.000Z",{"title":465,"path":466,"publishedAt":467},"マークダウンページの目次がスクロール時に固定表示されない問題","/table-of-contents-sticky-issue","2025-11-27T00:00:00.000Z",{"title":469,"path":470,"publishedAt":443},"2026年8月19日の開発日記 - やり直しの単位を小さくした一日","/2026-08-19-diary",{"title":472,"path":473,"publishedAt":443},"Windows Defenderの除外でNuxtのビルドは半分になったが、記事のプリレンダーは16%しか縮まなかった","/deploy-speed-defender-and-repo-push-audit","https://log.eurekapu.com/og/blog/chrome-extension-click-area-and-pycache.png?v=2026-08-19T00%3A00%3A00.000Z&title=Chrome%E6%8B%A1%E5%BC%B5%E3%81%AE%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%E9%A0%98%E5%9F%9F%E3%81%8C%E8%A1%8C%E5%85%A8%E4%BD%93%E3%81%AB%E5%BA%83%E3%81%8C%E3%82%8B%E3%83%90%E3%82%B0%E3%81%A8%E3%80%81__pycache__%20%E3%81%A7%E6%8B%A1%E5%BC%B5%E3%81%8C%E7%84%A1%E5%8A%B9%E5%8C%96%E3%81%95%E3%82%8C%E3%82%8B%E7%BD%A0&author=Kei%20Komatsu&sig=2a7de81fb692459c",1787187401061]