@@ -14,57 +14,111 @@ function debugLog(...args) {
14
14
class TabShareExtension {
15
15
constructor ( ) {
16
16
this . activeConnections = new Map ( ) ; // tabId -> connection info
17
- this . bridgeURL = 'ws://localhost:9223/extension' ; // Default bridge URL
18
17
19
- // Set up page action
20
- chrome . action . onClicked . addListener ( this . onPageActionClicked . bind ( this ) ) ;
18
+ // Remove page action click handler since we now use popup
21
19
chrome . tabs . onRemoved . addListener ( this . onTabRemoved . bind ( this ) ) ;
20
+
21
+ // Handle messages from popup
22
+ chrome . runtime . onMessage . addListener ( this . onMessage . bind ( this ) ) ;
23
+ }
24
+
25
+ /**
26
+ * Handle messages from popup
27
+ * @param {any } message
28
+ * @param {chrome.runtime.MessageSender } sender
29
+ * @param {Function } sendResponse
30
+ */
31
+ onMessage ( message , sender , sendResponse ) {
32
+ switch ( message . type ) {
33
+ case 'getStatus' :
34
+ this . getStatus ( message . tabId , sendResponse ) ;
35
+ return true ; // Will respond asynchronously
36
+
37
+ case 'connect' :
38
+ this . connectTab ( message . tabId , message . bridgeUrl ) . then (
39
+ ( ) => sendResponse ( { success : true } ) ,
40
+ ( error ) => sendResponse ( { success : false , error : error . message } )
41
+ ) ;
42
+ return true ; // Will respond asynchronously
43
+
44
+ case 'disconnect' :
45
+ this . disconnectTab ( message . tabId ) . then (
46
+ ( ) => sendResponse ( { success : true } ) ,
47
+ ( error ) => sendResponse ( { success : false , error : error . message } )
48
+ ) ;
49
+ return true ; // Will respond asynchronously
50
+ }
51
+ return false ;
22
52
}
23
53
24
54
/**
25
- * Handle page action click - "share" the tab with MCP server
26
- * @param {chrome.tabs.Tab } tab
55
+ * Get connection status for popup
56
+ * @param {number } requestedTabId
57
+ * @param {Function } sendResponse
27
58
*/
28
- async onPageActionClicked ( tab ) {
29
- if ( ! tab . id ) return ;
30
-
31
- if ( this . activeConnections . has ( tab . id ) ) {
32
- // Already connected - disconnect
33
- await this . disconnectTab ( tab . id ) ;
34
- chrome . action . setBadgeText ( { tabId : tab . id , text : '' } ) ;
35
- chrome . action . setTitle ( { tabId : tab . id , title : 'Share tab with Playwright MCP' } ) ;
59
+ getStatus ( requestedTabId , sendResponse ) {
60
+ const isConnected = this . activeConnections . size > 0 ;
61
+ let activeTabId = null ;
62
+ let activeTabInfo = null ;
63
+
64
+ if ( isConnected ) {
65
+ const [ tabId , connection ] = this . activeConnections . entries ( ) . next ( ) . value ;
66
+ activeTabId = tabId ;
67
+
68
+ // Get tab info
69
+ chrome . tabs . get ( tabId , ( tab ) => {
70
+ if ( chrome . runtime . lastError ) {
71
+ sendResponse ( {
72
+ isConnected : false ,
73
+ error : 'Active tab not found'
74
+ } ) ;
75
+ } else {
76
+ sendResponse ( {
77
+ isConnected : true ,
78
+ activeTabId,
79
+ activeTabInfo : {
80
+ title : tab . title ,
81
+ url : tab . url
82
+ }
83
+ } ) ;
84
+ }
85
+ } ) ;
36
86
} else {
37
- // Connect tab
38
- await this . connectTab ( tab . id ) ;
87
+ sendResponse ( {
88
+ isConnected : false ,
89
+ activeTabId : null ,
90
+ activeTabInfo : null
91
+ } ) ;
39
92
}
40
93
}
41
94
42
95
/**
43
96
* Connect a tab to the bridge server
44
97
* @param {number } tabId
98
+ * @param {string } bridgeUrl
45
99
*/
46
- async connectTab ( tabId ) {
100
+ async connectTab ( tabId , bridgeUrl ) {
47
101
try {
48
- debugLog ( `Connecting tab ${ tabId } to bridge` ) ;
102
+ debugLog ( `Connecting tab ${ tabId } to bridge at ${ bridgeUrl } ` ) ;
49
103
50
104
// Attach chrome debugger
51
105
const debuggee = { tabId } ;
52
106
await chrome . debugger . attach ( debuggee , '1.3' ) ;
53
107
54
108
if ( chrome . runtime . lastError )
55
109
throw new Error ( chrome . runtime . lastError . message ) ;
56
- const targetInfo = await chrome . debugger . sendCommand ( debuggee , 'Target.getTargetInfo' ) ;
110
+ const targetInfo = /** @type { any } */ ( await chrome . debugger . sendCommand ( debuggee , 'Target.getTargetInfo' ) ) ;
57
111
debugLog ( 'Target info:' , targetInfo ) ;
58
112
59
113
// Connect to bridge server
60
- const socket = new WebSocket ( this . bridgeURL ) ;
114
+ const socket = new WebSocket ( bridgeUrl ) ;
61
115
62
116
const connection = {
63
117
debuggee,
64
118
socket,
65
119
tabId,
66
- targetId : targetInfo . targetInfo . targetId ,
67
- browserContextId : targetInfo . targetInfo . browserContextId
120
+ targetId : targetInfo ? .targetInfo ? .targetId ,
121
+ browserContextId : targetInfo ? .targetInfo ? .browserContextId
68
122
} ;
69
123
70
124
await new Promise ( ( resolve , reject ) => {
@@ -76,7 +130,7 @@ class TabShareExtension {
76
130
tabId,
77
131
targetId : connection . targetId ,
78
132
browserContextId : connection . browserContextId ,
79
- targetInfo : targetInfo . targetInfo
133
+ targetInfo : targetInfo ? .targetInfo
80
134
} ) ) ;
81
135
resolve ( undefined ) ;
82
136
} ;
@@ -105,6 +159,8 @@ class TabShareExtension {
105
159
chrome . action . setBadgeText ( { tabId, text : '!' } ) ;
106
160
chrome . action . setBadgeBackgroundColor ( { tabId, color : '#F44336' } ) ;
107
161
chrome . action . setTitle ( { tabId, title : `Connection failed: ${ error . message } ` } ) ;
162
+
163
+ throw error ; // Re-throw for popup to handle
108
164
}
109
165
}
110
166
0 commit comments