C.W.K.
Stream
Lesson 03 of 05 · published

Host permission — URL match pattern 과 install 경고

~11 min · host_permissions, url-pattern, all_urls, install-warning

Level 0Extension 입덕
0 XP0/54 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"Manifest 의 모든 host pattern 이 만지려고 permission 요청하는 인터넷의 한 평방마일. Lesson 3 가 syntax, install prompt 비용, 가장 무서운 경고 최소로 가장 큰 reach 위해 ClipDeck design 하는 법."

URL match pattern syntax

Match pattern 이 세 부분: scheme / host / path. :/// 로 join:

<scheme>://<host>/<path>

예:

  • https://github.com/* — github.com root 과 모든 path, HTTPS only.
  • https://*.github.com/* — github.com AND 모든 subdomain (gist.github.com, api.github.com, ...).
  • https://github.com/anthropics/* — anthropics org 아래 repository 만.
  • *://*/* — Chrome 이 제한하는 거 (chrome://, 등) 외 모든 scheme, 모든 host, 모든 path. 몇 edge case 빼고 <all_urls> 와 동등.
  • <all_urls> — explicit wildcard. HTTP / HTTPS / FTP / file: 매칭.

규칙:

  • Scheme: http, https, file, ftp, 또는 *. 일반 extension 에서 chrome://chrome-extension:// 절대 매칭 안 됨.
  • Host: literal, OR * 혼자 (모든 host), OR *. prefix (subdomain wildcard). Host 가운데 wildcard (foo*.example.com) 안 허용.
  • Path: literal 문자와 * wildcard. Path 필수; "모든 path" 면 /* 사용.

Install 경고 사다리

Chrome 의 prompt 가 host 가 얼마나 넓은지에 따라 scale:

  • 한 특정 host (https://github.com/*) → "Read and change your data on github.com."
  • Subdomain wildcard (https://*.github.com/*) → "Read and change your data on sites in the github.com domain."
  • 여러 특정 host (https://github.com/*, https://gitlab.com/*) → "Read and change your data on github.com and gitlab.com." Chrome 이 작은 한계까지 list, 다음 collapse.
  • <all_urls>*://*/* → 시끄러운 "Read and change all your data on all websites."

"3 host" 와 "all websites" 사이 user 신뢰 drop 이 가파름. 가능하면 host 좁게 cluster, 정말로 everywhere 동작해야 할 케이스에 <all_urls> 예약.

Chrome 의 'Runtime Host Permission' twist

Chrome 70 쯤부터, user 가 puzzle-piece menu 나 chrome://extensions 통해 installed extension 의 site access 변경 가능: "On click," "On ," "On all sites." Manifest 가 host_permissions: ["<all_urls>"] 선언해도, user 가 "On click" 만으로 제한할 수 있어 — extension 이 activeTab 처럼 동작하게 만듦.

함의: 코드가 manifest-declare host permission 이 runtime 상태라고 가정 못 함. 중요할 때 chrome.permissions.contains 사용, 또는 모든 host-touch feature 가 denial 에 resilient 하도록 design (scripting 호출에서 'Cannot access contents of the page' error 돌아옴; catch 하고 설명).

Content-script match pattern

Content script 가 content_scripts 아래 자체 matches 배열 가짐. 같은 syntax 사용하지만 host_permissions 와는 분리된 grant:

  • host_permissions 가 programmatic inject (chrome.scripting), fetch, request 관찰할 권한 부여.
  • content_scripts.matches 가 매 page load 시 static, automatic injection 선언.

Chrome 이 경고 목적으로 둘 union: host_permissions: ["<all_urls>"] OR content_scripts.matches: ["<all_urls>"] 가 같은 무서운 경고 trigger. Host 좁히려면 두 field 함께 좁히기.

ClipDeck 의 선택

ClipDeck v0.9 가 content_scripts.matches: ["<all_urls>"] 가짐 — floating 버튼과 selection capture 가 user 방문 모든 page 에서 동작해야 해서. 경고 부드럽게 하는 두 방법:

  • 항상-on content script 완전 drop. Toolbar click 이나 hotkey 시 activeTab + programmatic chrome.scripting.executeScript 사용. 비용: 매 page 의 floating 버튼 없음, user 가 부른 후만. 이득: install 경고 없음, 훨씬 친절.
  • Content script 유지하되 민감 host 명시적 exclude. 넓은 reach 유지, 일부 카테고리 off-limit 인 거 user 한테 signal. 경고는 변함없지만, 신뢰 신호가 더 강함.

ClipDeck v1 은 두 번째 경로 — floating 버튼이 discovery 이야기 일부라서. v2 가 privacy-minded 무리 위해 activeTab-only mode 로 전환하는 per-user toggle 추가할 수도.

Match pattern: scheme + host + path. 좁은 host = 친절한 install 경고. <all_urls> 가 어떤 prompt 의 가장 시끄러운 줄 — 자격을 얻어. User 가 runtime 에 host downgrade 가능; 그것 위해 design.
User 가 실제로 보는 거 테스트. chrome://extensions → Developer mode → Pack extension → Pack 이 .crx 만 생성; 일반 Chrome profile 에 그거 install (또는 chrome://extensions → Drag and drop). 뜨는 dialog 가 user 가 보는 정확한 install prompt. Permission set 이 eye test 통과하는지 저렴하고 즉각적 feedback.

Code

GitHub-specific helper 위한 좁게-scoped host_permissions·json
{
  "host_permissions": [
    "https://github.com/*",
    "https://*.github.com/*",
    "https://gist.github.com/*"
  ]
}
Privacy-sensitive 명시적 exclusion 가진 넓은 matches·json
{
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "exclude_matches": [
        "https://accounts.google.com/*",
        "https://*.googleusercontent.com/*",
        "https://*.bank.com/*",
        "https://*.chase.com/*",
        "https://*.passwordmanager.com/*"
      ],
      "js": ["content.js"],
      "run_at": "document_idle"
    }
  ]
}
background.js — executeScript denial 의 defensive wrapper·javascript
// background.js — user 가 runtime 에 host access downgrade 처리
async function safeInject(tabId, fileOrFunc) {
  try {
    return await chrome.scripting.executeScript({
      target: { tabId },
      ...(typeof fileOrFunc === "function" ? { func: fileOrFunc } : { files: [fileOrFunc] }),
    });
  } catch (err) {
    if (String(err.message).includes("Cannot access")) {
      // URL 이 restricted (chrome:// 등) 이거나 OR user 가 이 site 의
      // 이 extension 의 site access revoke.
      console.warn("[ClipDeck SW] cannot inject:", err.message);
      return null;
    }
    throw err;
  }
}

External links

Exercise

clipdeck/manifest.json 의 content_scripts entry 에 두 번째 code block 의 explicit exclude_matches list 추가. Reload. 은행이나 password-manager URL (또는 exclude list 의 어느 거) 방문 — floating 버튼 안 나타나고 SW DevTools 에 [ClipDeck content] 줄 안 로깅되는지 확인. 다음 chrome://extensions → ClipDeck → 'This can read and change site data' 에서 'On all sites' 에서 'On click' 으로 전환. 이제 실제 page 방문 — ClipDeck 안 동작 보임; toolbar-icon click 은 여전히 capture 해야 함 (activeTab 통해). 세 번째 code block 의 safeInject helper 를 background.js 에 추가하고 chrome.scripting.executeScript 현재 있는 곳에 wire — wrapper 가 runtime-revoke-access error 를 exception 대신 silent return 으로 바꿈.
Hint
Floating 버튼이 excluded site 에서도 여전히 나타나면, exclude_matches pattern 이 틀릴 수도 — Chrome 이 literal 매칭하고, https://*.bank.com/*https://bank.com/ (subdomain 없음) 에 매칭 안 함. Apex 필요하면 https://bank.com/* 명시적 추가. 'On click' 으로 전환이 side panel 도 깨면, 옛 Chrome 에선 실제로 예상 — 새 Chrome 은 panel content 가 restricted tab 에서도 렌더되게 (panel 이 extension-owned) 하지만, page 에 대한 chrome.scripting.executeScript 는 여전히 reject. safeInject wrapper 가 rejection 을 silently 처리; deny 되는 action 이 user-initiated 면 user-facing 메시지 surface.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.