"Manifest에 선언. SW에서 manipulate. User gesture 아래에서 open. 세 문장, 한 lesson 안의 세 lesson — 그리고 어느 하나라도 건너뛰면 API가 조용히 동작 거부하는 세 가지 실제 방법."
Step 1 — Manifest에 선언
두 field가 함께 default panel 등록:
side_panel.default_path— panel 열릴 때 Chrome이 load 할 extension 안 HTML file. Panel 존재 자체에 필수.permissions의"sidePanel"— SW에서chrome.sidePanel.*호출 필수. 그게 없으면 API 자체가 undefined.
이것만 있어도 Chrome의 side-panel 목록에는 뜨긴 해. user가 직접 골라서 열 수 있고. 다만 그 외에는 아무것도 연결이 안 돼 있어.
Step 2 — SW에서 behavior 구성
chrome.sidePanel API가 실제로 쓸 세 method 노출:
chrome.sidePanel.setOptions({ tabId?, path, enabled })— panel HTML과 enabled 상태 설정, 선택적으로 tab 별. 한 tab target 하려면tabId전달. global default 면 생략.chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: boolean })— toolbar icon click이 popup 대신 panel 열지 toggle. Icon click의 popup과 mutually exclusive: click이 panel 열거나 popup 열거나.chrome.sidePanel.open({ tabId? | windowId? })— programmatic panel 열기. User-gesture handler (action click, keyboard command, context menu)에서 호출해야 함, 아니면 reject.
셋 다 SW에 살아. Panel 자체는 자기 visibility 구성 안 함 — cross-tab perspective 가진 SW에 그 권한이 있어.
User-gesture 규칙
chrome.sidePanel.open()가 엄격한 거. Timer, alarm, webRequest event, user gesture에서 안 온 content-script 메시지에서 호출하면 Side panel can only be opened by a user gesture로 reject. 정당한 trigger:
chrome.action.onClicked— toolbar icon click. Manifest에default_popup없을 때만 fire.chrome.commands.onCommand— manifestcommandsblock에 선언된 keyboard shortcut.chrome.contextMenus.onClicked— right-click menu item.- 실제 user click에 응답하는 popup 이나 panel에서 온 메시지일 때의
chrome.runtime.onMessage— Chrome이 그걸 gesture-derived event로 다룸.
이건 보안의 밑바닥 규칙이야. extension이 user가 아무것도 안 했는데 멋대로 panel을 들이밀 수는 없다는 거지. 그러니 존중해 줘. timeout을 걸어서 user가 누른 척 흉내 내려고 하지 말고.
Global-first 패턴
모든 tab이 같은 panel을 쓰는 ClipDeck v1은 global option 하나면 충분해:
- Manifest가 default
path와sidePanelpermission을 선언해. - SW가
chrome.sidePanel.setOptions({ path: 'panel.html', enabled: true })를 global로 한 번 걸어. - URL에 따라 panel을 끄거나 다른 path를 줄 제품 요구가 생길 때만
tabId와 tab lifecycle listener를 더해.
Popup 공존 선택
ClipDeck은 popup과 panel 둘 다 ship. Toolbar icon이 default로 뭘 열지 골라야 함:
action.default_popup: "popup.html"을 그대로 두고openPanelOnActionClick: false로 하면 → toolbar를 누르면 popup이 뜨고, panel은 자기 토글이나 버튼으로만 열려.default_popup제거 ANDopenPanelOnActionClick: true설정 → toolbar click이 panel 열고. popup은 icon에서 닿을 수 없음 (키보드나 다른 flow로 여전히 열 수는 있음).- 둘 다 유지: 불가. Chrome이 매 click에 선택 강제.
ClipDeck 현재 선택: popup을 default로 유지 (더 빨리 load, "reset / quick stats" 버튼 가짐), popup에 user-gesture handler에서 chrome.sidePanel.open() 부르는 "Open clip list" 버튼 추가.
open()은 user가 뭔가를 누른 직후에만 먹혀. 이 셋 중 하나라도 빠지면 panel이 아예 없거나, 있어도 안 뜨거나, 엉뚱한 에러를 뱉으면서 거절당해.tabs.onActivated나 tabs.onUpdated를 써.