diff --git a/client/src/pages/ExtensionAuth.tsx b/client/src/pages/ExtensionAuth.tsx index c7961f0..66c7360 100644 --- a/client/src/pages/ExtensionAuth.tsx +++ b/client/src/pages/ExtensionAuth.tsx @@ -9,7 +9,7 @@ export default function ExtensionAuth() { const [error, setError] = useState(null); useEffect(() => { - if (!user || tokenSent) return; + if (!user || tokenSent || error) return; (async () => { try { @@ -35,7 +35,7 @@ export default function ExtensionAuth() { setError("Something went wrong. Please try again."); } })(); - }, [user, tokenSent, error]); + }, [user, tokenSent]); if (isLoading) { return ( diff --git a/extension/fetchthechange-extension.zip b/extension/fetchthechange-extension.zip index cc406a6..ad6dcb9 100644 Binary files a/extension/fetchthechange-extension.zip and b/extension/fetchthechange-extension.zip differ diff --git a/extension/manifest.json b/extension/manifest.json index f4afc51..40e1f62 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "FetchTheChange", "description": "Track any element on any web page for changes. Get notified when prices drop, stock updates, or content changes.", - "version": "1.0.2", + "version": "1.0.3", "permissions": ["storage", "activeTab", "scripting", "tabs"], "host_permissions": ["https://ftc.bd73.com/*"], "background": { diff --git a/extension/src/popup/popup.ts b/extension/src/popup/popup.ts index d3b036e..f1f65af 100644 --- a/extension/src/popup/popup.ts +++ b/extension/src/popup/popup.ts @@ -1,5 +1,6 @@ import { BASE_URL, MSG } from "../shared/constants"; import { getToken, clearToken, isTokenValid } from "../auth/token"; +import { escapeAttr, sanitizeTier } from "./utils"; // ────────────────────────────────────────────────────────────────── // State @@ -39,6 +40,7 @@ let userInfo: UserInfo | null = null; let selection: Selection | null = null; let candidates: Candidate[] = []; let currentTabUrl = ""; +let currentTabTitle = ""; let currentTabId = 0; let errorMessage = ""; let createdMonitorName = ""; @@ -57,6 +59,7 @@ async function init(): Promise { const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); if (tab) { currentTabUrl = tab.url || ""; + currentTabTitle = tab.title || ""; currentTabId = tab.id || 0; } @@ -308,7 +311,7 @@ function renderAuthenticated(): void { selector: c.selector, currentValue: c.text, url: currentTabUrl, - pageTitle: document.title, + pageTitle: currentTabTitle, }; state = "confirm"; render(); @@ -538,14 +541,6 @@ function escapeHtml(str: string): string { return div.innerHTML; } -function escapeAttr(str: string): string { - return str.replace(/"/g, """).replace(/'/g, "'").replace(//g, ">"); -} - -const KNOWN_TIERS = ["free", "pro", "power"]; -function sanitizeTier(tier: string): string { - return KNOWN_TIERS.includes(tier) ? tier : "free"; -} // ────────────────────────────────────────────────────────────────── // Start diff --git a/extension/src/popup/utils.test.ts b/extension/src/popup/utils.test.ts new file mode 100644 index 0000000..e3d1432 --- /dev/null +++ b/extension/src/popup/utils.test.ts @@ -0,0 +1,53 @@ +import { describe, it, expect } from "vitest"; +import { escapeAttr, sanitizeTier } from "./utils"; + +describe("escapeAttr", () => { + it("escapes ampersand before other entities", () => { + expect(escapeAttr("A & B")).toBe("A & B"); + }); + + it("escapes double quotes", () => { + expect(escapeAttr('say "hello"')).toBe("say "hello""); + }); + + it("escapes single quotes", () => { + expect(escapeAttr("it's")).toBe("it's"); + }); + + it("escapes angle brackets", () => { + expect(escapeAttr("