feat: add option to add custom blocked domains#41
feat: add option to add custom blocked domains#41Justin24506 wants to merge 3 commits intoShantanugupta43:mainfrom
Conversation
|
Hey I am curious what you are working on. If possible can you also include the description in issues tab? Cheers |
|
#42 Done. |
There was a problem hiding this comment.
Pull request overview
Adds an initial “custom blocked domains” feature to the extension so users can configure domains where suggestions should be disabled.
Changes:
- Adds a “Blocked Sites” UI in the popup settings with tag-style add/remove behavior.
- Persists
blockedDomainsinto extension config and returns it viagetConfig. - Updates the content script to disable itself on blocked domains (now intended to be configurable).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| src/popup/popup.js | Adds blocked domain input handling, domain sanitization, and tag rendering; saves blockedDomains into config. |
| src/popup/popup.html | Adds the “Blocked Sites” section and container markup in Settings. |
| src/popup/popup.css | Adds styling for the blocked domain tags/input container. |
| src/content/content-script.js | Attempts to load blocked domains from config and short-circuit initialization on blocked sites. |
| src/config/config-manager.js | Adds blockedDomains to stored config initialization defaults. |
| src/background/service-worker.js | Exposes blockedDomains via getConfig response. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/content/content-script.js
Outdated
| import configManager from "../config/config-manager.js"; | ||
|
|
There was a problem hiding this comment.
import configManager ... will throw in a Manifest V3 content script unless the content script is loaded as an ES module (otherwise you get “Cannot use import statement outside a module”). Either update the manifest content_scripts entry to load this file as a module, or remove the import and fetch blockedDomains via chrome.runtime.sendMessage / chrome.storage directly.
| import configManager from "../config/config-manager.js"; | |
| const configManager = { | |
| async get(key, defaultValue = null) { | |
| try { | |
| const syncResult = await chrome.storage.sync.get(key); | |
| if (syncResult[key] !== undefined) { | |
| return syncResult[key]; | |
| } | |
| const localResult = await chrome.storage.local.get(key); | |
| if (localResult[key] !== undefined) { | |
| return localResult[key]; | |
| } | |
| } catch (error) { | |
| console.warn("Failed to read config from extension storage:", error); | |
| } | |
| return defaultValue; | |
| }, | |
| async getBlockedDomains() { | |
| const blockedDomains = await this.get("blockedDomains", []); | |
| return Array.isArray(blockedDomains) ? blockedDomains : []; | |
| }, | |
| }; |
| return; | ||
| async function initialize() { | ||
| try { | ||
| const blockedDomains = (await configManager.get("blockedDomains")) || []; |
There was a problem hiding this comment.
Blocked domains are read via configManager.get("blockedDomains") without calling await configManager.initialize(). Since get() just reads this.config and this.config is null until initialized, this will always fall back to [] and the blocking feature won’t work. Initialize the config manager first (and you can drop the unnecessary await on get).
| const blockedDomains = (await configManager.get("blockedDomains")) || []; | |
| await configManager.initialize(); | |
| const blockedDomains = configManager.get("blockedDomains") || []; |
src/content/content-script.js
Outdated
| if (!Array.isArray(blockedDomains)) return false; | ||
| const host = window.location.hostname.toLowerCase(); | ||
| return BLOCKED_DOMAINS.some(domain => host.includes(domain)); | ||
| return blockedDomains.some((domain) => host.includes(domain)); |
There was a problem hiding this comment.
host.includes(domain) will produce false positives (e.g. blocking in.com blocks linkedin.com, blocking linkedin.com blocks notlinkedin.com). Domain matching should be based on exact host match or a subdomain suffix check (e.g. host === domain || host.endsWith('.' + domain)).
| return blockedDomains.some((domain) => host.includes(domain)); | |
| return blockedDomains.some((domain) => { | |
| if (typeof domain !== "string") return false; | |
| const normalizedDomain = domain.trim().toLowerCase().replace(/^\.+/, ""); | |
| if (!normalizedDomain) return false; | |
| return ( | |
| host === normalizedDomain || host.endsWith(`.${normalizedDomain}`) | |
| ); | |
| }); |
src/popup/popup.js
Outdated
| derivationEl.className = 'suggestion-derivation'; | ||
| const derivationEl = document.createElement("div"); | ||
| derivationEl.className = "suggestion-derivation"; | ||
| derivationEl.innerHTML = `<strong>Why:</strong> ${derivation}`; |
There was a problem hiding this comment.
derivationEl.innerHTML = ... ${derivation} injects untrusted LLM-provided text into the extension popup as HTML, which is an XSS vector (LLM output can contain tags). Prefer setting textContent for the derivation portion (or sanitize/escape before assigning to innerHTML).
| derivationEl.innerHTML = `<strong>Why:</strong> ${derivation}`; | |
| const derivationLabelEl = document.createElement("strong"); | |
| derivationLabelEl.textContent = "Why:"; | |
| derivationEl.appendChild(derivationLabelEl); | |
| derivationEl.appendChild(document.createTextNode(` ${derivation}`)); |
| .tag { | ||
| background: var(--primary); | ||
| color: white; | ||
| padding: 4px 10px; | ||
| border-radius: 6px; | ||
| display: inline-flex; | ||
| align-items: center; | ||
| gap: 6px; | ||
| font-size: 13px; | ||
| font-weight: 500; | ||
| user-select: none; | ||
| animation: fadeIn 0.2s ease; | ||
| } |
There was a problem hiding this comment.
.tag uses animation: fadeIn 0.2s ease; but there is no @keyframes fadeIn defined in this stylesheet, so the animation won’t run (and can generate warnings in devtools). Define the keyframes or remove the animation reference.
|
I've made some fixes:
I'll now try to fix the errors pointed out by Copliot. |
- Replaced content script import with inline config to fix Manifest V3 module errors - Swapped .innerHTML for text nodes to prevent XSS in popup - Added aria-labels and focus outlines for better accessibility
|
Sorry for cluttering this up, didn't realize Copilot's automatic review was on. |
|
Since you did a draft PR, it triggered copilots auto reviewer. It doesn't trigger on default pull requests |
Foundation laid for custom blocked domains.
Need to
http:///https://from pasted URLsand more.