From b5a74e3aaf4aad2c82ce0891feb37af7026f01a9 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Thu, 1 Dec 2022 13:24:01 -0800 Subject: [PATCH 01/13] Add isFlutterApp changes --- dwds/CHANGELOG.md | 2 ++ dwds/lib/dart_web_debug_service.dart | 2 ++ dwds/lib/data/debug_info.dart | 1 + dwds/lib/data/debug_info.g.dart | 48 ++++++++++++++++++------- dwds/lib/src/handlers/injector.dart | 31 +++++++++------- dwds/lib/src/injected/client.js | 28 +++++++++++---- dwds/test/handlers/injector_test.dart | 6 ++++ dwds/test/puppeteer/extension_test.dart | 1 + dwds/web/client.dart | 6 +++- 9 files changed, 93 insertions(+), 32 deletions(-) diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index 60ada03d9..00798899f 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -9,6 +9,8 @@ - Include the entire exception description up to the stacktrace in `mapExceptionStackTrace`. - Allow enabling experiments in the expression compiler service. +- Include an optional param to `Dwds.start` to indicate whether it a Flutter app + or not. ## 16.0.1 diff --git a/dwds/lib/dart_web_debug_service.dart b/dwds/lib/dart_web_debug_service.dart index d609e643b..ba66a8272 100644 --- a/dwds/lib/dart_web_debug_service.dart +++ b/dwds/lib/dart_web_debug_service.dart @@ -87,6 +87,7 @@ class Dwds { SdkConfigurationProvider? sdkConfigurationProvider, bool emitDebugEvents = true, bool isInternalBuild = false, + bool isFlutterApp = false, }) async { globalLoadStrategy = loadStrategy; sdkConfigurationProvider ??= DefaultSdkConfigurationProvider(); @@ -129,6 +130,7 @@ class Dwds { enableDevtoolsLaunch: enableDevtoolsLaunch, emitDebugEvents: emitDebugEvents, isInternalBuild: isInternalBuild, + isFlutterApp: isFlutterApp, ); final devHandler = DevHandler( diff --git a/dwds/lib/data/debug_info.dart b/dwds/lib/data/debug_info.dart index 41ac51b39..288d1e7b5 100644 --- a/dwds/lib/data/debug_info.dart +++ b/dwds/lib/data/debug_info.dart @@ -22,4 +22,5 @@ abstract class DebugInfo implements Built { String? get dwdsVersion; String? get extensionUrl; bool? get isInternalBuild; + bool? get isFlutterApp; } diff --git a/dwds/lib/data/debug_info.g.dart b/dwds/lib/data/debug_info.g.dart index 6fb126599..e3b1f4135 100644 --- a/dwds/lib/data/debug_info.g.dart +++ b/dwds/lib/data/debug_info.g.dart @@ -75,6 +75,13 @@ class _$DebugInfoSerializer implements StructuredSerializer { ..add( serializers.serialize(value, specifiedType: const FullType(bool))); } + value = object.isFlutterApp; + if (value != null) { + result + ..add('isFlutterApp') + ..add( + serializers.serialize(value, specifiedType: const FullType(bool))); + } return result; } @@ -121,6 +128,10 @@ class _$DebugInfoSerializer implements StructuredSerializer { result.isInternalBuild = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool?; break; + case 'isFlutterApp': + result.isFlutterApp = serializers.deserialize(value, + specifiedType: const FullType(bool)) as bool?; + break; } } @@ -145,6 +156,8 @@ class _$DebugInfo extends DebugInfo { final String? extensionUrl; @override final bool? isInternalBuild; + @override + final bool? isFlutterApp; factory _$DebugInfo([void Function(DebugInfoBuilder)? updates]) => (new DebugInfoBuilder()..update(updates))._build(); @@ -157,7 +170,8 @@ class _$DebugInfo extends DebugInfo { this.appUrl, this.dwdsVersion, this.extensionUrl, - this.isInternalBuild}) + this.isInternalBuild, + this.isFlutterApp}) : super._(); @override @@ -178,7 +192,8 @@ class _$DebugInfo extends DebugInfo { appUrl == other.appUrl && dwdsVersion == other.dwdsVersion && extensionUrl == other.extensionUrl && - isInternalBuild == other.isInternalBuild; + isInternalBuild == other.isInternalBuild && + isFlutterApp == other.isFlutterApp; } @override @@ -189,14 +204,16 @@ class _$DebugInfo extends DebugInfo { $jc( $jc( $jc( - $jc($jc(0, appEntrypointPath.hashCode), - appId.hashCode), - appInstanceId.hashCode), - appOrigin.hashCode), - appUrl.hashCode), - dwdsVersion.hashCode), - extensionUrl.hashCode), - isInternalBuild.hashCode)); + $jc( + $jc($jc(0, appEntrypointPath.hashCode), + appId.hashCode), + appInstanceId.hashCode), + appOrigin.hashCode), + appUrl.hashCode), + dwdsVersion.hashCode), + extensionUrl.hashCode), + isInternalBuild.hashCode), + isFlutterApp.hashCode)); } @override @@ -209,7 +226,8 @@ class _$DebugInfo extends DebugInfo { ..add('appUrl', appUrl) ..add('dwdsVersion', dwdsVersion) ..add('extensionUrl', extensionUrl) - ..add('isInternalBuild', isInternalBuild)) + ..add('isInternalBuild', isInternalBuild) + ..add('isFlutterApp', isFlutterApp)) .toString(); } } @@ -252,6 +270,10 @@ class DebugInfoBuilder implements Builder { set isInternalBuild(bool? isInternalBuild) => _$this._isInternalBuild = isInternalBuild; + bool? _isFlutterApp; + bool? get isFlutterApp => _$this._isFlutterApp; + set isFlutterApp(bool? isFlutterApp) => _$this._isFlutterApp = isFlutterApp; + DebugInfoBuilder(); DebugInfoBuilder get _$this { @@ -265,6 +287,7 @@ class DebugInfoBuilder implements Builder { _dwdsVersion = $v.dwdsVersion; _extensionUrl = $v.extensionUrl; _isInternalBuild = $v.isInternalBuild; + _isFlutterApp = $v.isFlutterApp; _$v = null; } return this; @@ -294,7 +317,8 @@ class DebugInfoBuilder implements Builder { appUrl: appUrl, dwdsVersion: dwdsVersion, extensionUrl: extensionUrl, - isInternalBuild: isInternalBuild); + isInternalBuild: isInternalBuild, + isFlutterApp: isFlutterApp); replace(_$result); return _$result; } diff --git a/dwds/lib/src/handlers/injector.dart b/dwds/lib/src/handlers/injector.dart index 2f572cfef..b486cc058 100644 --- a/dwds/lib/src/handlers/injector.dart +++ b/dwds/lib/src/handlers/injector.dart @@ -37,6 +37,7 @@ class DwdsInjector { final bool _useSseForInjectedClient; final bool _emitDebugEvents; final bool _isInternalBuild; + final bool _isFlutterApp; DwdsInjector( this._loadStrategy, { @@ -45,11 +46,13 @@ class DwdsInjector { bool useSseForInjectedClient = true, bool emitDebugEvents = true, bool isInternalBuild = false, + bool isFlutterApp = false, }) : _extensionUri = extensionUri, _enableDevtoolsLaunch = enableDevtoolsLaunch, _useSseForInjectedClient = useSseForInjectedClient, _emitDebugEvents = emitDebugEvents, - _isInternalBuild = isInternalBuild; + _isInternalBuild = isInternalBuild, + _isFlutterApp = isFlutterApp; /// Returns the embedded dev handler paths. /// @@ -115,6 +118,7 @@ class DwdsInjector { _enableDevtoolsLaunch, _emitDebugEvents, _isInternalBuild, + _isFlutterApp, ); body += await _loadStrategy.bootstrapFor(entrypoint); _logger.info('Injected debugging metadata for ' @@ -140,16 +144,16 @@ class DwdsInjector { /// Returns the provided body with the main function hoisted into a global /// variable and a snippet of JS that loads the injected client. String _injectClientAndHoistMain( - String body, - String appId, - String devHandlerPath, - String entrypointPath, - String? extensionUri, - LoadStrategy loadStrategy, - bool enableDevtoolsLaunch, - bool emitDebugEvents, - bool isInternalBuild, -) { + String body, + String appId, + String devHandlerPath, + String entrypointPath, + String? extensionUri, + LoadStrategy loadStrategy, + bool enableDevtoolsLaunch, + bool emitDebugEvents, + bool isInternalBuild, + bool isFlutterApp) { final bodyLines = body.split('\n'); final extensionIndex = bodyLines.indexWhere((line) => line.contains(mainExtensionMarker)); @@ -169,7 +173,8 @@ String _injectClientAndHoistMain( loadStrategy, enableDevtoolsLaunch, emitDebugEvents, - isInternalBuild); + isInternalBuild, + isFlutterApp); result += ''' // Injected by dwds for debugging support. if(!window.\$dwdsInitialized) { @@ -204,6 +209,7 @@ String _injectedClientSnippet( bool enableDevtoolsLaunch, bool emitDebugEvents, bool isInternalBuild, + bool isFlutterApp, ) { var injectedBody = 'window.\$dartAppId = "$appId";\n' 'window.\$dartReloadConfiguration = "${loadStrategy.reloadConfiguration}";\n' @@ -215,6 +221,7 @@ String _injectedClientSnippet( 'window.\$dartEntrypointPath = "$entrypointPath";\n' 'window.\$dartEmitDebugEvents = $emitDebugEvents;\n' 'window.\$isInternalBuild = $isInternalBuild;\n' + 'window.\$isFlutterApp = $isFlutterApp;\n' '${loadStrategy.loadClientSnippet(_clientScript)}'; if (extensionUri != null) { injectedBody += 'window.\$dartExtensionUri = "$extensionUri";\n'; diff --git a/dwds/lib/src/injected/client.js b/dwds/lib/src/injected/client.js index d2b487866..b38e397a7 100644 --- a/dwds/lib/src/injected/client.js +++ b/dwds/lib/src/injected/client.js @@ -8156,7 +8156,7 @@ }, _$DebugInfoSerializer: function _$DebugInfoSerializer() { }, - _$DebugInfo: function _$DebugInfo(t0, t1, t2, t3, t4, t5, t6, t7) { + _$DebugInfo: function _$DebugInfo(t0, t1, t2, t3, t4, t5, t6, t7, t8) { var _ = this; _.appEntrypointPath = t0; _.appId = t1; @@ -8166,10 +8166,11 @@ _.dwdsVersion = t5; _.extensionUrl = t6; _.isInternalBuild = t7; + _.isFlutterApp = t8; }, DebugInfoBuilder: function DebugInfoBuilder() { var _ = this; - _._isInternalBuild = _._extensionUrl = _._dwdsVersion = _._appUrl = _._appOrigin = _._appInstanceId = _._appId = _._appEntrypointPath = _._$v = null; + _._isFlutterApp = _._isInternalBuild = _._extensionUrl = _._dwdsVersion = _._appUrl = _._appOrigin = _._appInstanceId = _._appId = _._appEntrypointPath = _._$v = null; }, DevToolsRequest: function DevToolsRequest() { }, @@ -22544,6 +22545,11 @@ result.push("isInternalBuild"); result.push(serializers.serialize$2$specifiedType(value, B.FullType_MtR)); } + value = object.isFlutterApp; + if (value != null) { + result.push("isFlutterApp"); + result.push(serializers.serialize$2$specifiedType(value, B.FullType_MtR)); + } return result; }, serialize$2(serializers, object) { @@ -22592,6 +22598,10 @@ t1 = A._asBoolQ(serializers.deserialize$2$specifiedType(value, B.FullType_MtR)); result.get$_$this()._isInternalBuild = t1; break; + case "isFlutterApp": + t1 = A._asBoolQ(serializers.deserialize$2$specifiedType(value, B.FullType_MtR)); + result.get$_$this()._isFlutterApp = t1; + break; } } return result._debug_info$_build$0(); @@ -22615,11 +22625,11 @@ return false; if (other === _this) return true; - return other instanceof A.DebugInfo && _this.appEntrypointPath == other.appEntrypointPath && _this.appId == other.appId && _this.appInstanceId == other.appInstanceId && _this.appOrigin == other.appOrigin && _this.appUrl == other.appUrl && _this.dwdsVersion == other.dwdsVersion && _this.extensionUrl == other.extensionUrl && _this.isInternalBuild == other.isInternalBuild; + return other instanceof A.DebugInfo && _this.appEntrypointPath == other.appEntrypointPath && _this.appId == other.appId && _this.appInstanceId == other.appInstanceId && _this.appOrigin == other.appOrigin && _this.appUrl == other.appUrl && _this.dwdsVersion == other.dwdsVersion && _this.extensionUrl == other.extensionUrl && _this.isInternalBuild == other.isInternalBuild && _this.isFlutterApp == other.isFlutterApp; }, get$hashCode(_) { var _this = this; - return A.$jf(A.$jc(A.$jc(A.$jc(A.$jc(A.$jc(A.$jc(A.$jc(A.$jc(0, J.get$hashCode$(_this.appEntrypointPath)), J.get$hashCode$(_this.appId)), J.get$hashCode$(_this.appInstanceId)), J.get$hashCode$(_this.appOrigin)), J.get$hashCode$(_this.appUrl)), J.get$hashCode$(_this.dwdsVersion)), J.get$hashCode$(_this.extensionUrl)), J.get$hashCode$(_this.isInternalBuild))); + return A.$jf(A.$jc(A.$jc(A.$jc(A.$jc(A.$jc(A.$jc(A.$jc(A.$jc(A.$jc(0, J.get$hashCode$(_this.appEntrypointPath)), J.get$hashCode$(_this.appId)), J.get$hashCode$(_this.appInstanceId)), J.get$hashCode$(_this.appOrigin)), J.get$hashCode$(_this.appUrl)), J.get$hashCode$(_this.dwdsVersion)), J.get$hashCode$(_this.extensionUrl)), J.get$hashCode$(_this.isInternalBuild)), J.get$hashCode$(_this.isFlutterApp))); }, toString$0(_) { var _this = this, @@ -22633,6 +22643,7 @@ t2.add$2(t1, "dwdsVersion", _this.dwdsVersion); t2.add$2(t1, "extensionUrl", _this.extensionUrl); t2.add$2(t1, "isInternalBuild", _this.isInternalBuild); + t2.add$2(t1, "isFlutterApp", _this.isFlutterApp); return t2.toString$0(t1); } }; @@ -22649,6 +22660,7 @@ _this._dwdsVersion = $$v.dwdsVersion; _this._extensionUrl = $$v.extensionUrl; _this._isInternalBuild = $$v.isInternalBuild; + _this._isFlutterApp = $$v.isFlutterApp; _this._$v = null; } return _this; @@ -22657,7 +22669,7 @@ var _this = this, _$result = _this._$v; if (_$result == null) - _$result = new A._$DebugInfo(_this.get$_$this()._appEntrypointPath, _this.get$_$this()._appId, _this.get$_$this()._appInstanceId, _this.get$_$this()._appOrigin, _this.get$_$this()._appUrl, _this.get$_$this()._dwdsVersion, _this.get$_$this()._extensionUrl, _this.get$_$this()._isInternalBuild); + _$result = new A._$DebugInfo(_this.get$_$this()._appEntrypointPath, _this.get$_$this()._appId, _this.get$_$this()._appInstanceId, _this.get$_$this()._appOrigin, _this.get$_$this()._appUrl, _this.get$_$this()._dwdsVersion, _this.get$_$this()._extensionUrl, _this.get$_$this()._isInternalBuild, _this.get$_$this()._isFlutterApp); A.ArgumentError_checkNotNull(_$result, "other", type$.DebugInfo); return _this._$v = _$result; } @@ -25187,8 +25199,10 @@ b.get$_$this()._appUrl = t2; t2 = A._asStringQ(t1.$index(0, "$dartExtensionUri")); b.get$_$this()._extensionUrl = t2; - t1 = A._asBoolQ(t1.$index(0, "$isInternalBuild")); - b.get$_$this()._isInternalBuild = t1; + t2 = A._asBoolQ(t1.$index(0, "$isInternalBuild")); + b.get$_$this()._isInternalBuild = t2; + t1 = A._asBoolQ(t1.$index(0, "$isFlutterApp")); + b.get$_$this()._isFlutterApp = t1; return b; }, $signature: 77 diff --git a/dwds/test/handlers/injector_test.dart b/dwds/test/handlers/injector_test.dart index 103551e6d..d0bd68b58 100644 --- a/dwds/test/handlers/injector_test.dart +++ b/dwds/test/handlers/injector_test.dart @@ -205,6 +205,12 @@ void main() { expect(result.body, contains('\$isInternalBuild')); }); + test('the injected client contains a global \$isFlutterApp', () async { + final result = await http.get(Uri.parse( + 'http://localhost:${server.port}/dwds/src/injected/client.js')); + expect(result.body, contains('\$isFlutterApp')); + }); + test('serves the injected client', () async { final result = await http.get(Uri.parse( 'http://localhost:${server.port}/dwds/src/injected/client.js')); diff --git a/dwds/test/puppeteer/extension_test.dart b/dwds/test/puppeteer/extension_test.dart index 768ebe481..07afb95d5 100644 --- a/dwds/test/puppeteer/extension_test.dart +++ b/dwds/test/puppeteer/extension_test.dart @@ -88,6 +88,7 @@ void main() async { expect(debugInfo.appOrigin, isNotNull); expect(debugInfo.appUrl, isNotNull); expect(debugInfo.isInternalBuild, isNotNull); + expect(debugInfo.isFlutterApp, isNotNull); await appTab.close(); }); diff --git a/dwds/web/client.dart b/dwds/web/client.dart index bd1eb2cab..1b1b4b309 100644 --- a/dwds/web/client.dart +++ b/dwds/web/client.dart @@ -181,7 +181,8 @@ Future? main() { ..appOrigin = window.location.origin ..appUrl = window.location.href ..extensionUrl = windowContext['\$dartExtensionUri'] - ..isInternalBuild = windowContext['\$isInternalBuild']))); + ..isInternalBuild = windowContext['\$isInternalBuild'] + ..isFlutterApp = windowContext['\$isFlutterApp']))); dispatchEvent(CustomEvent('dart-app-ready', detail: debugInfoJson)); }, (error, stackTrace) { @@ -278,4 +279,7 @@ external set emitRegisterEvent(void Function(String) func); @JS(r'$isInternalBuild') external bool get isInternalBuild; +@JS(r'$isFlutterApp') +external bool get isFlutterApp; + bool get _isChromium => window.navigator.vendor.contains('Google'); From 584986c512e1e0bc7b7c6d34767ad51375c9ffec Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Thu, 1 Dec 2022 13:24:29 -0800 Subject: [PATCH 02/13] Add DebugSession changes --- .../web/debug_session.dart | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/dwds/debug_extension_mv3/web/debug_session.dart b/dwds/debug_extension_mv3/web/debug_session.dart index b7f4c61d6..1d381dfe2 100644 --- a/dwds/debug_extension_mv3/web/debug_session.dart +++ b/dwds/debug_extension_mv3/web/debug_session.dart @@ -133,10 +133,10 @@ Future _connectToDwds({ final client = uri.isScheme('ws') || uri.isScheme('wss') ? WebSocketClient(WebSocketChannel.connect(uri)) : SseSocketClient(SseClient(uri.toString())); - final debugSession = _DebugSession(client: client, appTabId: dartAppTabId); - _debugSessions.add(debugSession); - client.stream.listen( - (data) => _routeDwdsEvent(data, client, dartAppTabId), + final debugSession = _DebugSession( + client: client, + appTabId: dartAppTabId, + onIncoming: (data) => _routeDwdsEvent(data, client, dartAppTabId), onDone: () { debugLog('Shutting down DWDS communication channel.'); _detachDebuggerForTab(dartAppTabId, type: TabType.dartApp); @@ -147,15 +147,15 @@ Future _connectToDwds({ }, cancelOnError: true, ); + _debugSessions.add(debugSession); final tabUrl = await _getTabUrl(dartAppTabId); // Send a DevtoolsRequest to the event stream: - final event = jsonEncode(serializers.serialize(DevToolsRequest((b) => b + debugSession.sendEvent(DevToolsRequest((b) => b ..appId = debugInfo.appId ..instanceId = debugInfo.appInstanceId ..contextId = dartAppContextId ..tabUrl = tabUrl - ..uriOnly = true))); - client.sink.add(event); + ..uriOnly = true)); return true; } @@ -323,12 +323,23 @@ class _DebugSession { _DebugSession({ required client, required this.appTabId, + required void Function(String data) onIncoming, + required void Function() onDone, + required void Function(dynamic error) onError, + required bool cancelOnError, }) : _socketClient = client { // Collect extension events and send them periodically to the server. _batchSubscription = _batchController.stream.listen((events) { _socketClient.sink.add(jsonEncode(serializers.serialize(BatchedEvents( (b) => b.events = ListBuilder(events))))); }); + // Listen for incoming events: + _socketClient.stream.listen( + onIncoming, + onDone: onDone, + onError: onError, + cancelOnError: cancelOnError, + ); } set socketClient(SocketClient client) { @@ -341,7 +352,7 @@ class _DebugSession { }); } - void sendEvent(ExtensionEvent event) { + void sendEvent(T event) { _socketClient.sink.add(jsonEncode(serializers.serialize(event))); } From cfcd63ed9931d2efabbae754b5ffaa003934b850 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Thu, 1 Dec 2022 13:25:19 -0800 Subject: [PATCH 03/13] Add storage changes --- dwds/debug_extension_mv3/web/storage.dart | 29 +++++++++++- dwds/test/puppeteer/extension_test.dart | 58 ++++++++++++++++++++--- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/dwds/debug_extension_mv3/web/storage.dart b/dwds/debug_extension_mv3/web/storage.dart index dc4328ced..26a286c63 100644 --- a/dwds/debug_extension_mv3/web/storage.dart +++ b/dwds/debug_extension_mv3/web/storage.dart @@ -27,6 +27,20 @@ enum StorageObject { return 'devToolsOpener'; } } + + Persistance get persistance { + switch (this) { + case StorageObject.debugInfo: + return Persistance.sessionOnly; + case StorageObject.devToolsOpener: + return Persistance.acrossSessions; + } + } +} + +enum Persistance { + sessionOnly, + acrossSessions; } Future setStorageObject({ @@ -39,7 +53,8 @@ Future setStorageObject({ final json = jsonEncode(serializers.serialize(value)); final storageObj = {storageKey: json}; final completer = Completer(); - chrome.storage.local.set(jsify(storageObj), allowInterop(() { + final storageArea = _getStorageArea(type.persistance); + storageArea.set(jsify(storageObj), allowInterop(() { if (callback != null) { callback(); } @@ -52,7 +67,8 @@ Future setStorageObject({ Future fetchStorageObject({required StorageObject type, int? tabId}) { final storageKey = _createStorageKey(type, tabId); final completer = Completer(); - chrome.storage.local.get([storageKey], allowInterop((Object storageObj) { + final storageArea = _getStorageArea(type.persistance); + storageArea.get([storageKey], allowInterop((Object storageObj) { final json = getProperty(storageObj, storageKey) as String?; if (json == null) { debugWarn('Does not exist.', prefix: storageKey); @@ -66,6 +82,15 @@ Future fetchStorageObject({required StorageObject type, int? tabId}) { return completer.future; } +StorageArea _getStorageArea(Persistance persistance) { + switch (persistance) { + case Persistance.acrossSessions: + return chrome.storage.local; + case Persistance.sessionOnly: + return chrome.storage.session; + } +} + String _createStorageKey(StorageObject type, int? tabId) { if (tabId == null) return type.keyName; return '$tabId-${type.keyName}'; diff --git a/dwds/test/puppeteer/extension_test.dart b/dwds/test/puppeteer/extension_test.dart index 07afb95d5..6985fa0df 100644 --- a/dwds/test/puppeteer/extension_test.dart +++ b/dwds/test/puppeteer/extension_test.dart @@ -13,10 +13,11 @@ import 'dart:async'; import 'dart:convert'; import 'package:dwds/data/debug_info.dart'; -import 'package:dwds/data/serializers.dart'; import 'package:puppeteer/puppeteer.dart'; import 'package:test/test.dart'; +import '../../debug_extension_mv3/web/data_serializers.dart'; +import '../../debug_extension_mv3/web/data_types.dart'; import '../fixtures/context.dart'; import 'test_utils.dart'; @@ -61,11 +62,17 @@ void main() async { .waitForTarget((target) => target.type == 'service_worker'); }); + tearDown(() async { + final worker = (await serviceWorkerTarget.worker)!; + await Future.delayed(Duration(seconds: executionContextDelay)); + await worker.evaluate(_clearStorageJs()); + }); + tearDownAll(() async { await browser.close(); }); - test('the debug info for a Dart app is saved in the extension storage', + test('the debug info for a Dart app is saved in session storage', () async { final appUrl = context.appUrl; // Navigate to the Dart app: @@ -77,8 +84,8 @@ void main() async { final tabIdForAppJs = _tabIdForTabJs(appUrl); final appTabId = (await worker.evaluate(tabIdForAppJs)) as int; final debugInfoKey = '$appTabId-debugInfo'; - final storageObj = - await worker.evaluate(_fetchStorageObjJs(debugInfoKey)); + final storageObj = await worker.evaluate( + _fetchStorageObjJs(debugInfoKey, storageArea: 'session')); final json = storageObj[debugInfoKey]; final debugInfo = serializers.deserialize(jsonDecode(json)) as DebugInfo; @@ -92,6 +99,32 @@ void main() async { await appTab.close(); }); + test('whether to open in a new tab or window is saved in local storage', + () async { + // Navigate to the extension settings page: + final extensionOrigin = getExtensionOrigin(browser); + final settingsTab = await navigateToPage( + browser, + url: '$extensionOrigin/settings.html', + isNew: true, + ); + // Set the settings to open DevTools in a new window: + await settingsTab.tap('#windowOpt'); + await settingsTab.tap('#saveButton'); + // Wait for the saved message to verify settings have been saved: + await settingsTab.waitForSelector('#savedMsg'); + // Close the settings tab: + await settingsTab.close(); + // Check that is has been saved in local storage: + final worker = (await serviceWorkerTarget.worker)!; + final storageObj = await worker.evaluate( + _fetchStorageObjJs('devToolsOpener', storageArea: 'local')); + final json = storageObj['devToolsOpener']; + final devToolsOpener = + serializers.deserialize(jsonDecode(json)) as DevToolsOpener; + expect(devToolsOpener.newWindow, isTrue); + }); + test( 'can configure opening DevTools in a tab/window with extension settings', () async { @@ -173,12 +206,15 @@ String _windowIdForTabJs(String tabUrl) { '''; } -String _fetchStorageObjJs(String storageKey) { +String _fetchStorageObjJs( + String storageKey, { + required String storageArea, +}) { return ''' async () => { const storageKey = "$storageKey"; return new Promise((resolve, reject) => { - chrome.storage.local.get(storageKey, (storageObj) => { + chrome.storage.$storageArea.get(storageKey, (storageObj) => { if (storageObj != null) { resolve(storageObj); } else { @@ -189,3 +225,13 @@ String _fetchStorageObjJs(String storageKey) { } '''; } + +String _clearStorageJs() { + return ''' + async () => { + await chrome.storage.local.clear(); + await chrome.storage.session.clear(); + return true; + } +'''; +} From 0839252923720d4c6f7452064d7078f1cdf17eaf Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Thu, 1 Dec 2022 14:38:10 -0800 Subject: [PATCH 04/13] Can add panels --- dwds/debug_extension_mv3/web/chrome_api.dart | 58 ++++++++++++++ .../web/debug_session.dart | 4 +- dwds/debug_extension_mv3/web/devtools.dart | 77 +++++++++++++++++++ dwds/debug_extension_mv3/web/devtools.html | 11 +++ dwds/debug_extension_mv3/web/manifest.json | 1 + dwds/debug_extension_mv3/web/panel.html | 11 +++ 6 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 dwds/debug_extension_mv3/web/devtools.dart create mode 100644 dwds/debug_extension_mv3/web/devtools.html create mode 100644 dwds/debug_extension_mv3/web/panel.html diff --git a/dwds/debug_extension_mv3/web/chrome_api.dart b/dwds/debug_extension_mv3/web/chrome_api.dart index b6fa30654..bfdf5b31e 100644 --- a/dwds/debug_extension_mv3/web/chrome_api.dart +++ b/dwds/debug_extension_mv3/web/chrome_api.dart @@ -2,6 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:html'; + import 'package:js/js.dart'; @JS() @@ -12,6 +14,7 @@ external Chrome get chrome; class Chrome { external Action get action; external Debugger get debugger; + external Devtools get devtools; external Notifications get notifications; external Runtime get runtime; external Scripting get scripting; @@ -86,6 +89,50 @@ class Debuggee { external factory Debuggee({int tabId, String? extensionId, String? targetId}); } +/// chrome.devtools APIs: + +@JS() +@anonymous +class Devtools { + // https://developer.chrome.com/docs/extensions/reference/devtools_inspectedWindow + external InspectedWindow get inspectedWindow; + + // https://developer.chrome.com/docs/extensions/reference/devtools_panels/ + external Panels get panels; +} + +@JS() +@anonymous +class InspectedWindow { + external int get tabId; +} + +@JS() +@anonymous +class Panels { + external void create(String title, String iconPath, String pagePath, + void Function(ExtensionPanel)? callback); +} + +@JS() +@anonymous +class ExtensionPanel { + external OnHiddenHandler get onHidden; + external OnShownHandler get onShown; +} + +@JS() +@anonymous +class OnHiddenHandler { + external void addListener(void Function() callback); +} + +@JS() +@anonymous +class OnShownHandler { + external void addListener(void Function(Window window) callback); +} + /// chrome.notification APIs: /// https://developer.chrome.com/docs/extensions/reference/notifications @@ -210,6 +257,8 @@ class Storage { external StorageArea get local; external StorageArea get session; + + external OnChangedHandler get onChanged; } @JS() @@ -220,6 +269,15 @@ class StorageArea { external Object set(Object items, void Function()? callback); } +@JS() +@anonymous +class OnChangedHandler { + external void addListener( + void Function(Object changes, String areaName) callback, + ); +} + + /// chrome.tabs APIs /// https://developer.chrome.com/docs/extensions/reference/tabs diff --git a/dwds/debug_extension_mv3/web/debug_session.dart b/dwds/debug_extension_mv3/web/debug_session.dart index 1d381dfe2..5db963f14 100644 --- a/dwds/debug_extension_mv3/web/debug_session.dart +++ b/dwds/debug_extension_mv3/web/debug_session.dart @@ -208,7 +208,7 @@ void _forwardChromeDebuggerEventToDwds( if (method == 'Debugger.scriptParsed') { debugSession.sendBatchedEvent(event); } else { - debugSession.sendEvent(event); + debugSession.sendEvent(event); } } @@ -265,7 +265,7 @@ void _removeDebugSession(_DebugSession debugSession) { // https://github.com/dart-lang/webdev/pull/1595#issuecomment-1116773378 final event = _extensionEventFor('DebugExtension.detached', js_util.jsify({})); - debugSession.sendEvent(event); + debugSession.sendEvent(event); debugSession.close(); final removed = _debugSessions.remove(debugSession); if (!removed) { diff --git a/dwds/debug_extension_mv3/web/devtools.dart b/dwds/debug_extension_mv3/web/devtools.dart new file mode 100644 index 000000000..edaab0828 --- /dev/null +++ b/dwds/debug_extension_mv3/web/devtools.dart @@ -0,0 +1,77 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +@JS() +library detector; + +import 'dart:html'; +import 'dart:js_util'; +import 'package:js/js.dart'; +import 'package:dwds/data/debug_info.dart'; + +import 'chrome_api.dart'; +import 'logger.dart'; +import 'storage.dart'; +import 'utils.dart'; + + +bool panelsExist = false; + +void main() async { + _registerListeners(); + _maybeCreatePanels(); +} + +void _registerListeners() { + chrome.storage.onChanged.addListener(allowInterop(( + Object _, + String storageArea, + ) { + if (storageArea != 'session') return; + _maybeCreatePanels(); + })); +} + +void _maybeCreatePanels() async { + if (panelsExist) return; + final tabId = chrome.devtools.inspectedWindow.tabId; + final debugInfo = await fetchStorageObject( + type: StorageObject.debugInfo, + tabId: tabId, + ); + if (debugInfo == null) return; + final isInternalBuild = debugInfo.isInternalBuild ?? false; + if (!isInternalBuild) return; + // Create a Debugger panel: + chrome.devtools.panels.create( + isDevMode() ? '[DEV] Dart Debugger' : 'Dart Debugger', + '', + 'panel.html', + allowInterop(_onDebuggerPanelAdded), + ); + // Create an inspector panel: + final isFlutterApp = debugInfo.isFlutterApp ?? false; + if (isFlutterApp) { + chrome.devtools.panels.create( + isDevMode() ? '[DEV] Flutter Inspector' : 'Flutter Inspector', + '', + 'panel.html', + allowInterop(_onInspectorPanelAdded), + ); + } + panelsExist = true; +} + +void _onDebuggerPanelAdded(ExtensionPanel debuggerPanel) { + debuggerPanel.onShown.addListener(allowInterop((Window window) { + debugLog('shown and window is ${window.origin}'); + })); + debuggerPanel.onHidden.addListener(allowInterop(() { + debugLog('hidden'); + })); +} + +void _onInspectorPanelAdded(ExtensionPanel inspectorPanel) { + // TODO(elliette) Implement. +} diff --git a/dwds/debug_extension_mv3/web/devtools.html b/dwds/debug_extension_mv3/web/devtools.html new file mode 100644 index 000000000..50038348f --- /dev/null +++ b/dwds/debug_extension_mv3/web/devtools.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/dwds/debug_extension_mv3/web/manifest.json b/dwds/debug_extension_mv3/web/manifest.json index fa1beeef4..b3add0a1b 100644 --- a/dwds/debug_extension_mv3/web/manifest.json +++ b/dwds/debug_extension_mv3/web/manifest.json @@ -2,6 +2,7 @@ "name": "MV3 Dart Debug Extension", "version": "1.0", "manifest_version": 3, + "devtools_page": "devtools.html", "action": { "default_icon": "dart_dev.png" }, diff --git a/dwds/debug_extension_mv3/web/panel.html b/dwds/debug_extension_mv3/web/panel.html new file mode 100644 index 000000000..d5535a066 --- /dev/null +++ b/dwds/debug_extension_mv3/web/panel.html @@ -0,0 +1,11 @@ + + + + + + + +

Panel

+ + + \ No newline at end of file From b5ef48914a6db8c3fb2c39f9f98d91c3d0375360 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Mon, 5 Dec 2022 11:09:19 -0800 Subject: [PATCH 05/13] Polish --- dwds/debug_extension_mv3/web/devtools.dart | 28 ++++++++++------------ 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/dwds/debug_extension_mv3/web/devtools.dart b/dwds/debug_extension_mv3/web/devtools.dart index edaab0828..dfe22e38e 100644 --- a/dwds/debug_extension_mv3/web/devtools.dart +++ b/dwds/debug_extension_mv3/web/devtools.dart @@ -3,10 +3,9 @@ // BSD-style license that can be found in the LICENSE file. @JS() -library detector; +library devtools; import 'dart:html'; -import 'dart:js_util'; import 'package:js/js.dart'; import 'package:dwds/data/debug_info.dart'; @@ -43,35 +42,32 @@ void _maybeCreatePanels() async { if (debugInfo == null) return; final isInternalBuild = debugInfo.isInternalBuild ?? false; if (!isInternalBuild) return; - // Create a Debugger panel: + // Create a Debugger panel for all internal apps: chrome.devtools.panels.create( isDevMode() ? '[DEV] Dart Debugger' : 'Dart Debugger', '', 'panel.html', - allowInterop(_onDebuggerPanelAdded), + allowInterop((ExtensionPanel panel) => _onPanelAdded(panel, debugInfo)), ); - // Create an inspector panel: + // Create an inspector panel for internal Flutter apps: final isFlutterApp = debugInfo.isFlutterApp ?? false; if (isFlutterApp) { chrome.devtools.panels.create( isDevMode() ? '[DEV] Flutter Inspector' : 'Flutter Inspector', '', 'panel.html', - allowInterop(_onInspectorPanelAdded), + allowInterop((ExtensionPanel panel) => _onPanelAdded(panel, debugInfo)), ); } panelsExist = true; } -void _onDebuggerPanelAdded(ExtensionPanel debuggerPanel) { - debuggerPanel.onShown.addListener(allowInterop((Window window) { - debugLog('shown and window is ${window.origin}'); +void _onPanelAdded(ExtensionPanel panel, DebugInfo debugInfo) { + panel.onShown.addListener(allowInterop((Window window) { + if (window.origin != debugInfo.appOrigin) { + debugWarn('Page at ${window.origin} is no longer a Dart app.'); + // TODO(elliette): Display banner that panel is not applicable. See: + // https://stackoverflow.com/questions/18927147/how-to-close-destroy-chrome-devtools-extensionpanel-programmatically + } })); - debuggerPanel.onHidden.addListener(allowInterop(() { - debugLog('hidden'); - })); -} - -void _onInspectorPanelAdded(ExtensionPanel inspectorPanel) { - // TODO(elliette) Implement. } From 568977e43a4f2a5d33f69c3da13a42dcf5583770 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Mon, 5 Dec 2022 13:27:22 -0800 Subject: [PATCH 06/13] Started adding test --- dwds/test/fixtures/context.dart | 2 + dwds/test/fixtures/server.dart | 4 + dwds/test/puppeteer/extension_test.dart | 148 +++++++++++++++++------- 3 files changed, 115 insertions(+), 39 deletions(-) diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index 7c0562665..965f6ca9f 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -162,6 +162,8 @@ class TestContext { SdkConfigurationProvider? sdkConfigurationProvider, bool useDebuggerModuleNames = false, bool launchChrome = true, + bool isFlutterApp = false, + bool isInternalBuild = false, }) async { sdkConfigurationProvider ??= DefaultSdkConfigurationProvider(); diff --git a/dwds/test/fixtures/server.dart b/dwds/test/fixtures/server.dart index 01211379e..0f1a97f46 100644 --- a/dwds/test/fixtures/server.dart +++ b/dwds/test/fixtures/server.dart @@ -80,6 +80,8 @@ class TestServer { ExpressionCompiler? expressionCompiler, bool spawnDds, ExpressionCompilerService? ddcService, + bool isFlutterApp, + bool isInternalBuild, ) async { var pipeline = const Pipeline(); @@ -113,6 +115,8 @@ class TestServer { hostname: hostname, urlEncoder: urlEncoder, expressionCompiler: expressionCompiler, + isInternalBuild: isInternalBuild, + isFlutterApp: isFlutterApp, devtoolsLauncher: serveDevTools ? (hostname) async { final server = await DevToolsServer().serveDevTools( diff --git a/dwds/test/puppeteer/extension_test.dart b/dwds/test/puppeteer/extension_test.dart index 6985fa0df..7cb8b9dae 100644 --- a/dwds/test/puppeteer/extension_test.dart +++ b/dwds/test/puppeteer/extension_test.dart @@ -23,22 +23,19 @@ import 'test_utils.dart'; final context = TestContext(); -// Note: The following delay is required to reduce flakiness. It makes -// sure the service worker execution context is ready. -const executionContextDelay = 1; - void main() async { - late Target serviceWorkerTarget; - late Browser browser; - late String extensionPath; - group('MV3 Debug Extension', () { + late String extensionPath; + setUpAll(() async { extensionPath = await buildDebugExtension(); }); for (var useSse in [true, false]) { group(useSse ? 'with SSE' : 'with WebSockets', () { + late Browser browser; + late Worker worker; + setUpAll(() async { // TODO(elliette): Only start a TestServer, that way we can get rid of // the launchChrome parameter: https://github.com/dart-lang/webdev/issues/1779 @@ -58,13 +55,13 @@ void main() async { ], ); - serviceWorkerTarget = await browser + final serviceWorkerTarget = await browser .waitForTarget((target) => target.type == 'service_worker'); + worker = (await serviceWorkerTarget.worker)!; }); tearDown(() async { - final worker = (await serviceWorkerTarget.worker)!; - await Future.delayed(Duration(seconds: executionContextDelay)); + await workerEvalDelay(); await worker.evaluate(_clearStorageJs()); }); @@ -78,17 +75,15 @@ void main() async { // Navigate to the Dart app: final appTab = await navigateToPage(browser, url: appUrl, isNew: true); - final worker = (await serviceWorkerTarget.worker)!; - await Future.delayed(Duration(seconds: executionContextDelay)); // Verify that we have debug info for the Dart app: - final tabIdForAppJs = _tabIdForTabJs(appUrl); - final appTabId = (await worker.evaluate(tabIdForAppJs)) as int; + await workerEvalDelay(); + final appTabId = await _getTabId(appUrl, worker: worker); final debugInfoKey = '$appTabId-debugInfo'; - final storageObj = await worker.evaluate( - _fetchStorageObjJs(debugInfoKey, storageArea: 'session')); - final json = storageObj[debugInfoKey]; - final debugInfo = - serializers.deserialize(jsonDecode(json)) as DebugInfo; + final debugInfo = await _fetchStorageObj( + debugInfoKey, + storageArea: 'session', + worker: worker, + ); expect(debugInfo.appId, isNotNull); expect(debugInfo.appEntrypointPath, isNotNull); expect(debugInfo.appInstanceId, isNotNull); @@ -116,12 +111,11 @@ void main() async { // Close the settings tab: await settingsTab.close(); // Check that is has been saved in local storage: - final worker = (await serviceWorkerTarget.worker)!; - final storageObj = await worker.evaluate( - _fetchStorageObjJs('devToolsOpener', storageArea: 'local')); - final json = storageObj['devToolsOpener']; - final devToolsOpener = - serializers.deserialize(jsonDecode(json)) as DevToolsOpener; + final devToolsOpener = await _fetchStorageObj( + 'devToolsOpener', + storageArea: 'local', + worker: worker, + ); expect(devToolsOpener.newWindow, isTrue); }); @@ -131,22 +125,21 @@ void main() async { final appUrl = context.appUrl; final devToolsUrlFragment = useSse ? 'debugger?uri=sse' : 'debugger?uri=ws'; - final windowIdForAppJs = _windowIdForTabJs(appUrl); // Navigate to the Dart app: final appTab = await navigateToPage(browser, url: appUrl, isNew: true); // Click on the Dart Debug Extension icon: - final worker = (await serviceWorkerTarget.worker)!; - await Future.delayed(Duration(seconds: executionContextDelay)); - await worker.evaluate(clickIconJs); + await workerEvalDelay(); + await clickOnExtensionIcon(worker); // Verify the extension opened the Dart docs in the same window: var devToolsTabTarget = await browser.waitForTarget( (target) => target.url.contains(devToolsUrlFragment)); final devToolsPage = await devToolsTabTarget.page; - final windowIdForDevToolsJs = _windowIdForTabJs(devToolsPage.url!); - var devToolsWindowId = - (await worker.evaluate(windowIdForDevToolsJs)) as int?; - var appWindowId = (await worker.evaluate(windowIdForAppJs)) as int?; + var devToolsWindowId = await _getWindowId( + devToolsPage.url!, + worker: worker, + ); + var appWindowId = await _getWindowId(appUrl, worker: worker); expect(devToolsWindowId == appWindowId, isTrue); // Close the DevTools tab: var devToolsTab = await devToolsTabTarget.page; @@ -168,13 +161,15 @@ void main() async { // Navigate to the Dart app: await navigateToPage(browser, url: appUrl); // Click on the Dart Debug Extension icon: - await worker.evaluate(clickIconJs); + await clickOnExtensionIcon(worker); // Verify the extension opened DevTools in a different window: devToolsTabTarget = await browser.waitForTarget( (target) => target.url.contains(devToolsUrlFragment)); - devToolsWindowId = - (await worker.evaluate(windowIdForDevToolsJs)) as int?; - appWindowId = (await worker.evaluate(windowIdForAppJs)) as int?; + devToolsWindowId = await _getWindowId( + devToolsPage.url!, + worker: worker, + ); + appWindowId = await _getWindowId(appUrl, worker: worker); expect(devToolsWindowId == appWindowId, isFalse); // Close the DevTools tab: devToolsTab = await devToolsTabTarget.page; @@ -183,9 +178,84 @@ void main() async { }); }); } + + for (var isFlutterApp in [true, false]) { + group(isFlutterApp ? 'internal Flutter app' : 'internal Dart app', () { + late Browser browser; + late Worker worker; + + setUpAll(() async { + // TODO(elliette): Only start a TestServer, that way we can get rid of + // the launchChrome parameter: https://github.com/dart-lang/webdev/issues/1779 + await context.setUp( + serveDevTools: true, + launchChrome: false, + useSse: true, + enableDebugExtension: true, + ); + browser = await puppeteer.launch( + devTools: true, + headless: false, + timeout: Duration(seconds: 60), + args: [ + '--load-extension=$extensionPath', + '--disable-extensions-except=$extensionPath', + '--disable-features=DialMediaRouteProvider', + ], + ); + + final serviceWorkerTarget = await browser + .waitForTarget((target) => target.type == 'service_worker'); + worker = (await serviceWorkerTarget.worker)!; + }); + + tearDown(() async { + await workerEvalDelay(); + await worker.evaluate(_clearStorageJs()); + }); + + tearDownAll(() async { + await browser.close(); + }); + + test('the debug info for a Dart app is saved in session storage', + () async { + + }); + }); + } }); } +Future _getTabId( + String url, { + required Worker worker, +}) async { + final jsExpression = _tabIdForTabJs(url); + return (await worker.evaluate(jsExpression)) as int; +} + +Future _getWindowId( + String url, { + required Worker worker, +}) async { + final jsExpression = _windowIdForTabJs(url); + return (await worker.evaluate(jsExpression)) as int?; +} + +Future _fetchStorageObj( + String storageKey, { + required String storageArea, + required Worker worker, +}) async { + final storageObj = await worker.evaluate(_fetchStorageObjJs( + storageKey, + storageArea: storageArea, + )); + final json = storageObj[storageKey]; + return serializers.deserialize(jsonDecode(json)) as T; +} + String _tabIdForTabJs(String tabUrl) { return ''' async () => { @@ -234,4 +304,4 @@ String _clearStorageJs() { return true; } '''; -} +} \ No newline at end of file From d767dacdd65d16ba3b7a17a43732401e6a666142 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Mon, 5 Dec 2022 13:42:35 -0800 Subject: [PATCH 07/13] Print out targets --- dwds/test/fixtures/context.dart | 2 + dwds/test/puppeteer/extension_test.dart | 65 +++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index 965f6ca9f..6644cdabb 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -372,6 +372,8 @@ class TestContext { expressionCompiler, spawnDds, ddcService, + isFlutterApp, + isInternalBuild ); _appUrl = basePath.isEmpty diff --git a/dwds/test/puppeteer/extension_test.dart b/dwds/test/puppeteer/extension_test.dart index b1f1fa9a4..fcdf537c0 100644 --- a/dwds/test/puppeteer/extension_test.dart +++ b/dwds/test/puppeteer/extension_test.dart @@ -176,9 +176,54 @@ void main() async { await devToolsTab.close(); await appTab.close(); }); - }); + }, skip: true); } + group('external apps', () { + late Browser browser; + late Worker worker; + + setUpAll(() async { + // TODO(elliette): Only start a TestServer, that way we can get rid of + // the launchChrome parameter: https://github.com/dart-lang/webdev/issues/1779 + await context.setUp( + serveDevTools: true, + launchChrome: false, + useSse: true, + enableDebugExtension: true, + isInternalBuild: true, + ); + browser = await puppeteer.launch( + devTools: true, + headless: false, + timeout: Duration(seconds: 60), + args: [ + '--load-extension=$extensionPath', + '--disable-extensions-except=$extensionPath', + '--disable-features=DialMediaRouteProvider', + ], + ); + + final serviceWorkerTarget = await browser + .waitForTarget((target) => target.type == 'service_worker'); + worker = (await serviceWorkerTarget.worker)!; + }); + + tearDown(() async { + await workerEvalDelay(); + await worker.evaluate(_clearStorageJs()); + }); + + tearDownAll(() async { + await browser.close(); + }); + + test('No additional panels are added in Chrome DevTools', () async { + // TODO + }); + }, skip: true); + + for (var isFlutterApp in [true, false]) { group(isFlutterApp ? 'internal Flutter app' : 'internal Dart app', () { late Browser browser; @@ -192,6 +237,8 @@ void main() async { launchChrome: false, useSse: true, enableDebugExtension: true, + isFlutterApp: isFlutterApp, + isInternalBuild: true, ); browser = await puppeteer.launch( devTools: true, @@ -218,8 +265,20 @@ void main() async { await browser.close(); }); - test('the debug info for a Dart app is saved in session storage', - () async {}); + test('the correct additional panels are added to Chrome DevTools', + () async { + final appUrl = context.appUrl; + // Navigate to the Dart app: + final appTab = + await navigateToPage(browser, url: appUrl, isNew: true); + // Verify that we have debug info for the Dart app: + await workerEvalDelay(); + final targets = browser.targets; + for (var target in targets) { + print(target.url); + } + // Find the chrome devtools target: + }); }); } }); From 0982d2b6b4ce70fedb26f076e36357b5476d8ef1 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Tue, 6 Dec 2022 10:38:48 -0800 Subject: [PATCH 08/13] Add TODOs to test with issue links --- dwds/test/puppeteer/extension_test.dart | 109 +++--------------------- 1 file changed, 10 insertions(+), 99 deletions(-) diff --git a/dwds/test/puppeteer/extension_test.dart b/dwds/test/puppeteer/extension_test.dart index fcdf537c0..5515def01 100644 --- a/dwds/test/puppeteer/extension_test.dart +++ b/dwds/test/puppeteer/extension_test.dart @@ -180,107 +180,18 @@ void main() async { } group('external apps', () { - late Browser browser; - late Worker worker; - - setUpAll(() async { - // TODO(elliette): Only start a TestServer, that way we can get rid of - // the launchChrome parameter: https://github.com/dart-lang/webdev/issues/1779 - await context.setUp( - serveDevTools: true, - launchChrome: false, - useSse: true, - enableDebugExtension: true, - isInternalBuild: true, - ); - browser = await puppeteer.launch( - devTools: true, - headless: false, - timeout: Duration(seconds: 60), - args: [ - '--load-extension=$extensionPath', - '--disable-extensions-except=$extensionPath', - '--disable-features=DialMediaRouteProvider', - ], - ); - - final serviceWorkerTarget = await browser - .waitForTarget((target) => target.type == 'service_worker'); - worker = (await serviceWorkerTarget.worker)!; - }); - - tearDown(() async { - await workerEvalDelay(); - await worker.evaluate(_clearStorageJs()); - }); - - tearDownAll(() async { - await browser.close(); - }); - - test('No additional panels are added in Chrome DevTools', () async { - // TODO - }); + // TODO(elliette): Test that extension does not add any panels to Chrome + // DevTools. Requires either of the following to be resolved: + // - https://github.com/puppeteer/puppeteer/issues/9371 + // - https://github.com/xvrh/puppeteer-dart/issues/201 }, skip: true); - - for (var isFlutterApp in [true, false]) { - group(isFlutterApp ? 'internal Flutter app' : 'internal Dart app', () { - late Browser browser; - late Worker worker; - - setUpAll(() async { - // TODO(elliette): Only start a TestServer, that way we can get rid of - // the launchChrome parameter: https://github.com/dart-lang/webdev/issues/1779 - await context.setUp( - serveDevTools: true, - launchChrome: false, - useSse: true, - enableDebugExtension: true, - isFlutterApp: isFlutterApp, - isInternalBuild: true, - ); - browser = await puppeteer.launch( - devTools: true, - headless: false, - timeout: Duration(seconds: 60), - args: [ - '--load-extension=$extensionPath', - '--disable-extensions-except=$extensionPath', - '--disable-features=DialMediaRouteProvider', - ], - ); - - final serviceWorkerTarget = await browser - .waitForTarget((target) => target.type == 'service_worker'); - worker = (await serviceWorkerTarget.worker)!; - }); - - tearDown(() async { - await workerEvalDelay(); - await worker.evaluate(_clearStorageJs()); - }); - - tearDownAll(() async { - await browser.close(); - }); - - test('the correct additional panels are added to Chrome DevTools', - () async { - final appUrl = context.appUrl; - // Navigate to the Dart app: - final appTab = - await navigateToPage(browser, url: appUrl, isNew: true); - // Verify that we have debug info for the Dart app: - await workerEvalDelay(); - final targets = browser.targets; - for (var target in targets) { - print(target.url); - } - // Find the chrome devtools target: - }); - }); - } + group('internal apps', () { + // TODO(elliette): Test that extension does not adds the correct panels to + // Chrome DevTools. Requires either of the following to be resolved: + // - https://github.com/puppeteer/puppeteer/issues/9371 + // - https://github.com/xvrh/puppeteer-dart/issues/201 + }, skip: true); }); } From a22edbe4de40be29bd0510ab5872f2cc52ab76f8 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Tue, 6 Dec 2022 13:25:48 -0800 Subject: [PATCH 09/13] Messy commit --- dwds/test/puppeteer/extension_test.dart | 171 +++++++++++++++++++----- dwds/test/puppeteer/test_utils.dart | 39 ++++++ 2 files changed, 177 insertions(+), 33 deletions(-) diff --git a/dwds/test/puppeteer/extension_test.dart b/dwds/test/puppeteer/extension_test.dart index 7d76fc24f..f0b77776f 100644 --- a/dwds/test/puppeteer/extension_test.dart +++ b/dwds/test/puppeteer/extension_test.dart @@ -37,27 +37,18 @@ void main() async { late Worker worker; setUpAll(() async { - // TODO(elliette): Only start a TestServer, that way we can get rid of - // the launchChrome parameter: https://github.com/dart-lang/webdev/issues/1779 - await context.setUp( + browser = await setUpExtensionTest( + context, + extensionPath: extensionPath, serveDevTools: true, - launchChrome: false, useSse: useSse, - enableDebugExtension: true, - ); - browser = await puppeteer.launch( - headless: false, - timeout: Duration(seconds: 60), - args: [ - '--load-extension=$extensionPath', - '--disable-extensions-except=$extensionPath', - '--disable-features=DialMediaRouteProvider', - ], ); + worker = await getServiceWorker(browser); - final serviceWorkerTarget = await browser - .waitForTarget((target) => target.type == 'service_worker'); - worker = (await serviceWorkerTarget.worker)!; + // Navigate to the Chrome extension page instead of the blank tab + // opened by Chrome. This is helpful for local debugging. + final blankTab = await navigateToPage(browser, url: 'about:blank'); + await blankTab.goto('chrome://extensions/'); }); tearDown(() async { @@ -165,6 +156,7 @@ void main() async { // Verify the extension opened DevTools in a different window: devToolsTabTarget = await browser.waitForTarget( (target) => target.url.contains(devToolsUrlFragment)); + print('GETTING WINDOW ID FOR ${devToolsPage.url!}'); devToolsWindowId = await _getWindowId( devToolsPage.url!, worker: worker, @@ -198,6 +190,7 @@ void main() async { await appTab.bringToFront(); // Verify that the Dart DevTools tab closes: await devToolsTabTarget.onClose; + await appTab.close(); }); test('Closing the Dart app while debugging closes DevTools', () async { @@ -222,19 +215,129 @@ void main() async { }); } - group('external apps', () { - // TODO(elliette): Test that extension does not add any panels to Chrome - // DevTools. Requires either of the following to be resolved: - // - https://github.com/puppeteer/puppeteer/issues/9371 - // - https://github.com/xvrh/puppeteer-dart/issues/201 - }, skip: true); - - group('internal apps', () { - // TODO(elliette): Test that extension does not adds the correct panels to - // Chrome DevTools. Requires either of the following to be resolved: - // - https://github.com/puppeteer/puppeteer/issues/9371 - // - https://github.com/xvrh/puppeteer-dart/issues/201 - }, skip: true); +/* + group('external builds', () { + for (var isFlutterApp in [true, false]) { + group(isFlutterApp ? 'flutter apps' : 'dart apps', () { + late Browser browser; + late Worker worker; + + setUpAll(() async { + browser = await setUpExtensionTest( + context, + extensionPath: extensionPath, + serveDevTools: true, + isInternalBuild: false, + isFlutterApp: isFlutterApp, + ); + worker = await getServiceWorker(browser); + }); + + tearDown(() async { + await workerEvalDelay(); + await worker.evaluate(_clearStorageJs()); + }); + + tearDownAll(() async { + await browser.close(); + }); + test( + 'isFlutterApp=$isFlutterApp and isInternalBuild=false are saved in storage', + () async { + final appUrl = context.appUrl; + // Navigate to the Dart app: + final appTab = + await navigateToPage(browser, url: appUrl, isNew: true); + // Verify that we have debug info for the Dart app: + await workerEvalDelay(); + final appTabId = await _getTabId(appUrl, worker: worker); + final debugInfoKey = '$appTabId-debugInfo'; + final debugInfo = await _fetchStorageObj( + debugInfoKey, + storageArea: 'session', + worker: worker, + ); + expect(debugInfo.isInternalBuild, equals(false)); + expect(debugInfo.isFlutterApp, equals(isFlutterApp)); + await appTab.close(); + }); + + test('No additional panels are added in Chrome DevTools', () async { + // TODO(elliette): Requires either of the following to be resolved: + // - https://github.com/puppeteer/puppeteer/issues/9371 + // - https://github.com/xvrh/puppeteer-dart/issues/201 + }, skip: true); + }); + } + }); + + */ + + /* + group('internal builds', () { + for (var isFlutterApp in [true, false]) { + group(isFlutterApp ? 'flutter apps' : 'dart apps', () { + late Browser browser; + late Worker worker; + + setUpAll(() async { + browser = await setUpExtensionTest( + context, + extensionPath: extensionPath, + serveDevTools: true, + isInternalBuild: true, + isFlutterApp: isFlutterApp, + ); + worker = await getServiceWorker(browser); + }); + + tearDown(() async { + await workerEvalDelay(); + await worker.evaluate(_clearStorageJs()); + }); + + tearDownAll(() async { + await browser.close(); + }); + test( + 'isFlutterApp=$isFlutterApp and isInternalBuild=true are saved in storage', + () async { + final appUrl = context.appUrl; + // Navigate to the Dart app: + final appTab = + await navigateToPage(browser, url: appUrl, isNew: true); + // Verify that we have debug info for the Dart app: + await workerEvalDelay(); + final appTabId = await _getTabId(appUrl, worker: worker); + final debugInfoKey = '$appTabId-debugInfo'; + final debugInfo = await _fetchStorageObj( + debugInfoKey, + storageArea: 'session', + worker: worker, + ); + expect(debugInfo.isInternalBuild, equals(false)); + expect(debugInfo.isFlutterApp, equals(isFlutterApp)); + await appTab.close(); + }); + + test('The Dart Debugger panel is added to Chrome DevTools', () async { + // TODO(elliette): Requires either of the following to be resolved: + // - https://github.com/puppeteer/puppeteer/issues/9371 + // - https://github.com/xvrh/puppeteer-dart/issues/201 + }, skip: true); + + if (isFlutterApp) { + test('The Flutter Inspector panel is added to Chrome DevTools', + () async { + // TODO(elliette): Requires either of the following to be resolved: + // - https://github.com/puppeteer/puppeteer/issues/9371 + // - https://github.com/xvrh/puppeteer-dart/issues/201 + }, skip: true); + } + }); + } + }); + */ }); } @@ -251,7 +354,9 @@ Future _getWindowId( required Worker worker, }) async { final jsExpression = _windowIdForTabJs(url); - return (await worker.evaluate(jsExpression)) as int?; + print(jsExpression); + final result = (await worker.evaluate(jsExpression)) as int?; + return result; } Future _fetchStorageObj( @@ -280,8 +385,8 @@ String _tabIdForTabJs(String tabUrl) { String _windowIdForTabJs(String tabUrl) { return ''' async () => { - const matchingTabs = await chrome.tabs.query({ url: "$tabUrl" }); - const tab = matchingTabs[0]; + const allTabs = await chrome.tabs.query({}); + const tab = allTabs.find((tab) => tab.url == "$tabUrl"); return tab.windowId; } '''; diff --git a/dwds/test/puppeteer/test_utils.dart b/dwds/test/puppeteer/test_utils.dart index 7d8c046b1..46b5ef2f6 100644 --- a/dwds/test/puppeteer/test_utils.dart +++ b/dwds/test/puppeteer/test_utils.dart @@ -8,6 +8,8 @@ import 'dart:io'; import 'package:path/path.dart' as p; import 'package:puppeteer/puppeteer.dart'; +import '../fixtures/context.dart'; + Future buildDebugExtension() async { final currentDir = Directory.current.path; if (!currentDir.endsWith('dwds')) { @@ -24,6 +26,43 @@ Future buildDebugExtension() async { return '$extensionDir/compiled'; } +Future setUpExtensionTest( + TestContext context, { + required String extensionPath, + bool serveDevTools = true, + bool useSse = false, + bool isInternalBuild = false, + bool isFlutterApp = false, + bool openChromeDevTools = false, +}) async { + // TODO(elliette): Only start a TestServer, that way we can get rid of the + // launchChrome parameter: https://github.com/dart-lang/webdev/issues/1779 + await context.setUp( + launchChrome: false, + serveDevTools: serveDevTools, + useSse: useSse, + enableDebugExtension: true, + isInternalBuild: isInternalBuild, + isFlutterApp: isFlutterApp, + ); + return await puppeteer.launch( + devTools: openChromeDevTools, + headless: false, + timeout: Duration(seconds: 60), + args: [ + '--load-extension=$extensionPath', + '--disable-extensions-except=$extensionPath', + '--disable-features=DialMediaRouteProvider', + ], + ); +} + +Future getServiceWorker(Browser browser) async { + final serviceWorkerTarget = + await browser.waitForTarget((target) => target.type == 'service_worker'); + return (await serviceWorkerTarget.worker)!; +} + Future clickOnExtensionIcon(Worker worker) async { return worker.evaluate(_clickIconJs); } From 7214b5b172b4410870683d4d9034c652403981bc Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Tue, 6 Dec 2022 15:04:40 -0800 Subject: [PATCH 10/13] Update test --- dwds/test/puppeteer/extension_test.dart | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/dwds/test/puppeteer/extension_test.dart b/dwds/test/puppeteer/extension_test.dart index f0b77776f..2ab203158 100644 --- a/dwds/test/puppeteer/extension_test.dart +++ b/dwds/test/puppeteer/extension_test.dart @@ -125,15 +125,15 @@ void main() async { // Verify the extension opened the Dart docs in the same window: var devToolsTabTarget = await browser.waitForTarget( (target) => target.url.contains(devToolsUrlFragment)); - final devToolsPage = await devToolsTabTarget.page; + var devToolsTab = await devToolsTabTarget.page; var devToolsWindowId = await _getWindowId( - devToolsPage.url!, + devToolsTab.url!, worker: worker, ); var appWindowId = await _getWindowId(appUrl, worker: worker); expect(devToolsWindowId == appWindowId, isTrue); // Close the DevTools tab: - var devToolsTab = await devToolsTabTarget.page; + devToolsTab = await devToolsTabTarget.page; await devToolsTab.close(); // Navigate to the extension settings page: final extensionOrigin = getExtensionOrigin(browser); @@ -156,9 +156,9 @@ void main() async { // Verify the extension opened DevTools in a different window: devToolsTabTarget = await browser.waitForTarget( (target) => target.url.contains(devToolsUrlFragment)); - print('GETTING WINDOW ID FOR ${devToolsPage.url!}'); + devToolsTab = await devToolsTabTarget.page; devToolsWindowId = await _getWindowId( - devToolsPage.url!, + devToolsTab.url!, worker: worker, ); appWindowId = await _getWindowId(appUrl, worker: worker); @@ -215,7 +215,6 @@ void main() async { }); } -/* group('external builds', () { for (var isFlutterApp in [true, false]) { group(isFlutterApp ? 'flutter apps' : 'dart apps', () { @@ -271,9 +270,6 @@ void main() async { } }); - */ - - /* group('internal builds', () { for (var isFlutterApp in [true, false]) { group(isFlutterApp ? 'flutter apps' : 'dart apps', () { @@ -337,7 +333,6 @@ void main() async { }); } }); - */ }); } @@ -354,9 +349,7 @@ Future _getWindowId( required Worker worker, }) async { final jsExpression = _windowIdForTabJs(url); - print(jsExpression); - final result = (await worker.evaluate(jsExpression)) as int?; - return result; + return (await worker.evaluate(jsExpression)) as int?; } Future _fetchStorageObj( @@ -385,8 +378,8 @@ String _tabIdForTabJs(String tabUrl) { String _windowIdForTabJs(String tabUrl) { return ''' async () => { - const allTabs = await chrome.tabs.query({}); - const tab = allTabs.find((tab) => tab.url == "$tabUrl"); + const matchingTabs = await chrome.tabs.query({ url: "$tabUrl" }); + const tab = matchingTabs[0]; return tab.windowId; } '''; From fa0f997d17733d11130c910565a7c36a37614535 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Tue, 6 Dec 2022 15:17:01 -0800 Subject: [PATCH 11/13] Test succeeds --- dwds/test/puppeteer/extension_test.dart | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/dwds/test/puppeteer/extension_test.dart b/dwds/test/puppeteer/extension_test.dart index 2ab203158..1b558faf8 100644 --- a/dwds/test/puppeteer/extension_test.dart +++ b/dwds/test/puppeteer/extension_test.dart @@ -32,7 +32,7 @@ void main() async { }); for (var useSse in [true, false]) { - group(useSse ? 'with SSE' : 'with WebSockets', () { + group(useSse ? 'connected with SSE:' : 'connected with WebSockets:', () { late Browser browser; late Worker worker; @@ -170,7 +170,7 @@ void main() async { }); test( - 'Navigating away from the Dart app while debugging closes DevTools', + 'navigating away from the Dart app while debugging closes DevTools', () async { final appUrl = context.appUrl; final devToolsUrlFragment = @@ -193,7 +193,7 @@ void main() async { await appTab.close(); }); - test('Closing the Dart app while debugging closes DevTools', () async { + test('closing the Dart app while debugging closes DevTools', () async { final appUrl = context.appUrl; final devToolsUrlFragment = useSse ? 'debugger?uri=sse' : 'debugger?uri=ws'; @@ -215,9 +215,9 @@ void main() async { }); } - group('external builds', () { + group('connected to an externally built', () { for (var isFlutterApp in [true, false]) { - group(isFlutterApp ? 'flutter apps' : 'dart apps', () { + group(isFlutterApp ? 'Flutter app:' : 'Dart app:', () { late Browser browser; late Worker worker; @@ -261,7 +261,7 @@ void main() async { await appTab.close(); }); - test('No additional panels are added in Chrome DevTools', () async { + test('no additional panels are added in Chrome DevTools', () async { // TODO(elliette): Requires either of the following to be resolved: // - https://github.com/puppeteer/puppeteer/issues/9371 // - https://github.com/xvrh/puppeteer-dart/issues/201 @@ -270,9 +270,9 @@ void main() async { } }); - group('internal builds', () { + group('connected to an internally built', () { for (var isFlutterApp in [true, false]) { - group(isFlutterApp ? 'flutter apps' : 'dart apps', () { + group(isFlutterApp ? 'Flutter app:' : 'Dart app:', () { late Browser browser; late Worker worker; @@ -311,19 +311,19 @@ void main() async { storageArea: 'session', worker: worker, ); - expect(debugInfo.isInternalBuild, equals(false)); + expect(debugInfo.isInternalBuild, equals(true)); expect(debugInfo.isFlutterApp, equals(isFlutterApp)); await appTab.close(); }); - test('The Dart Debugger panel is added to Chrome DevTools', () async { + test('the Dart Debugger panel is added to Chrome DevTools', () async { // TODO(elliette): Requires either of the following to be resolved: // - https://github.com/puppeteer/puppeteer/issues/9371 // - https://github.com/xvrh/puppeteer-dart/issues/201 }, skip: true); if (isFlutterApp) { - test('The Flutter Inspector panel is added to Chrome DevTools', + test('the Flutter Inspector panel is added to Chrome DevTools', () async { // TODO(elliette): Requires either of the following to be resolved: // - https://github.com/puppeteer/puppeteer/issues/9371 From e7a011ca8c7b9122b46b120bb6df4d38a20da805 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Tue, 6 Dec 2022 15:19:08 -0800 Subject: [PATCH 12/13] Update lifeline test --- dwds/test/puppeteer/lifeline_test.dart | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/dwds/test/puppeteer/lifeline_test.dart b/dwds/test/puppeteer/lifeline_test.dart index aed47d747..600db189b 100644 --- a/dwds/test/puppeteer/lifeline_test.dart +++ b/dwds/test/puppeteer/lifeline_test.dart @@ -24,23 +24,12 @@ void main() async { group('MV3 Debug Extension Lifeline Connection', () { setUpAll(() async { extensionPath = await buildDebugExtension(); - await context.setUp( - launchChrome: false, - enableDebugExtension: true, + browser = await setUpExtensionTest( + context, + extensionPath: extensionPath, + serveDevTools: true, ); - browser = await puppeteer.launch( - headless: false, - timeout: Duration(seconds: 60), - args: [ - '--load-extension=$extensionPath', - '--disable-extensions-except=$extensionPath', - '--disable-features=DialMediaRouteProvider', - ], - ); - - final serviceWorkerTarget = await browser - .waitForTarget((target) => target.type == 'service_worker'); - worker = (await serviceWorkerTarget.worker)!; + worker = await getServiceWorker(browser); }); tearDownAll(() async { From 2e2523e10492892deb8c85cb7d5c089bc06074ae Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Tue, 6 Dec 2022 15:23:48 -0800 Subject: [PATCH 13/13] Add Dart debugger / Flutter inspector panels to Chrome DevTools --- dwds/CHANGELOG.md | 4 +- .../web/debug_session.dart | 4 +- dwds/debug_extension_mv3/web/panel.html | 2 +- dwds/test/fixtures/context.dart | 39 ++++++++++--------- dwds/test/puppeteer/extension_test.dart | 4 +- 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index 9ef3f6aba..ebe8a4c96 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -9,9 +9,9 @@ - Include the entire exception description up to the stacktrace in `mapExceptionStackTrace`. - Allow enabling experiments in the expression compiler service. +- Include an optional param to `Dwds.start` to indicate whether it a Flutter app + or not. - Pre-warm expression compiler cache to speed up Flutter Inspector loading. -- Include an optional param to `Dwds.start` to indicate whether the connected - app is a Flutter app. ## 16.0.1 diff --git a/dwds/debug_extension_mv3/web/debug_session.dart b/dwds/debug_extension_mv3/web/debug_session.dart index 4a76f10c0..4e265c392 100644 --- a/dwds/debug_extension_mv3/web/debug_session.dart +++ b/dwds/debug_extension_mv3/web/debug_session.dart @@ -239,7 +239,7 @@ void _forwardChromeDebuggerEventToDwds( if (method == 'Debugger.scriptParsed') { debugSession.sendBatchedEvent(event); } else { - debugSession.sendEvent(event); + debugSession.sendEvent(event); } } @@ -289,7 +289,7 @@ void _removeDebugSession(_DebugSession debugSession) { // https://github.com/dart-lang/webdev/pull/1595#issuecomment-1116773378 final event = _extensionEventFor('DebugExtension.detached', js_util.jsify({})); - debugSession.sendEvent(event); + debugSession.sendEvent(event); debugSession.close(); final removed = _debugSessions.remove(debugSession); if (!removed) { diff --git a/dwds/debug_extension_mv3/web/panel.html b/dwds/debug_extension_mv3/web/panel.html index d5535a066..f7e8d6924 100644 --- a/dwds/debug_extension_mv3/web/panel.html +++ b/dwds/debug_extension_mv3/web/panel.html @@ -8,4 +8,4 @@

Panel

- \ No newline at end of file + diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index d79b05ce5..2fbaef572 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -355,25 +355,26 @@ class TestContext { final connection = ChromeConnection('localhost', debugPort); _testServer = await TestServer.start( - hostname, - port, - assetHandler, - assetReader, - requireStrategy, - pathToServe, - buildResults, - () async => connection, - serveDevTools, - enableDebugExtension, - autoRun, - enableDebugging, - useSse, - urlEncoder, - expressionCompiler, - spawnDds, - ddcService, - isFlutterApp, - isInternalBuild); + hostname, + port, + assetHandler, + assetReader, + requireStrategy, + pathToServe, + buildResults, + () async => connection, + serveDevTools, + enableDebugExtension, + autoRun, + enableDebugging, + useSse, + urlEncoder, + expressionCompiler, + spawnDds, + ddcService, + isFlutterApp, + isInternalBuild, + ); _appUrl = basePath.isEmpty ? 'http://localhost:$port/$path' diff --git a/dwds/test/puppeteer/extension_test.dart b/dwds/test/puppeteer/extension_test.dart index 1b558faf8..348a2d8e6 100644 --- a/dwds/test/puppeteer/extension_test.dart +++ b/dwds/test/puppeteer/extension_test.dart @@ -215,7 +215,7 @@ void main() async { }); } - group('connected to an externally built', () { + group('connected to an externally-built', () { for (var isFlutterApp in [true, false]) { group(isFlutterApp ? 'Flutter app:' : 'Dart app:', () { late Browser browser; @@ -270,7 +270,7 @@ void main() async { } }); - group('connected to an internally built', () { + group('connected to an internally-built', () { for (var isFlutterApp in [true, false]) { group(isFlutterApp ? 'Flutter app:' : 'Dart app:', () { late Browser browser;