@@ -49,6 +49,7 @@ enum DetachReason {
49
49
connectionDoneEvent,
50
50
devToolsTabClosed,
51
51
navigatedAwayFromApp,
52
+ staleDebugSession,
52
53
unknown;
53
54
54
55
factory DetachReason .fromString (String value) {
@@ -127,40 +128,60 @@ void attachDebugger(int dartAppTabId, {required Trigger trigger}) async {
127
128
);
128
129
}
129
130
130
- void detachDebugger (
131
+ Future < bool > detachDebugger (
131
132
int tabId, {
132
133
required TabType type,
133
134
required DetachReason reason,
134
135
}) async {
135
136
final debugSession = _debugSessionForTab (tabId, type: type);
136
- if (debugSession == null ) return ;
137
+ if (debugSession == null ) return false ;
137
138
final debuggee = Debuggee (tabId: debugSession.appTabId);
139
+ final completer = Completer <bool >();
138
140
chrome.debugger.detach (debuggee, allowInterop (() {
139
141
final error = chrome.runtime.lastError;
140
142
if (error != null ) {
141
143
debugWarn (
142
144
'Error detaching tab for reason: $reason . Error: ${error .message }' );
145
+ completer.complete (false );
143
146
} else {
144
147
_handleDebuggerDetach (debuggee, reason);
148
+ completer.complete (true );
145
149
}
146
150
}));
151
+ return completer.future;
152
+ }
153
+
154
+ bool isActiveDebugSession (int tabId) =>
155
+ _debugSessionForTab (tabId, type: TabType .dartApp) != null ;
156
+
157
+ Future <void > clearStaleDebugSession (int tabId) async {
158
+ final debugSession = _debugSessionForTab (tabId, type: TabType .dartApp);
159
+ if (debugSession != null ) {
160
+ await detachDebugger (
161
+ tabId,
162
+ type: TabType .dartApp,
163
+ reason: DetachReason .staleDebugSession,
164
+ );
165
+ } else {
166
+ await _removeDebugSessionDataInStorage (tabId);
167
+ }
147
168
}
148
169
149
170
void _registerDebugEventListeners () {
150
171
chrome.debugger.onEvent.addListener (allowInterop (_onDebuggerEvent));
151
- chrome.debugger.onDetach.addListener (allowInterop (
152
- (source, _) => _handleDebuggerDetach (
172
+ chrome.debugger.onDetach.addListener (allowInterop ((source, _) async {
173
+ await _handleDebuggerDetach (
153
174
source,
154
175
DetachReason .canceledByUser,
155
- ),
156
- ));
157
- chrome.tabs.onRemoved.addListener (allowInterop (
158
- (tabId, _) => detachDebugger (
176
+ );
177
+ } ));
178
+ chrome.tabs.onRemoved.addListener (allowInterop ((tabId, _) async {
179
+ await detachDebugger (
159
180
tabId,
160
181
type: TabType .devTools,
161
182
reason: DetachReason .devToolsTabClosed,
162
- ),
163
- ));
183
+ );
184
+ } ));
164
185
}
165
186
166
187
_enableExecutionContextReporting (int tabId) {
@@ -222,7 +243,7 @@ Future<void> _maybeConnectToDwds(int tabId, Object? params) async {
222
243
);
223
244
if (! connected) {
224
245
debugWarn ('Failed to connect to DWDS for $contextOrigin .' );
225
- _sendConnectFailureMessage (ConnectFailureReason .unknown,
246
+ await _sendConnectFailureMessage (ConnectFailureReason .unknown,
226
247
dartAppTabId: tabId);
227
248
}
228
249
}
@@ -247,16 +268,16 @@ Future<bool> _connectToDwds({
247
268
appTabId: dartAppTabId,
248
269
trigger: trigger,
249
270
onIncoming: (data) => _routeDwdsEvent (data, client, dartAppTabId),
250
- onDone: () {
251
- detachDebugger (
271
+ onDone: () async {
272
+ await detachDebugger (
252
273
dartAppTabId,
253
274
type: TabType .dartApp,
254
275
reason: DetachReason .connectionDoneEvent,
255
276
);
256
277
},
257
- onError: (err) {
278
+ onError: (err) async {
258
279
debugWarn ('Connection error: $err ' , verbose: true );
259
- detachDebugger (
280
+ await detachDebugger (
260
281
dartAppTabId,
261
282
type: TabType .dartApp,
262
283
reason: DetachReason .connectionErrorEvent,
@@ -377,24 +398,26 @@ void _openDevTools(String devToolsUri, {required int dartAppTabId}) async {
377
398
}
378
399
}
379
400
380
- void _handleDebuggerDetach (Debuggee source, DetachReason reason) async {
401
+ Future < void > _handleDebuggerDetach (Debuggee source, DetachReason reason) async {
381
402
final tabId = source.tabId;
382
403
debugLog (
383
404
'Debugger detached due to: $reason ' ,
384
405
verbose: true ,
385
406
prefix: '$tabId ' ,
386
407
);
387
408
final debugSession = _debugSessionForTab (tabId, type: TabType .dartApp);
388
- if (debugSession == null ) return ;
389
- debugLog ('Removing debug session...' );
390
- _removeDebugSession (debugSession);
391
- // Notify the extension panels that the debug session has ended:
392
- _sendStopDebuggingMessage (reason, dartAppTabId: source.tabId);
393
- // Remove the DevTools URI and encoded URI from storage:
394
- await removeStorageObject (type: StorageObject .devToolsUri, tabId: tabId);
395
- await removeStorageObject (type: StorageObject .encodedUri, tabId: tabId);
396
- // Maybe close the associated DevTools tab as well:
397
- final devToolsTabId = debugSession.devToolsTabId;
409
+ if (debugSession != null ) {
410
+ debugLog ('Removing debug session...' );
411
+ _removeDebugSession (debugSession);
412
+ // Notify the extension panels that the debug session has ended:
413
+ await _sendStopDebuggingMessage (reason, dartAppTabId: tabId);
414
+ // Maybe close the associated DevTools tab as well:
415
+ await _maybeCloseDevTools (debugSession.devToolsTabId);
416
+ }
417
+ await _removeDebugSessionDataInStorage (tabId);
418
+ }
419
+
420
+ Future <void > _maybeCloseDevTools (int ? devToolsTabId) async {
398
421
if (devToolsTabId == null ) return ;
399
422
final devToolsTab = await getTab (devToolsTabId);
400
423
if (devToolsTab != null ) {
@@ -403,6 +426,12 @@ void _handleDebuggerDetach(Debuggee source, DetachReason reason) async {
403
426
}
404
427
}
405
428
429
+ Future <void > _removeDebugSessionDataInStorage (int tabId) async {
430
+ // Remove the DevTools URI and encoded URI from storage:
431
+ await removeStorageObject (type: StorageObject .devToolsUri, tabId: tabId);
432
+ await removeStorageObject (type: StorageObject .encodedUri, tabId: tabId);
433
+ }
434
+
406
435
void _removeDebugSession (_DebugSession debugSession) {
407
436
// Note: package:sse will try to keep the connection alive, even after the
408
437
// client has been closed. Therefore the extension sends an event to notify
@@ -422,25 +451,25 @@ void _removeDebugSession(_DebugSession debugSession) {
422
451
}
423
452
}
424
453
425
- void _sendConnectFailureMessage (ConnectFailureReason reason,
454
+ Future < bool > _sendConnectFailureMessage (ConnectFailureReason reason,
426
455
{required int dartAppTabId}) async {
427
456
final json = jsonEncode (serializers.serialize (ConnectFailure ((b) => b
428
457
..tabId = dartAppTabId
429
458
..reason = reason.name)));
430
- sendRuntimeMessage (
459
+ return await sendRuntimeMessage (
431
460
type: MessageType .connectFailure,
432
461
body: json,
433
462
sender: Script .background,
434
463
recipient: Script .debuggerPanel);
435
464
}
436
465
437
- void _sendStopDebuggingMessage (DetachReason reason,
466
+ Future < bool > _sendStopDebuggingMessage (DetachReason reason,
438
467
{required int dartAppTabId}) async {
439
468
final json = jsonEncode (serializers.serialize (DebugStateChange ((b) => b
440
469
..tabId = dartAppTabId
441
470
..reason = reason.name
442
471
..newState = DebugStateChange .stopDebugging)));
443
- sendRuntimeMessage (
472
+ return await sendRuntimeMessage (
444
473
type: MessageType .debugStateChange,
445
474
body: json,
446
475
sender: Script .background,
@@ -478,7 +507,7 @@ Future<bool> _authenticateUser(int tabId) async {
478
507
tabId: tabId,
479
508
);
480
509
} else {
481
- _sendConnectFailureMessage (
510
+ await _sendConnectFailureMessage (
482
511
ConnectFailureReason .authentication,
483
512
dartAppTabId: tabId,
484
513
);
@@ -622,8 +651,20 @@ class _DebugSession {
622
651
}
623
652
624
653
void close () {
625
- _socketClient.close ();
626
- _batchSubscription.cancel ();
627
- _batchController.close ();
654
+ try {
655
+ _socketClient.close ();
656
+ } catch (error) {
657
+ debugError ('Error closing socket client: $error ' );
658
+ }
659
+ try {
660
+ _batchSubscription.cancel ();
661
+ } catch (error) {
662
+ debugError ('Error canceling batch subscription: $error ' );
663
+ }
664
+ try {
665
+ _batchController.close ();
666
+ } catch (error) {
667
+ debugError ('Error closing batch controller: $error ' );
668
+ }
628
669
}
629
670
}
0 commit comments