aboutsummaryrefslogtreecommitdiff
path: root/extensions/chrome-profile-bridge/browser-extension/service_worker.js
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/chrome-profile-bridge/browser-extension/service_worker.js')
-rw-r--r--extensions/chrome-profile-bridge/browser-extension/service_worker.js43
1 files changed, 34 insertions, 9 deletions
diff --git a/extensions/chrome-profile-bridge/browser-extension/service_worker.js b/extensions/chrome-profile-bridge/browser-extension/service_worker.js
index 24caa58..68fe8c9 100644
--- a/extensions/chrome-profile-bridge/browser-extension/service_worker.js
+++ b/extensions/chrome-profile-bridge/browser-extension/service_worker.js
@@ -1232,11 +1232,16 @@ async function chromeInputFill(params) {
await cdp(tab.id, "Input.dispatchMouseEvent", { type: "mouseReleased", x: point.x, y: point.y, button: "left", buttons: 0, clickCount: i, pointerType: "mouse" });
await sleep(rng(20, 60));
}
- await contentEditableInTab(tab.id, params);
- // Delete selection.
- await cdp(tab.id, "Input.dispatchKeyEvent", { type: "keyDown", key: "Delete", code: "Delete", windowsVirtualKeyCode: 46 });
- await cdp(tab.id, "Input.dispatchKeyEvent", { type: "keyUp", key: "Delete", code: "Delete", windowsVirtualKeyCode: 46 });
- await sleep(rng(20, 60));
+ if (await contentEditableInTab(tab.id, params)) {
+ // The requested editor's whole contents are already selected; delete the selection.
+ await cdp(tab.id, "Input.dispatchKeyEvent", { type: "keyDown", key: "Delete", code: "Delete", windowsVirtualKeyCode: 46 });
+ await cdp(tab.id, "Input.dispatchKeyEvent", { type: "keyUp", key: "Delete", code: "Delete", windowsVirtualKeyCode: 46 });
+ await sleep(rng(20, 60));
+ } else {
+ // A triple-click selects only one line of a multi-line textarea. Select the whole value with
+ // Chrome's selectAll editing command before deleting.
+ await selectAllAndDelete(tab.id);
+ }
const text = String(params.text || "");
const typing = await typeTextInTab(tab.id, text, params.perCharacter);
if (params.submit) await chromeInputKey({ ...params, targetId: tab.id, key: "Enter" });
@@ -1706,10 +1711,14 @@ async function groupTab(tab, title, color) {
const groupTitle = cleanGroupTitle(title);
let groupId = tab.groupId;
if (typeof groupId !== "number" || groupId < 0) {
- const existing = await findGroupByTitle(tab.windowId, groupTitle);
+ // Some browsers omit windowId on freshly created tabs; read it back instead of guessing.
+ const windowId = typeof tab.windowId === "number" ? tab.windowId : (await chrome.tabs.get(tab.id).catch(() => null))?.windowId;
+ const existing = await findGroupByTitle(windowId, groupTitle);
+ // Without createProperties.windowId Chrome creates the group in the *current* (user's) window
+ // and moves the tab there, pulling Pi's automation tab out of its own window as a hidden tab.
groupId = existing !== null
? await chrome.tabs.group({ groupId: existing, tabIds: [tab.id] })
- : await chrome.tabs.group({ tabIds: [tab.id] });
+ : await chrome.tabs.group(typeof windowId === "number" ? { tabIds: [tab.id], createProperties: { windowId } } : { tabIds: [tab.id] });
}
await chrome.tabGroups.update(groupId, { title: groupTitle, color: cleanGroupColor(color), collapsed: false });
const grouped = await chrome.tabs.get(tab.id);
@@ -1743,8 +1752,20 @@ async function dispatch(action, params) {
const existingGroup = await findGroupRecordByTitle(groupTitle);
const createParams = { url: params.url || "about:blank", active: foregroundRequested(params) };
if (existingGroup && typeof existingGroup.windowId === "number") createParams.windowId = existingGroup.windowId;
- const tab = await chrome.tabs.create(createParams);
- await trackSessionTab(sessionKeyOf(params), tab.id, true);
+ // Register the creation as in flight until the tab is tracked, so early capture (which only
+ // runs in tracked tabs) waits for it instead of skipping the new tab's first page load.
+ const creation = (async () => {
+ const created = await chrome.tabs.create(createParams);
+ await trackSessionTab(sessionKeyOf(params), created.id, true);
+ return created;
+ })();
+ pendingTabCreations.add(creation);
+ let tab;
+ try {
+ tab = await creation;
+ } finally {
+ pendingTabCreations.delete(creation);
+ }
try {
await bringToFront(tab, params);
const grouped = await groupTab(tab, groupTitle, params.groupColor);
@@ -2298,8 +2319,12 @@ async function unregisterInitScript(tabId) {
// console messages, errors, and network requests that fire during page load, before chrome_snapshot
// or chrome_evaluate install the instrumentation normally. installEarlyCapture sets __piChromeWrapped
// flags so the post-hoc installPiChromeInstrumentation() call is idempotent.
+const pendingTabCreations = new Set(); // in-flight Pi tab creations, resolved once tracked
+
async function isPiTrackedTab(tabId) {
await Promise.all([hydrateAutomationTargets(), hydrateSessionTabs()]);
+ // A tab Pi is creating right now can commit its first page before tab.new has tracked it.
+ if (pendingTabCreations.size) await Promise.allSettled([...pendingTabCreations]);
if (isPiChromeOwnedTarget(tabId)) return true;
for (const tabs of sessionTabs.values()) if (tabs.has(tabId)) return true;
return false;