Add Firefox Extension#330
Conversation
|
기존 chrome extension 기반으로, codex로 firefox extension 버전으로 포팅 하였습니다. |
There was a problem hiding this comment.
Pull request overview
Adds a new Firefox WebExtension package (rhwp-firefox) that reuses the existing rhwp-studio viewer build output, while wiring Firefox-compatible MV3 background scripts (non–service worker) plus Firefox-specific content-script behavior, build tooling, and documentation.
Changes:
- Added
rhwp-firefoxextension package (manifest, background scripts, content script, options script, SW helpers). - Added Firefox build pipeline (
build.mjs+vite.config.ts) to producerhwp-firefox/distby buildingrhwp-studioand copying shared assets. - Updated repo ignore rules to exclude Node deps and Firefox build output.
Reviewed changes
Copilot reviewed 14 out of 16 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| rhwp-firefox/vite.config.ts | Vite config to build rhwp-studio into the Firefox extension dist/ output |
| rhwp-firefox/sw/viewer-launcher.js | Helper to open/reuse the viewer tab with URL params |
| rhwp-firefox/sw/thumbnail-extractor.js | JS thumbnail extraction from HWP/HWPX (CFB/ZIP) for hover previews |
| rhwp-firefox/sw/message-router.js | Background message routing for open/fetch/thumbnail/settings |
| rhwp-firefox/sw/download-observer.js | Observes downloads and auto-opens detected HWP/HWPX files |
| rhwp-firefox/sw/context-menus.js | Adds context menu entry for opening HWP/HWPX links |
| rhwp-firefox/package.json | Firefox package scripts/deps for build and validation |
| rhwp-firefox/package-lock.json | Locked dev dependency graph for rhwp-firefox |
| rhwp-firefox/options.js | Options page logic (sync storage + i18n strings) |
| rhwp-firefox/manifest.json | Firefox MV3 manifest using background scripts (module) + permissions/CSP |
| rhwp-firefox/firefox-compat.js | Compatibility shim to expose chrome as browser where needed |
| rhwp-firefox/content-script.js | Firefox content script for link detection, hover cards, prefetch, click interception |
| rhwp-firefox/build.mjs | Build script assembling dist/ from studio build + shared assets + WASM/fonts |
| rhwp-firefox/background.js | Background entrypoint wiring context menus, downloads observer, message router |
| rhwp-firefox/README.md | Build/load instructions and Firefox-specific notes |
| .gitignore | Ignores Node modules and Firefox build output |
Files not reviewed (1)
- rhwp-firefox/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Base64 인코딩 | ||
| let binary = ''; | ||
| for (let i = 0; i < data.length; i++) { | ||
| binary += String.fromCharCode(data[i]); | ||
| } | ||
| const base64 = btoa(binary); | ||
| const dataUri = `data:${mime};base64,${base64}`; |
There was a problem hiding this comment.
Base64 encoding is done by concatenating to a JS string in a byte-by-byte loop. For multi-megabyte PrvImage streams this is very slow and memory-heavy (quadratic-ish due to repeated string reallocations) and can cause extension jank. Consider switching to a chunked conversion (e.g., process in 32–64KB chunks) or a streaming Blob/FileReader approach.
| function prefetchThumbnails() { | ||
| setTimeout(() => { | ||
| const anchors = document.querySelectorAll('a[href]'); | ||
| for (const anchor of anchors) { | ||
| if (!isHwpLink(anchor)) continue; | ||
| if (anchor.getAttribute('data-hwp-thumbnail')) continue; | ||
| if (thumbnailCache.has(anchor.href)) continue; | ||
| prefetchQueue.push(anchor.href); | ||
| } | ||
| prefetchQueue = [...new Set(prefetchQueue)]; | ||
| drainPrefetchQueue(); | ||
| }, 1000); |
There was a problem hiding this comment.
The automatic thumbnail prefetch queues every detected HWP/HWPX link and triggers background fetches under <all_urls> host permissions. A malicious page can abuse this to make the extension request arbitrary internal/network URLs (SSRF-style) and then read the resulting data URI from the injected hover card DOM. Consider restricting prefetch to same-origin links (or disabling prefetch by default / gating behind explicit user action) and rejecting non-http(s) URLs.
| browser.runtime.sendMessage({ type: 'extract-thumbnail', url: anchor.href }) | ||
| .then((response) => { | ||
| if (response?.dataUri) { | ||
| thumbnailCache.set(anchor.href, response); | ||
| if (activeCard === card) { | ||
| const thumbDiv = card.querySelector('.rhwp-thumb-loading'); | ||
| if (thumbDiv) insertThumbnailImg(thumbDiv, response.dataUri); | ||
| } |
There was a problem hiding this comment.
loadThumbnail sends an 'extract-thumbnail' message for anchor.href without any origin/scheme constraints. Since the resulting data URI is rendered into the page DOM, this can be used to exfiltrate fetched content to the page if the extension is tricked into fetching a sensitive URL. Consider adding URL validation here (e.g., require http(s) and same-origin with the current document) before requesting extraction.
| browser.runtime.onMessage.addListener((message, sender) => { | ||
| const handler = messageHandlers[message?.type]; | ||
| if (!handler) return undefined; | ||
|
|
||
| return Promise.resolve(handler(message, sender)) | ||
| .catch((err) => ({ error: err.message || String(err) })); | ||
| }); | ||
| } | ||
|
|
||
| const messageHandlers = { | ||
| 'open-hwp': (message) => { | ||
| openViewer({ url: message.url, filename: message.filename }); | ||
| return { ok: true }; | ||
| }, | ||
|
|
||
| 'fetch-file': async (message) => { | ||
| const response = await fetch(message.url); | ||
| if (!response.ok) { | ||
| return { error: `HTTP ${response.status}: ${response.statusText}` }; | ||
| } | ||
|
|
||
| const buffer = await response.arrayBuffer(); | ||
| return { data: Array.from(new Uint8Array(buffer)) }; | ||
| }, |
There was a problem hiding this comment.
This message router trusts any sender and allows fetching arbitrary URLs via 'fetch-file' and 'extract-thumbnail' under <all_urls> host permissions. The repo already has a sender validation helper (rhwp-shared/security/sender-validator.js) used by the Safari build; consider applying similar sender checks here (e.g., only allow fetch-file from internal viewer pages, and strongly constrain/validate URLs for extract-thumbnail).
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@ivLis-Studio 님, Firefox 확장 기여 의지에 진심으로 감사드립니다. 현재 상황본 PR 의 변경 영역인 PR 의 base 가
결정본 PR 을 close 처리하겠습니다. 사유:
한 가지 안내 — 우리 측 책임PR 이
이 부분은 우리 측에서 README 에 base=devel 안내 추가 로 개선 후속 처리하겠습니다. 향후 기여 환영Firefox 확장 영역에 다음과 같은 후속 기여 환영합니다:
기여 시 다시 한 번 기여 의지에 감사드립니다. |
PR #330 (@ivLis-Studio Add Firefox Extension) 정중한 close 처리: - 우리 측 rhwp-firefox/ v0.2.1 가 이미 devel 에 존재 + AMO 제출 검토 중 - 16 파일 모두 동일 경로 충돌 + AMO 전제 조건 (gecko id, _locales, PRIVACY.md) 누락 후속 개선: - README.md / README_EN.md 의 Contributing 섹션 강화 - PR base 는 devel (main 아님) 명시 - 이슈/PR 사전 확인 안내 - 이슈 close 는 메인테이너 안내 - AMO 워닝 feedback 문서 commit (별도 task 후보) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
아하 그랬군요. |
Summary
rhwp-firefox.Validation
npm run checkinrhwp-firefoxnpm run buildinrhwp-firefox