Skip to content

Commit 3cbaf37

Browse files
authored
[MV3 Debug Extension] Support Bolt workflow (#1983)
1 parent 0f893e6 commit 3cbaf37

File tree

7 files changed

+98
-17
lines changed

7 files changed

+98
-17
lines changed

dwds/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313
- Move shared test-only code to a new `test_common` package.
1414

1515
**Breaking changes**
16+
1617
- Require `sdkConfigurationProvider` in `ExpressionCompilerService`
1718
constructor.
19+
- Change DWDS parameter `isFlutterApp` from type `bool?` to type
20+
`Future<bool> Function()?`.
1821

1922
## 17.0.0
2023

@@ -40,6 +43,7 @@
4043
- Fix expression compiler throwing when weak SDK summary is not found.
4144

4245
**Breaking changes**
46+
4347
- Include an optional param to `Dwds.start` to indicate whether it is running
4448
internally or externally.
4549
- Include an optional param to `Dwds.start` to indicate whether it a Flutter

dwds/debug_extension_mv3/web/debug_session.dart

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ Future<void> _maybeConnectToDwds(int tabId, Object? params) async {
246246
if (debugInfo == null) return;
247247
if (contextOrigin != debugInfo.appOrigin) return;
248248
final contextId = context['id'] as int;
249+
// Find the correct frame to connect to (this is necessary if the Dart app is
250+
// embedded in an IFRAME):
251+
final isDartFrame = await _isDartFrame(tabId: tabId, contextId: contextId);
252+
if (!isDartFrame) return;
249253
final connected = await _connectToDwds(
250254
dartAppContextId: contextId,
251255
dartAppTabId: tabId,
@@ -258,6 +262,33 @@ Future<void> _maybeConnectToDwds(int tabId, Object? params) async {
258262
}
259263
}
260264

265+
Future<bool> _isDartFrame({required int tabId, required int contextId}) {
266+
final completer = Completer<bool>();
267+
chrome.debugger.sendCommand(
268+
Debuggee(tabId: tabId),
269+
'Runtime.evaluate',
270+
_InjectedParams(
271+
expression:
272+
'[window.\$dartAppId, window.\$dartAppInstanceId, window.\$dwdsVersion]',
273+
returnByValue: true,
274+
contextId: contextId), allowInterop((dynamic response) {
275+
final evalResponse = response as _EvalResponse;
276+
final value = evalResponse.result.value;
277+
final appId = value?[0];
278+
final instanceId = value?[1];
279+
final dwdsVersion = value?[2];
280+
final frameIdentifier = 'Frame at tab $tabId with context $contextId';
281+
if (appId == null || instanceId == null) {
282+
debugWarn('$frameIdentifier is not a Dart frame.');
283+
completer.complete(false);
284+
} else {
285+
debugLog('Dart $frameIdentifier is using DWDS $dwdsVersion.');
286+
completer.complete(true);
287+
}
288+
}));
289+
return completer.future;
290+
}
291+
261292
Future<bool> _connectToDwds({
262293
required int dartAppContextId,
263294
required int dartAppTabId,
@@ -689,3 +720,25 @@ class _DebugSession {
689720
}
690721
}
691722
}
723+
724+
@JS()
725+
@anonymous
726+
class _EvalResponse {
727+
external _EvalResult get result;
728+
}
729+
730+
@JS()
731+
@anonymous
732+
class _EvalResult {
733+
external List<String?>? get value;
734+
}
735+
736+
@JS()
737+
@anonymous
738+
class _InjectedParams {
739+
external String get expresion;
740+
external bool get returnByValue;
741+
external int get contextId;
742+
external factory _InjectedParams(
743+
{String? expression, bool? returnByValue, int? contextId});
744+
}

dwds/lib/dart_web_debug_service.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,10 @@ class Dwds {
8484
bool launchDevToolsInNewWindow = true,
8585
bool emitDebugEvents = true,
8686
bool isInternalBuild = false,
87-
bool isFlutterApp = false,
87+
Future<bool> Function()? isFlutterApp,
8888
}) async {
8989
globalLoadStrategy = loadStrategy;
90+
isFlutterApp ??= () => Future.value(true);
9091

9192
DevTools? devTools;
9293
Future<String>? extensionUri;

dwds/lib/src/handlers/injector.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ class DwdsInjector {
3636
final bool _useSseForInjectedClient;
3737
final bool _emitDebugEvents;
3838
final bool _isInternalBuild;
39-
final bool _isFlutterApp;
39+
final Future<bool> Function() _isFlutterApp;
4040

4141
DwdsInjector(
4242
this._loadStrategy, {
43+
required bool enableDevtoolsLaunch,
44+
required bool useSseForInjectedClient,
45+
required bool emitDebugEvents,
46+
required bool isInternalBuild,
47+
required Future<bool> Function() isFlutterApp,
4348
Future<String>? extensionUri,
44-
bool enableDevtoolsLaunch = false,
45-
bool useSseForInjectedClient = true,
46-
bool emitDebugEvents = true,
47-
bool isInternalBuild = false,
48-
bool isFlutterApp = false,
4949
}) : _extensionUri = extensionUri,
5050
_enableDevtoolsLaunch = enableDevtoolsLaunch,
5151
_useSseForInjectedClient = useSseForInjectedClient,
@@ -117,7 +117,7 @@ class DwdsInjector {
117117
_enableDevtoolsLaunch,
118118
_emitDebugEvents,
119119
_isInternalBuild,
120-
_isFlutterApp,
120+
await _isFlutterApp(),
121121
);
122122
body += await _loadStrategy.bootstrapFor(entrypoint);
123123
_logger.info('Injected debugging metadata for '

dwds/test/fixtures/server.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class TestServer {
116116
urlEncoder: urlEncoder,
117117
expressionCompiler: expressionCompiler,
118118
isInternalBuild: isInternalBuild,
119-
isFlutterApp: isFlutterApp,
119+
isFlutterApp: () => Future.value(isFlutterApp),
120120
devtoolsLauncher: serveDevTools
121121
? (hostname) async {
122122
final server = await DevToolsServer().serveDevTools(

dwds/test/handlers/injector_test.dart

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ void main() {
2424
group('InjectedHandlerWithoutExtension', () {
2525
late DwdsInjector injector;
2626
setUp(() async {
27-
injector = DwdsInjector(loadStrategy);
27+
injector = DwdsInjector(
28+
loadStrategy,
29+
useSseForInjectedClient: true,
30+
enableDevtoolsLaunch: true,
31+
emitDebugEvents: true,
32+
isInternalBuild: false,
33+
isFlutterApp: () => Future.value(true),
34+
);
2835
final pipeline = const Pipeline().addMiddleware(injector.middleware);
2936
server = await shelf_io.serve(pipeline.addHandler((request) {
3037
if (request.url.path.endsWith(bootstrapJsExtension)) {
@@ -223,7 +230,14 @@ void main() {
223230
group('InjectedHandlerWithoutExtension using WebSockets', () {
224231
late DwdsInjector injector;
225232
setUp(() async {
226-
injector = DwdsInjector(loadStrategy, useSseForInjectedClient: false);
233+
injector = DwdsInjector(
234+
loadStrategy,
235+
useSseForInjectedClient: false,
236+
enableDevtoolsLaunch: true,
237+
emitDebugEvents: true,
238+
isInternalBuild: false,
239+
isFlutterApp: () => Future.value(true),
240+
);
227241
final pipeline = const Pipeline().addMiddleware(injector.middleware);
228242
server = await shelf_io.serve(pipeline.addHandler((request) {
229243
if (request.url.path.endsWith(bootstrapJsExtension)) {
@@ -269,9 +283,15 @@ void main() {
269283
group('InjectedHandlerWithExtension', () {
270284
setUp(() async {
271285
final extensionUri = 'http://localhost:4000';
272-
final pipeline = const Pipeline().addMiddleware(
273-
DwdsInjector(loadStrategy, extensionUri: Future.value(extensionUri))
274-
.middleware);
286+
final pipeline = const Pipeline().addMiddleware(DwdsInjector(
287+
loadStrategy,
288+
extensionUri: Future.value(extensionUri),
289+
useSseForInjectedClient: true,
290+
enableDevtoolsLaunch: true,
291+
emitDebugEvents: true,
292+
isInternalBuild: false,
293+
isFlutterApp: () => Future.value(true),
294+
).middleware);
275295
server = await shelf_io.serve(pipeline.addHandler((request) {
276296
return Response.ok(
277297
'$entrypointExtensionMarker\n'

dwds/test/puppeteer/extension_test.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -650,9 +650,12 @@ void main() async {
650650
expect(iframeTarget, isNotNull);
651651
});
652652

653-
// TODO(elliette): Pull TestServer out of TestContext, so we can add
654-
// a test case for starting another test app, loading that app in
655-
// the tab we were debugging, and be able to reconnect to that one.
653+
// TODO(elliette): Pull TestServer out of TestContext, so we can add:
654+
// 1. a test case for starting another test app, loading that app in
655+
// the tab we were debugging, and being able to reconnect to that
656+
// one.
657+
// 2. a test case for embedding a Dart app in a tab with the same
658+
// origin, and being able to connect to the embedded Dart app.
656659
// See https://github.com/dart-lang/webdev/issues/1779
657660

658661
test('The Dart DevTools IFRAME has the correct query parameters',

0 commit comments

Comments
 (0)