Skip to content
43 changes: 35 additions & 8 deletions dwds/debug_extension_mv3/web/background.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:dwds/data/debug_info.dart';
import 'package:dwds/data/extension_request.dart';
import 'package:js/js.dart';

import 'data_types.dart';
import 'debug_session.dart';
import 'chrome_api.dart';
import 'lifeline_ports.dart';
Expand Down Expand Up @@ -45,23 +46,36 @@ void _registerListeners() {
.addListener(allowInterop(_detectNavigationAwayFromDartApp));

// Detect clicks on the Dart Debug Extension icon.
chrome.action.onClicked.addListener(allowInterop(_startDebugSession));
chrome.action.onClicked.addListener(allowInterop(
(Tab tab) => _startDebugSession(
tab.id,
trigger: Trigger.extensionIcon,
),
));
}

// TODO(elliette): Start a debug session instead.
Future<void> _startDebugSession(Tab currentTab) async {
final tabId = currentTab.id;
Future<void> _startDebugSession(int tabId, {required Trigger trigger}) async {
final debugInfo = await _fetchDebugInfo(tabId);
final extensionUrl = debugInfo?.extensionUrl;
if (extensionUrl == null) {
_showWarningNotification('Can\'t debug Dart app. Extension URL not found.');
sendConnectFailureMessage(
ConnectFailureReason.noDartApp,
dartAppTabId: tabId,
);
return;
}
final isAuthenticated = await _authenticateUser(extensionUrl, tabId);
if (!isAuthenticated) return;
if (!isAuthenticated) {
sendConnectFailureMessage(
ConnectFailureReason.authentication,
dartAppTabId: tabId,
);
return;
}

maybeCreateLifelinePort(currentTab.id);
attachDebugger(tabId);
maybeCreateLifelinePort(tabId);
attachDebugger(tabId, trigger: trigger);
}

Future<bool> _authenticateUser(String extensionUrl, int tabId) async {
Expand Down Expand Up @@ -113,6 +127,19 @@ void _handleRuntimeMessages(
_setDebuggableIcon();
}
});

interceptMessage<DebugStateChange>(
message: jsRequest,
expectedType: MessageType.debugStateChange,
expectedSender: Script.debuggerPanel,
expectedRecipient: Script.background,
messageHandler: (DebugStateChange debugStateChange) {
final newState = debugStateChange.newState;
final tabId = debugStateChange.tabId;
if (newState == DebugStateChange.startDebugging) {
_startDebugSession(tabId, trigger: Trigger.extensionPanel);
}
});
}

void _detectNavigationAwayFromDartApp(NavigationInfo navigationInfo) async {
Expand All @@ -125,7 +152,7 @@ void _detectNavigationAwayFromDartApp(NavigationInfo navigationInfo) async {
detachDebugger(
tabId,
type: TabType.dartApp,
reason: 'Navigated away from Dart app.',
reason: DetachReason.navigatedAwayFromApp,
);
}
}
Expand Down
2 changes: 2 additions & 0 deletions dwds/debug_extension_mv3/web/chrome_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ class InspectedWindow {
@JS()
@anonymous
class Panels {
external String get themeName;

external void create(String title, String iconPath, String pagePath,
void Function(ExtensionPanel)? callback);
}
Expand Down
3 changes: 3 additions & 0 deletions dwds/debug_extension_mv3/web/data_serializers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ part 'data_serializers.g.dart';
/// Serializers for all the data types used in the Dart Debug Extension.
@SerializersFor([
BatchedEvents,
ConnectFailure,
DebugInfo,
DebugStateChange,
DevToolsOpener,
DevToolsUrl,
DevToolsRequest,
ExtensionEvent,
ExtensionRequest,
Expand Down
3 changes: 3 additions & 0 deletions dwds/debug_extension_mv3/web/data_serializers.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions dwds/debug_extension_mv3/web/data_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@ import 'package:built_value/serializer.dart';

part 'data_types.g.dart';

abstract class ConnectFailure
implements Built<ConnectFailure, ConnectFailureBuilder> {
static Serializer<ConnectFailure> get serializer =>
_$connectFailureSerializer;

factory ConnectFailure([Function(ConnectFailureBuilder) updates]) =
_$ConnectFailure;

ConnectFailure._();

int get tabId;

String? get reason;
}

abstract class DevToolsOpener
implements Built<DevToolsOpener, DevToolsOpenerBuilder> {
static Serializer<DevToolsOpener> get serializer =>
Expand All @@ -19,3 +34,37 @@ abstract class DevToolsOpener

bool get newWindow;
}

abstract class DevToolsUrl implements Built<DevToolsUrl, DevToolsUrlBuilder> {
static Serializer<DevToolsUrl> get serializer => _$devToolsUrlSerializer;

factory DevToolsUrl([Function(DevToolsUrlBuilder) updates]) = _$DevToolsUrl;

DevToolsUrl._();

int get tabId;

String get url;
}

abstract class DebugStateChange
implements Built<DebugStateChange, DebugStateChangeBuilder> {
static const startDebugging = 'start-debugging';
static const stopDebugging = 'stop-debugging';
static const failedToConnect = 'failed-to-connect';

static Serializer<DebugStateChange> get serializer =>
_$debugStateChangeSerializer;

factory DebugStateChange([Function(DebugStateChangeBuilder) updates]) =
_$DebugStateChange;

DebugStateChange._();

int get tabId;

/// Can only be [startDebugging] or [stopDebugging].
String get newState;

String? get reason;
}
Loading