diff --git a/extension/background.js b/extension/background.js
index 9b9217b..b9a256a 100644
--- a/extension/background.js
+++ b/extension/background.js
@@ -8,10 +8,6 @@
const DEFAULTS = {
apiBase: 'http://localhost:3000',
pollSeconds: 3,
- // Chrome match pattern, e.g. "https://*.tradovate.com/*". Empty = whichever
- // tab is active in the last focused window — which would mean scraping your
- // banking or email tab if you switched to one. Default it to the broker.
- targetUrlPattern: 'https://*.tradeify.co/*',
// Optional CSS selector — matching elements get their on-screen position
// measured alongside the HTML.
elementSelector: '',
@@ -97,22 +93,27 @@ function pageCapture(selector) {
// ── Capture pipeline ────────────────────────────────────────────────────────
-async function pickTab(cfg) {
- if (cfg.targetUrlPattern) {
- try {
- const tabs = await chrome.tabs.query({ url: cfg.targetUrlPattern });
- return tabs.find((t) => /^https?:/.test(t.url || ''));
- } catch {
- throw new Error(`Invalid target URL pattern: ${cfg.targetUrlPattern}`);
- }
- }
+/** The sites this extension is allowed to touch, taken from the manifest rather
+ * than from a setting.
+ *
+ * These are the same hosts host_permissions grants, so they cannot drift out of
+ * sync with what the extension can actually read, and adding a firm — which
+ * means adding its host to the manifest anyway — scopes capture automatically.
+ * localhost is filtered out: that is the dashboard, and capturing it would just
+ * mirror our own output back. */
+function firmPatterns() {
+ return chrome.runtime.getManifest().host_permissions
+ .filter((p) => !/\/\/(localhost|127\.0\.0\.1)/.test(p));
+}
- const [tab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true });
- // chrome://, about:, the Web Store and PDF viewers can't be scripted.
- if (!tab || !/^https?:/.test(tab.url || '')) return undefined;
- // Skip the dashboard itself, otherwise it just captures its own output.
- if (tab.url.startsWith(cfg.apiBase)) return undefined;
- return tab;
+async function pickTab(cfg) {
+ const tabs = (await chrome.tabs.query({ url: firmPatterns() }))
+ .filter((t) => /^https?:/.test(t.url || ''));
+ if (tabs.length === 0) return undefined;
+
+ // Prefer the one being looked at, so with two firms open the capture follows
+ // attention rather than tab order.
+ return tabs.find((t) => t.active) ?? tabs[0];
}
async function captureAndSend(cfg) {
@@ -245,7 +246,9 @@ function waitForTabLoad(tabId, timeoutMs = 15000) {
}
async function resolveLocateTab(cfg, request) {
- const pattern = request.urlPattern || cfg.targetUrlPattern;
+ // Every step carries its firm's pattern; the manifest hosts are the fallback
+ // for a bare request (the CLI's locate without --url).
+ const pattern = request.urlPattern || firmPatterns();
if (pattern) {
const tabs = await chrome.tabs.query({ url: pattern });
const tab = tabs.find((t) => /^https?:/.test(t.url || ''));
diff --git a/extension/manifest.json b/extension/manifest.json
index 1f240df..819cbe6 100644
--- a/extension/manifest.json
+++ b/extension/manifest.json
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "AutoFirmer Capture",
- "version": "0.5.0",
+ "version": "0.6.0",
"description": "Scrapes the HTML of the target tab and posts it to the AutoFirmer dashboard while the AutoBuyer is switched on.",
"permissions": ["scripting", "tabs", "storage", "alarms"],
"host_permissions": [
diff --git a/extension/popup.html b/extension/popup.html
index 28d74f3..b9c758e 100644
--- a/extension/popup.html
+++ b/extension/popup.html
@@ -27,9 +27,6 @@
-
-
-
diff --git a/extension/popup.js b/extension/popup.js
index 35c7eaf..aaa593c 100644
--- a/extension/popup.js
+++ b/extension/popup.js
@@ -1,8 +1,7 @@
-const FIELDS = ['apiBase', 'pollSeconds', 'targetUrlPattern', 'elementSelector'];
+const FIELDS = ['apiBase', 'pollSeconds', 'elementSelector'];
const DEFAULTS = {
apiBase: 'http://localhost:3000',
pollSeconds: 3,
- targetUrlPattern: 'https://*.tradeify.co/*',
elementSelector: '',
};