Skip to content

Commit beb74f1

Browse files
authored
chore: optimize devtool tab connect (#279)
1 parent 68b4004 commit beb74f1

File tree

4 files changed

+40
-54
lines changed

4 files changed

+40
-54
lines changed

packages/visualizer/src/component/playground-component.tsx

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,8 @@ const serverLaunchTip = (
157157
);
158158

159159
// remember to destroy the agent when the tab is destroyed: agent.page.destroy()
160-
export const extensionAgentForTabId = (getTabId: () => number) => {
161-
if (!getTabId()) {
162-
return null;
163-
}
164-
const page = new ChromeExtensionProxyPage(getTabId);
160+
export const extensionAgentForTabId = (trackingActiveTab: () => boolean) => {
161+
const page = new ChromeExtensionProxyPage(trackingActiveTab);
165162
return new ChromeExtensionProxyPageAgent(page);
166163
};
167164

@@ -171,7 +168,9 @@ export function Playground({
171168
showContextPreview = true,
172169
dryMode = false,
173170
}: {
174-
getAgent: () => StaticPageAgent | ChromeExtensionProxyPageAgent | null;
171+
getAgent: (
172+
trackingActiveTab: () => boolean,
173+
) => StaticPageAgent | ChromeExtensionProxyPageAgent | null;
175174
hideLogo?: boolean;
176175
showContextPreview?: boolean;
177176
dryMode?: boolean;
@@ -195,6 +194,13 @@ export function Playground({
195194
const [verticalMode, setVerticalMode] = useState(false);
196195

197196
const { tabId } = useChromeTabInfo();
197+
const tabActiveRef = useRef<boolean>(true);
198+
199+
useEffect(() => {
200+
if (tabId) {
201+
tabActiveRef.current = trackingActiveTab;
202+
}
203+
}, [trackingActiveTab]);
198204

199205
// if the screen is narrow, we use vertical mode
200206
useEffect(() => {
@@ -226,7 +232,7 @@ export function Playground({
226232
if (uiContextPreview) return;
227233
if (!showContextPreview) return;
228234

229-
getAgent()
235+
getAgent(() => tabActiveRef.current)
230236
?.getUIContext()
231237
.then((context) => {
232238
setUiContextPreview(context);
@@ -289,7 +295,7 @@ export function Playground({
289295
error: null,
290296
};
291297

292-
const activeAgent = getAgent();
298+
const activeAgent = getAgent(() => tabActiveRef.current);
293299
try {
294300
if (!activeAgent) {
295301
throw new Error('No agent found');

packages/visualizer/src/extension/popup.tsx

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,8 @@ declare const __VERSION__: string;
2323

2424
function PlaygroundPopup() {
2525
const extensionVersion = getExtensionVersion();
26-
const { tabId } = useChromeTabInfo();
27-
const tabIdRef = useRef<number | null>(null);
2826
const { popupTab, setPopupTab, trackingActiveTab } = useEnvConfig();
2927

30-
useEffect(() => {
31-
if (tabId) {
32-
tabIdRef.current = tabId;
33-
}
34-
}, [tabId]);
35-
3628
const items = [
3729
{
3830
key: 'playground',
@@ -42,13 +34,8 @@ function PlaygroundPopup() {
4234
<div className="popup-playground-container">
4335
<Playground
4436
hideLogo
45-
getAgent={() => {
46-
return extensionAgentForTabId(() => {
47-
if (trackingActiveTab) {
48-
return tabIdRef.current || 0;
49-
}
50-
return tabId || 0;
51-
});
37+
getAgent={(trackingActiveTab: () => boolean) => {
38+
return extensionAgentForTabId(trackingActiveTab);
5239
}}
5340
showContextPreview={false}
5441
/>

packages/web-integration/src/bridge-mode/page-browser-side.ts

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class ChromeExtensionPageBrowserSide extends ChromeExtensionProxyPage {
2121
type: 'log' | 'status',
2222
) => void = () => {},
2323
) {
24-
super(() => 0);
24+
super(() => true);
2525
}
2626

2727
private async setupBridgeClient() {
@@ -44,7 +44,8 @@ export class ChromeExtensionPageBrowserSide extends ChromeExtensionProxyPage {
4444
return this.onLogMessage(args[0] as string, 'status');
4545
}
4646

47-
if (!this.getTabId || this.getTabId() === 0) {
47+
const tabId = await this.getTabId();
48+
if (!tabId || tabId === 0) {
4849
throw new Error('no tab is connected');
4950
}
5051

@@ -93,31 +94,19 @@ export class ChromeExtensionPageBrowserSide extends ChromeExtensionProxyPage {
9394
}
9495

9596
public async connectNewTabWithUrl(url: string) {
96-
assert(url, 'url is required to create a new tab');
97-
if (this.getTabId()) {
98-
throw new Error('tab is already connected');
99-
}
100-
10197
const tab = await chrome.tabs.create({ url });
10298
const tabId = tab.id;
10399
assert(tabId, 'failed to get tabId after creating a new tab');
104-
this.getTabId = () => tabId;
105100

106101
// new tab
107102
this.onLogMessage(`Creating new tab: ${url}`, 'log');
108103
}
109104

110105
public async connectCurrentTab() {
111-
if (this.getTabId()) {
112-
throw new Error(
113-
`already connected with tab id ${this.getTabId()}, cannot reconnect`,
114-
);
115-
}
116106
const tabs = await chrome.tabs.query({ active: true, currentWindow: true });
117107
console.log('current tab', tabs);
118108
const tabId = tabs[0]?.id;
119109
assert(tabId, 'failed to get tabId');
120-
this.getTabId = () => tabId;
121110

122111
this.onLogMessage(`Connected to current tab: ${tabs[0]?.url}`, 'log');
123112
}
@@ -129,6 +118,5 @@ export class ChromeExtensionPageBrowserSide extends ChromeExtensionProxyPage {
129118
this.onDisconnect();
130119
}
131120
super.destroy();
132-
this.getTabId = () => 0;
133121
}
134122
}

packages/web-integration/src/chrome-extension/page.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,28 @@ function sleep(ms: number) {
2525
export default class ChromeExtensionProxyPage implements AbstractPage {
2626
pageType = 'chrome-extension-proxy';
2727

28-
public getTabId: () => number;
28+
public trackingActiveTab: () => boolean;
2929

3030
private viewportSize?: Size;
3131

32-
private debuggerAttached = false;
32+
private activeTabId: number | null = null;
3333

3434
private attachingDebugger: Promise<void> | null = null;
3535

36-
constructor(getTabId: () => number) {
37-
this.getTabId = getTabId;
36+
constructor(trackingActiveTab: () => boolean) {
37+
this.trackingActiveTab = trackingActiveTab;
38+
}
39+
40+
public async getTabId() {
41+
const trackingActiveTab = this.trackingActiveTab();
42+
if (this.activeTabId && !trackingActiveTab) {
43+
return this.activeTabId;
44+
}
45+
const tabId = await chrome.tabs
46+
.query({ active: true, currentWindow: true })
47+
.then((tabs) => tabs[0]?.id);
48+
this.activeTabId = tabId || 0;
49+
return this.activeTabId;
3850
}
3951

4052
private async attachDebugger() {
@@ -54,7 +66,7 @@ export default class ChromeExtensionProxyPage implements AbstractPage {
5466
}
5567

5668
try {
57-
const currentTabId = this.getTabId();
69+
const currentTabId = await this.getTabId();
5870
// check if debugger is already attached to the tab
5971
const targets = await chrome.debugger.getTargets();
6072
const target = targets.find(
@@ -63,16 +75,8 @@ export default class ChromeExtensionProxyPage implements AbstractPage {
6375
if (!target) {
6476
// await chrome.debugger.detach({ tabId: currentTabId });
6577
await chrome.debugger.attach({ tabId: currentTabId }, '1.3');
66-
this.debuggerAttached = true;
6778
// Prevent AI logic from being influenced by changes in page width and height due to the debugger banner appearing on attach.
6879
await sleep(340);
69-
// listen to the debugger detach event
70-
chrome.debugger.onEvent.addListener((source, method, params) => {
71-
console.log('debugger event', source, method, params);
72-
if (method === 'Debugger.detached') {
73-
this.debuggerAttached = false;
74-
}
75-
});
7680
}
7781
} finally {
7882
this.attachingDebugger = null;
@@ -113,7 +117,6 @@ export default class ChromeExtensionProxyPage implements AbstractPage {
113117
chrome.debugger.detach({ tabId: tab.tabId });
114118
}
115119
}
116-
this.debuggerAttached = false;
117120
}
118121
}
119122

@@ -122,7 +125,7 @@ export default class ChromeExtensionProxyPage implements AbstractPage {
122125
params: RequestType,
123126
): Promise<ResponseType> {
124127
await this.attachDebugger();
125-
const tabId = this.getTabId();
128+
const tabId = await this.getTabId();
126129
this.enableWaterFlowAnimation(tabId);
127130
return (await chrome.debugger.sendCommand(
128131
{ tabId },
@@ -222,7 +225,8 @@ export default class ChromeExtensionProxyPage implements AbstractPage {
222225
}
223226

224227
async url() {
225-
const url = await chrome.tabs.get(this.getTabId()).then((tab) => tab.url);
228+
const tabId = await this.getTabId();
229+
const url = await chrome.tabs.get(tabId).then((tab) => tab.url);
226230
return url || '';
227231
}
228232

@@ -380,6 +384,7 @@ export default class ChromeExtensionProxyPage implements AbstractPage {
380384
};
381385

382386
async destroy(): Promise<void> {
387+
this.activeTabId = null;
383388
await this.detachDebugger();
384389
}
385390
}

0 commit comments

Comments
 (0)