Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions extension/dist/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ async function getAutomationWindow(workspace) {
}
}
const win = await chrome.windows.create({
url: "about:blank",
url: "data:text/html,<html></html>",
focused: false,
width: 1280,
height: 900,
Expand Down Expand Up @@ -309,6 +309,7 @@ async function resolveTabId(tabId, workspace) {
if (tabId !== void 0) {
try {
const tab = await chrome.tabs.get(tabId);
console.log(`[opencli] resolveTabId: explicit tabId=${tabId}, url=${tab.url}`);
if (isDebuggableUrl(tab.url)) return tabId;
console.warn(`[opencli] Tab ${tabId} URL is not debuggable (${tab.url}), re-resolving`);
} catch {
Expand All @@ -318,10 +319,14 @@ async function resolveTabId(tabId, workspace) {
const windowId = await getAutomationWindow(workspace);
const tabs = await chrome.tabs.query({ windowId });
const debuggableTab = tabs.find((t) => t.id && isDebuggableUrl(t.url));
if (debuggableTab?.id) return debuggableTab.id;
if (debuggableTab?.id) {
console.log(`[opencli] resolveTabId: found debuggable tab ${debuggableTab.id} (${debuggableTab.url})`);
return debuggableTab.id;
}
console.warn(`[opencli] resolveTabId: no debuggable tabs found, tabs: ${tabs.map((t) => `${t.id}=${t.url}`).join(", ")}`);
const reuseTab = tabs.find((t) => t.id);
if (reuseTab?.id) {
await chrome.tabs.update(reuseTab.id, { url: "about:blank" });
await chrome.tabs.update(reuseTab.id, { url: "data:text/html,<html></html>" });
await new Promise((resolve) => setTimeout(resolve, 300));
try {
const updated = await chrome.tabs.get(reuseTab.id);
Expand All @@ -335,7 +340,7 @@ async function resolveTabId(tabId, workspace) {
} catch {
}
}
const newTab = await chrome.tabs.create({ windowId, url: "about:blank", active: true });
const newTab = await chrome.tabs.create({ windowId, url: "data:text/html,<html></html>", active: true });
if (!newTab.id) throw new Error("Failed to create tab in automation window");
return newTab.id;
}
Expand Down Expand Up @@ -423,7 +428,7 @@ async function handleTabs(cmd, workspace) {
}
case "new": {
const windowId = await getAutomationWindow(workspace);
const tab = await chrome.tabs.create({ windowId, url: cmd.url ?? "about:blank", active: true });
const tab = await chrome.tabs.create({ windowId, url: cmd.url ?? "data:text/html,<html></html>", active: true });
return { id: cmd.id, ok: true, data: { tabId: tab.id, url: tab.url } };
}
case "close": {
Expand Down
2 changes: 1 addition & 1 deletion extension/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "OpenCLI",
"version": "0.2.0",
"version": "1.2.4",
"description": "Bridge between opencli CLI and your browser — execute commands, read cookies, manage tabs.",
"permissions": [
"debugger",
Expand Down
2 changes: 1 addition & 1 deletion extension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "opencli-extension",
"version": "0.2.0",
"version": "1.2.4",
"private": true,
"type": "module",
"scripts": {
Expand Down
18 changes: 12 additions & 6 deletions extension/src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,10 @@ async function getAutomationWindow(workspace: string): Promise<number> {
}
}

// Create a new window with about:blank (not chrome://newtab which blocks scripting)
// Create a new window with a data: URI that New Tab Override extensions cannot intercept.
// Using about:blank would be hijacked by extensions like "New Tab Override".
const win = await chrome.windows.create({
url: 'about:blank',
url: 'data:text/html,<html></html>',
focused: false,
width: 1280,
height: 900,
Expand Down Expand Up @@ -244,6 +245,7 @@ async function resolveTabId(tabId: number | undefined, workspace: string): Promi
if (tabId !== undefined) {
try {
const tab = await chrome.tabs.get(tabId);
console.log(`[opencli] resolveTabId: explicit tabId=${tabId}, url=${tab.url}`);
if (isDebuggableUrl(tab.url)) return tabId;
// Tab exists but URL is not debuggable — fall through to auto-resolve
console.warn(`[opencli] Tab ${tabId} URL is not debuggable (${tab.url}), re-resolving`);
Expand All @@ -259,15 +261,19 @@ async function resolveTabId(tabId: number | undefined, workspace: string): Promi
// Prefer an existing debuggable tab (about:blank, http://, https://, etc.)
const tabs = await chrome.tabs.query({ windowId });
const debuggableTab = tabs.find(t => t.id && isDebuggableUrl(t.url));
if (debuggableTab?.id) return debuggableTab.id;
if (debuggableTab?.id) {
console.log(`[opencli] resolveTabId: found debuggable tab ${debuggableTab.id} (${debuggableTab.url})`);
return debuggableTab.id;
}
console.warn(`[opencli] resolveTabId: no debuggable tabs found, tabs: ${tabs.map(t => `${t.id}=${t.url}`).join(', ')}`);

// No debuggable tab found — this typically happens when a "New Tab Override"
// extension replaces about:blank with a chrome-extension:// page.
// Reuse the first existing tab by navigating it to about:blank (avoids
// accumulating orphan tabs if chrome.tabs.create is also intercepted).
const reuseTab = tabs.find(t => t.id);
if (reuseTab?.id) {
await chrome.tabs.update(reuseTab.id, { url: 'about:blank' });
await chrome.tabs.update(reuseTab.id, { url: 'data:text/html,<html></html>' });
// Wait for the navigation to take effect
await new Promise(resolve => setTimeout(resolve, 300));
// Verify the URL is actually debuggable (New Tab Override may have intercepted)
Expand All @@ -288,7 +294,7 @@ async function resolveTabId(tabId: number | undefined, workspace: string): Promi
}

// Window has no debuggable tabs — create one
const newTab = await chrome.tabs.create({ windowId, url: 'about:blank', active: true });
const newTab = await chrome.tabs.create({ windowId, url: 'data:text/html,<html></html>', active: true });
if (!newTab.id) throw new Error('Failed to create tab in automation window');
return newTab.id;
}
Expand Down Expand Up @@ -397,7 +403,7 @@ async function handleTabs(cmd: Command, workspace: string): Promise<Result> {
}
case 'new': {
const windowId = await getAutomationWindow(workspace);
const tab = await chrome.tabs.create({ windowId, url: cmd.url ?? 'about:blank', active: true });
const tab = await chrome.tabs.create({ windowId, url: cmd.url ?? 'data:text/html,<html></html>', active: true });
return { id: cmd.id, ok: true, data: { tabId: tab.id, url: tab.url } };
}
case 'close': {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jackwener/opencli",
"version": "1.2.3",
"version": "1.2.4",
"publishConfig": {
"access": "public"
},
Expand Down
Loading