22// for details. All rights reserved. Use of this source code is governed by a
33// BSD-style license that can be found in the LICENSE file.
44
5- // @dart = 2.9
6-
75@JS ()
86library background;
97
@@ -12,6 +10,12 @@ import 'dart:convert';
1210import 'dart:html' ;
1311
1412import 'package:built_collection/built_collection.dart' ;
13+ // TODO(elliette): The format_and_analyze Github actions complains about this
14+ // import because it is looking for it in DWDS' pubspec, not in the extension's
15+ // pubspec. We should fix the Github action and / or unnest the extension from
16+ // the DWDS directory.
17+ // ignore: depend_on_referenced_packages
18+ import 'package:collection/collection.dart' show IterableExtension;
1519import 'package:dwds/data/devtools_request.dart' ;
1620import 'package:dwds/data/extension_request.dart' ;
1721import 'package:dwds/data/serializers.dart' ;
@@ -55,11 +59,11 @@ final _devToolsPanelsNotifier =
5559// Keeps track of the most recent Dart tab that was opened. This is a heuristic
5660// to let us guess which tab the user is trying to debug if they start debugging
5761// from the Chrome DevTools Dart panel (which doesn't have a tab ID).
58- Tab _mostRecentDartTab;
62+ Tab ? _mostRecentDartTab;
5963
6064// Keeps track of how debugging was triggered. This lets us know if we should
6165// open Dart DevTools in a new window/tab or embed it in Chrome DevTools.
62- DebuggerTrigger _debuggerTrigger;
66+ DebuggerTrigger ? _debuggerTrigger;
6367
6468class DebugSession {
6569 // The tab ID that contains the running Dart application.
@@ -69,7 +73,7 @@ class DebugSession {
6973 final String appId;
7074
7175 // The tab ID that contains the corresponding Dart DevTools.
72- int devtoolsTabId;
76+ int ? devtoolsTabId;
7377
7478 // Socket client for communication with dwds extension backend.
7579 final SocketClient _socketClient;
@@ -80,7 +84,7 @@ class DebugSession {
8084 // Collect events into batches to be send periodically to the server.
8185 final _batchController =
8286 BatchedStreamController <ExtensionEvent >(delay: _batchDelayMilliseconds);
83- StreamSubscription <List <ExtensionEvent >> _batchSubscription;
87+ late final StreamSubscription <List <ExtensionEvent >> _batchSubscription;
8488
8589 DebugSession (this ._socketClient, this .appTabId, this .appId) {
8690 // Collect extension events and send them periodically to the server.
@@ -107,10 +111,10 @@ class DebugSession {
107111
108112class DevToolsPanel {
109113 // The Dart app ID.
110- final String appId;
114+ final String ? appId;
111115
112116 // The Chrome DevTools panel ID.
113- String panelId;
117+ String ? panelId;
114118
115119 // The URI for the embedded Dart DevTools, or an empty string if the debugger
116120 // is disconnected.
@@ -213,7 +217,7 @@ void _startDebugging(DebuggerTrigger debuggerTrigger) {
213217 if (tabs.isNotEmpty) {
214218 attachDebuggerToTab (tabs.first as Tab );
215219 } else if (_mostRecentDartTab != null ) {
216- attachDebuggerToTab (_mostRecentDartTab);
220+ attachDebuggerToTab (_mostRecentDartTab! );
217221 } else {
218222 alert ('''
219223 Could not find a Dart app to start debugging.
@@ -235,8 +239,8 @@ void _attachDebuggerToTab(Tab currentTab) async {
235239 attach (Debuggee (tabId: currentTab.id), '1.3' , allowInterop (() async {
236240 if (lastError != null ) {
237241 String alertMessage;
238- if (lastError.message.contains ('Cannot access' ) ||
239- lastError.message.contains ('Cannot attach' )) {
242+ if (lastError! .message.contains ('Cannot access' ) ||
243+ lastError! .message.contains ('Cannot attach' )) {
240244 alertMessage = _notADartAppAlert;
241245 } else {
242246 alertMessage = 'DevTools is already opened on a different window.' ;
@@ -298,12 +302,12 @@ void _maybeAttachDebugSession(
298302 if (method != 'Runtime.executionContextCreated' ) return ;
299303
300304 final context = json.decode (stringify (params))['context' ];
301- final tab = _tabsToAttach.firstWhere ((tab) => tab.id == source.tabId,
302- orElse : () => null ) ;
303- if (tab != null ) {
305+ final tab = _tabsToAttach.firstWhereOrNull ((tab) => tab.id == source.tabId);
306+ final contextId = context[ 'id' ] as int ? ;
307+ if (tab != null && contextId != null ) {
304308 final launchInChromeDevTools =
305309 _debuggerTrigger == DebuggerTrigger .dartPanel;
306- if (await _tryAttach (context[ 'id' ] as int , tab, launchInChromeDevTools)) {
310+ if (await _tryAttach (contextId , tab, launchInChromeDevTools)) {
307311 _tabsToAttach.remove (tab);
308312 }
309313 }
@@ -322,9 +326,8 @@ void _removeAndDetachDebugSessionForTab(int tabId, _) {
322326// Tries to remove the debug session for the specified tab. If no session is
323327// found, returns -1. Otherwise returns the tab ID.
324328int _removeDebugSessionForTab (int tabId) {
325- final session = _debugSessions.firstWhere (
326- (session) => session.appTabId == tabId || session.devtoolsTabId == tabId,
327- orElse: () => null );
329+ final session = _debugSessions.firstWhereOrNull (
330+ (session) => session.appTabId == tabId || session.devtoolsTabId == tabId);
328331 if (session != null ) {
329332 // Note: package:sse will try to keep the connection alive, even after the
330333 // client has been closed. Therefore the extension sends an event to notify
@@ -435,23 +438,25 @@ Future<bool> _tryAttach(
435438 expression:
436439 '[\$ dartExtensionUri, \$ dartAppId, \$ dartAppInstanceId, window.\$ dwdsVersion]' ,
437440 returnByValue: true ,
438- contextId: contextId), allowInterop ((e) {
439- String extensionUri, appId, instanceId, dwdsVersion;
440- if (e.result.value == null ) {
441+ contextId: contextId), allowInterop ((evalResponse) {
442+ final value = evalResponse.result.value;
443+ final extensionUri = value? [0 ] as String ? ;
444+ final appId = value? [1 ] as String ? ;
445+ final instanceId = value? [2 ] as String ? ;
446+ final dwdsVersion = value? [3 ] as String ? ;
447+ if (extensionUri == null || appId == null || instanceId == null ) {
448+ consoleWarn (
449+ 'Unable to debug app. Missing Dart debugging global variables' );
441450 successCompleter.complete (false );
442451 return ;
443452 }
444- extensionUri = e.result.value[0 ] as String ;
445- appId = e.result.value[1 ] as String ;
446- instanceId = e.result.value[2 ] as String ;
447- dwdsVersion = e.result.value[3 ] as String ;
448453 _startSseClient (
449454 Uri .parse (extensionUri),
450455 appId,
451456 instanceId,
452457 contextId,
453458 tab,
454- dwdsVersion,
459+ dwdsVersion ?? '0.0.0' ,
455460 launchInChromeDevTools,
456461 );
457462 successCompleter.complete (true );
@@ -472,16 +477,16 @@ Future<void> _startSseClient(
472477 String dwdsVersion,
473478 bool launchInChromeDevTools,
474479) async {
475- if (Version .parse (dwdsVersion ?? '0.0.0' ) >= Version .parse ('9.1.0' )) {
480+ if (Version .parse (dwdsVersion) >= Version .parse ('9.1.0' )) {
476481 var authUri = uri.replace (path: authenticationPath);
477482 if (authUri.scheme == 'ws' ) authUri = authUri.replace (scheme: 'http' );
478483 if (authUri.scheme == 'wss' ) authUri = authUri.replace (scheme: 'https' );
479484 final authUrl = authUri.toString ();
480485 try {
481486 final response = await HttpRequest .request (authUrl,
482487 method: 'GET' , withCredentials: true );
483- if ( ! response.responseText
484- .contains ('Dart Debug Authentication Success!' )) {
488+ final responseText = response.responseText ?? '' ;
489+ if ( ! responseText .contains ('Dart Debug Authentication Success!' )) {
485490 throw Exception ('Not authenticated.' );
486491 }
487492 } catch (_) {
@@ -507,8 +512,9 @@ Future<void> _startSseClient(
507512 client.stream.listen ((data) {
508513 final message = serializers.deserialize (jsonDecode (data));
509514 if (message is ExtensionRequest ) {
515+ final messageParams = message.commandParams ?? '{}' ;
510516 final params =
511- BuiltMap <String , Object >(json.decode (message.commandParams )).toMap ();
517+ BuiltMap <String , Object >(json.decode (messageParams )).toMap ();
512518 sendCommand (Debuggee (tabId: currentTab.id), message.command,
513519 js_util.jsify (params), allowInterop (([e]) {
514520 // No arguments indicate that an error occurred.
@@ -588,7 +594,6 @@ void _updateIcon() {
588594 // Therefore, do not update the icon:
589595 if (tabs.isEmpty) return ;
590596 final tab = tabs.first as Tab ;
591- if (tab.id == null ) return ;
592597
593598 if (_tabIdToWarning.containsKey (tab.id)) {
594599 // Set the warning icon (red):
@@ -605,16 +610,15 @@ void _updateIcon() {
605610}
606611
607612/// Construct an [ExtensionEvent] from [method] and [params] .
608- ExtensionEvent _extensionEventFor (String method, Object params) =>
613+ ExtensionEvent _extensionEventFor (String method, Object ? params) =>
609614 ExtensionEvent ((b) => b
610615 ..params = jsonEncode (json.decode (stringify (params)))
611616 ..method = jsonEncode (method));
612617
613618/// Forward debugger events to the backend if applicable.
614619void _filterAndForwardToBackend (Debuggee source, String method, Object params) {
615- final debugSession = _debugSessions.firstWhere (
616- (session) => session.appTabId == source.tabId,
617- orElse: () => null );
620+ final debugSession = _debugSessions
621+ .firstWhereOrNull ((session) => session.appTabId == source.tabId);
618622
619623 if (debugSession == null ) return ;
620624
@@ -662,7 +666,7 @@ external void browserActionOnClickedAddListener(Function callback);
662666
663667@JS ('chrome.debugger.sendCommand' )
664668external void sendCommand (
665- Debuggee target, String method, Object commandParams, Function callback);
669+ Debuggee target, String method, Object ? commandParams, Function callback);
666670
667671@JS ('chrome.debugger.attach' )
668672external void attach (
@@ -684,7 +688,7 @@ external List<Tab> queryTabs(QueryInfo queryInfo, Function callback);
684688external String stringify (o);
685689
686690@JS ('window.alert' )
687- external void alert ([String message]);
691+ external void alert ([String ? message]);
688692
689693@JS ('chrome.tabs.onCreated.addListener' )
690694external void tabsOnCreatedAddListener (Function callback);
@@ -715,16 +719,20 @@ external void sendMessage(
715719 String id, Object message, Object options, Function callback);
716720
717721@JS ('chrome.runtime.sendMessage' )
718- external void sendSimpleMessage (String id, SimpleMessage message);
722+ external void sendSimpleMessage (String ? id, SimpleMessage message);
723+
724+ @JS ('console.warn' )
725+ external void consoleWarn (String header,
726+ [String ? style1, String ? style2, String ? style3]);
719727
720728// For debugging purposes:
721729@JS ('console.log' )
722730external void consoleLog (String header,
723- [String style1, String style2, String style3]);
731+ [String ? style1, String ? style2, String ? style3]);
724732
725733// Note: Not checking the lastError when one occurs throws a runtime exception.
726734@JS ('chrome.runtime.lastError' )
727- external ChromeError get lastError;
735+ external ChromeError ? get lastError;
728736
729737@JS ()
730738class ChromeError {
@@ -736,7 +744,7 @@ class ChromeError {
736744class QueryInfo {
737745 external bool get active;
738746 external bool get currentWindow;
739- external factory QueryInfo ({bool active, bool currentWindow});
747+ external factory QueryInfo ({bool ? active, bool ? currentWindow});
740748}
741749
742750@JS ()
@@ -759,7 +767,7 @@ class Debuggee {
759767 external int get tabId;
760768 external String get extensionId;
761769 external String get targetId;
762- external factory Debuggee ({int tabId, String extensionId, String targetId});
770+ external factory Debuggee ({int tabId, String ? extensionId, String ? targetId});
763771}
764772
765773@JS ()
@@ -787,7 +795,8 @@ class NavigationInfo {
787795class SimpleMessage {
788796 external String get recipient;
789797 external String get body;
790- external factory SimpleMessage ({String recipient, String body});
798+ external factory SimpleMessage (
799+ {required String recipient, required String body});
791800}
792801
793802@JS ()
@@ -800,7 +809,8 @@ class Request {
800809 external dynamic get options;
801810 external String get warning;
802811 external String get message;
803- external factory Request ({int tabId, String name, dynamic options});
812+ external factory Request (
813+ {required int tabId, required String name, required dynamic options});
804814}
805815
806816@JS ()
@@ -858,14 +868,7 @@ class InjectedParams {
858868 external bool get returnByValue;
859869 external int get contextId;
860870 external factory InjectedParams (
861- {String expression, bool returnByValue, int contextId});
862- }
863-
864- @JS ()
865- @anonymous
866- class ScriptIdParam {
867- external String get scriptId;
868- external factory ScriptIdParam ({String scriptId});
871+ {String ? expression, bool ? returnByValue, int ? contextId});
869872}
870873
871874@JS ()
0 commit comments