From 8c225550dae7bd34fd72d7fbeef1decf5b31c123 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Wed, 29 Nov 2023 13:05:34 -0800 Subject: [PATCH] Prepare Dart Debug Extension for MV3 release (#2293) --- dwds/debug_extension_mv3/pubspec.yaml | 2 +- .../tool/build_extension.dart | 16 ++-- .../web/debug_session.dart | 8 +- .../web/lifeline_connection.dart | 27 ------ .../web/lifeline_ports.dart | 94 ------------------- .../debug_extension_mv3/web/manifest_mv2.json | 2 +- .../debug_extension_mv3/web/manifest_mv3.json | 2 +- dwds/test/puppeteer/lifeline_test.dart | 93 ------------------ 8 files changed, 12 insertions(+), 232 deletions(-) delete mode 100644 dwds/debug_extension_mv3/web/lifeline_connection.dart delete mode 100644 dwds/debug_extension_mv3/web/lifeline_ports.dart delete mode 100644 dwds/test/puppeteer/lifeline_test.dart diff --git a/dwds/debug_extension_mv3/pubspec.yaml b/dwds/debug_extension_mv3/pubspec.yaml index a23537f75..2fe28cf89 100644 --- a/dwds/debug_extension_mv3/pubspec.yaml +++ b/dwds/debug_extension_mv3/pubspec.yaml @@ -1,6 +1,6 @@ name: mv3_extension publish_to: none -version: 1.38.0 +version: 2.0.0 homepage: https://github.com/dart-lang/webdev description: >- A Chrome extension for Dart debugging. diff --git a/dwds/debug_extension_mv3/tool/build_extension.dart b/dwds/debug_extension_mv3/tool/build_extension.dart index 5226e346e..66bc1cb4c 100644 --- a/dwds/debug_extension_mv3/tool/build_extension.dart +++ b/dwds/debug_extension_mv3/tool/build_extension.dart @@ -9,8 +9,8 @@ // Run from the extension root directory: // - For dev: dart run tool/build_extension.dart -// - For prod: dart run tool/build_extension.dart prod -// - For MV3: dart run tool/build_extension.dart --mv3 +// - For prod: dart run tool/build_extension.dart --prod +// - For MV2: dart run tool/build_extension.dart --mv2 import 'dart:convert'; import 'dart:io'; @@ -19,26 +19,26 @@ import 'package:args/args.dart'; import 'package:path/path.dart' as p; const _prodFlag = 'prod'; -const _mv3Flag = 'mv3'; +const _mv2Flag = 'mv2'; void main(List arguments) async { final parser = ArgParser() ..addFlag(_prodFlag, negatable: true, defaultsTo: false) - ..addFlag(_mv3Flag, negatable: true, defaultsTo: false); + ..addFlag(_mv2Flag, negatable: true, defaultsTo: false); final argResults = parser.parse(arguments); exitCode = await run( isProd: argResults[_prodFlag] as bool, - isMV3: argResults[_mv3Flag] as bool, + isMV2: argResults[_mv2Flag] as bool, ); if (exitCode != 0) { _logWarning('Run terminated unexpectedly with exit code: $exitCode'); } } -Future run({required bool isProd, required bool isMV3}) async { +Future run({required bool isProd, required bool isMV2}) async { _logInfo( - 'Building ${isMV3 ? 'MV3' : 'MV2'} extension for ${isProd ? 'prod' : 'dev'}', + 'Building ${isMV2 ? 'MV2' : 'MV3'} extension for ${isProd ? 'prod' : 'dev'}', ); _logInfo('Compiling extension with dart2js to /compiled directory'); final compileStep = await Process.start( @@ -50,7 +50,7 @@ Future run({required bool isProd, required bool isMV3}) async { if (compileExitCode != 0) { return compileExitCode; } - final manifestFileName = isMV3 ? 'manifest_mv3' : 'manifest_mv2'; + final manifestFileName = isMV2 ? 'manifest_mv2' : 'manifest_mv3'; _logInfo('Copying manifest.json to /compiled directory'); try { File(p.join('web', '$manifestFileName.json')).copySync( diff --git a/dwds/debug_extension_mv3/web/debug_session.dart b/dwds/debug_extension_mv3/web/debug_session.dart index 6333ed528..898a160fb 100644 --- a/dwds/debug_extension_mv3/web/debug_session.dart +++ b/dwds/debug_extension_mv3/web/debug_session.dart @@ -25,7 +25,6 @@ import 'cider_connection.dart'; import 'cross_extension_communication.dart'; import 'data_serializers.dart'; import 'data_types.dart'; -import 'lifeline_ports.dart'; import 'logger.dart'; import 'messaging.dart'; import 'storage.dart'; @@ -381,8 +380,6 @@ Future _connectToDwds({ cancelOnError: true, ); _debugSessions.add(debugSession); - // Create a connection with the lifeline port to keep the debug session alive: - await maybeCreateLifelinePort(dartAppTabId); // Send a DevtoolsRequest to the event stream: final tabUrl = await _getTabUrl(dartAppTabId); debugSession.sendEvent( @@ -592,10 +589,7 @@ void _removeDebugSession(_DebugSession debugSession) { debugSession.sendEvent(event); debugSession.close(); final removed = _debugSessions.remove(debugSession); - if (removed) { - // Maybe remove the corresponding lifeline connection: - maybeRemoveLifelinePort(debugSession.appTabId); - } else { + if (!removed) { debugWarn('Could not remove debug session.'); } } diff --git a/dwds/debug_extension_mv3/web/lifeline_connection.dart b/dwds/debug_extension_mv3/web/lifeline_connection.dart deleted file mode 100644 index 948bf3507..000000000 --- a/dwds/debug_extension_mv3/web/lifeline_connection.dart +++ /dev/null @@ -1,27 +0,0 @@ -// 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. - -import 'chrome_api.dart'; -import 'logger.dart'; - -void main() { - _connectToLifelinePort(); -} - -void _connectToLifelinePort() { - debugLog( - 'Connecting to lifeline port at ${_currentTime()}.', - prefix: 'Dart Debug Extension', - ); - chrome.runtime.connect( - // extensionId - null, - ConnectInfo(name: 'keepAlive'), - ); -} - -String _currentTime() { - final date = DateTime.now(); - return '${date.hour}:${date.minute}::${date.second}'; -} diff --git a/dwds/debug_extension_mv3/web/lifeline_ports.dart b/dwds/debug_extension_mv3/web/lifeline_ports.dart deleted file mode 100644 index d43ad9b4f..000000000 --- a/dwds/debug_extension_mv3/web/lifeline_ports.dart +++ /dev/null @@ -1,94 +0,0 @@ -// 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. - -// Keeps the background service worker alive for the duration of a Dart debug -// session by using the workaround described in: -// https://bugs.chromium.org/p/chromium/issues/detail?id=1152255#c21 -@JS() -library lifeline_ports; - -import 'dart:async'; -import 'package:js/js.dart'; - -import 'chrome_api.dart'; -import 'debug_session.dart'; -import 'logger.dart'; -import 'utils.dart'; - -Port? _lifelinePort; -int? _lifelineTab; - -Future maybeCreateLifelinePort(int tabId) async { - // This is only necessary for Manifest V3 extensions: - if (!isMV3) return; - // Don't create a lifeline port if we already have one (meaning another Dart - // app is currently being debugged): - if (_lifelinePort != null) { - debugWarn('Port already exists.'); - return; - } - // Start the keep-alive logic when the port connects: - chrome.runtime.onConnect.addListener(allowInterop(_keepLifelinePortAlive)); - // Inject the connection script into the current Dart tab, that way the tab - // will connect to the port: - debugLog('Creating lifeline port.'); - _lifelineTab = tabId; - await injectScript('lifeline_connection.dart.js', tabId: tabId); -} - -void maybeRemoveLifelinePort(int removedTabId) { - // This is only necessary for Manifest V3 extensions: - if (!isMV3) return; - // If the removed Dart tab hosted the lifeline port connection, see if there - // are any other Dart tabs to connect to. Otherwise disconnect the port. - if (_lifelineTab == removedTabId) { - if (existsActiveDebugSession) { - _lifelineTab = latestAppBeingDebugged; - debugLog('Reconnecting lifeline port to a new Dart tab: $_lifelineTab.'); - _reconnectToLifelinePort(); - } else { - _lifelineTab = null; - debugLog('No more Dart tabs, disconnecting from lifeline port.'); - _disconnectFromLifelinePort(); - } - } -} - -void _keepLifelinePortAlive(Port port) { - final portName = port.name ?? ''; - if (portName != 'keepAlive') return; - _lifelinePort = port; - // Reconnect to the lifeline port every 5 minutes, as per: - // https://bugs.chromium.org/p/chromium/issues/detail?id=1146434#c6 - Timer(Duration(minutes: 5), () { - debugLog('5 minutes have elapsed, therefore reconnecting.'); - _reconnectToLifelinePort(); - }); -} - -void _reconnectToLifelinePort() { - debugLog('Reconnecting...'); - if (_lifelinePort == null) { - debugWarn('Could not find a lifeline port.'); - return; - } - if (_lifelineTab == null) { - debugWarn('Could not find a lifeline tab.'); - return; - } - // Disconnect from the port, and then recreate the connection with the current - // Dart tab: - _disconnectFromLifelinePort(); - maybeCreateLifelinePort(_lifelineTab!); - debugLog('Reconnection complete.'); -} - -void _disconnectFromLifelinePort() { - debugLog('Disconnecting...'); - if (_lifelinePort != null) { - _lifelinePort!.disconnect(); - _lifelinePort = null; - debugLog('Disconnection complete.'); - } -} diff --git a/dwds/debug_extension_mv3/web/manifest_mv2.json b/dwds/debug_extension_mv3/web/manifest_mv2.json index 6300fc96e..84cccef73 100644 --- a/dwds/debug_extension_mv3/web/manifest_mv2.json +++ b/dwds/debug_extension_mv3/web/manifest_mv2.json @@ -1,6 +1,6 @@ { "name": "Dart Debug Extension", - "version": "1.40", + "version": "2.0", "manifest_version": 2, "devtools_page": "static_assets/devtools.html", "browser_action": { diff --git a/dwds/debug_extension_mv3/web/manifest_mv3.json b/dwds/debug_extension_mv3/web/manifest_mv3.json index 71320e445..7894ab693 100644 --- a/dwds/debug_extension_mv3/web/manifest_mv3.json +++ b/dwds/debug_extension_mv3/web/manifest_mv3.json @@ -1,6 +1,6 @@ { "name": "Dart Debug Extension", - "version": "1.40", + "version": "2.0", "manifest_version": 3, "devtools_page": "static_assets/devtools.html", "action": { diff --git a/dwds/test/puppeteer/lifeline_test.dart b/dwds/test/puppeteer/lifeline_test.dart deleted file mode 100644 index 50dc7558d..000000000 --- a/dwds/test/puppeteer/lifeline_test.dart +++ /dev/null @@ -1,93 +0,0 @@ -// 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. - -@Timeout(Duration(minutes: 12)) -@Skip('https://github.com/dart-lang/webdev/issues/1788') - -import 'package:puppeteer/puppeteer.dart'; -import 'package:test/test.dart'; -import 'package:test_common/test_sdk_configuration.dart'; - -import '../fixtures/context.dart'; -import '../fixtures/project.dart'; -import 'test_utils.dart'; - -void main() async { - final provider = TestSdkConfigurationProvider(); - final context = TestContext(TestProject.testWithSoundNullSafety, provider); - late Worker worker; - late Browser browser; - late String extensionPath; - - int connectionCount = 0; - - tearDownAll(provider.dispose); - - group('MV3 Debug Extension Lifeline Connection', () { - setUpAll(() async { - extensionPath = await buildDebugExtension(isMV3: true); - browser = await setUpExtensionTest( - context, - extensionPath: extensionPath, - serveDevTools: true, - ); - worker = await getServiceWorker(browser); - }); - - tearDownAll(() async { - await browser.close(); - await context.tearDown(); - }); - - test('connects to a lifeline port', () async { - // Navigate to the Dart app: - final appTab = - await navigateToPage(browser, url: context.appUrl, isNew: true); - await workerEvalDelay(); - // Initiate listeners for the port connection event and the subsequent - // reconnection logs: - final portConnectionFuture = _connectToPort(worker); - appTab.onConsole.listen((ConsoleMessage message) { - final messageText = message.text ?? ''; - if (messageText - .contains('[Dart Debug Extension] Connecting to lifeline port')) { - connectionCount++; - } - }); - // Click on the Dart Debug Extension icon to initiate a debug session: - await clickOnExtensionIcon(worker: worker, backgroundPage: null); - final connectedToPort = await portConnectionFuture; - // Verify that we have connected to the port: - expect(connectedToPort, isTrue); - expect(connectionCount, equals(1)); - // Wait for a little over 5 minutes, and verify that we have reconnected - // to the port again: - await _reconnectToPortDelay(); - expect(connectionCount, equals(2)); - }); - }); -} - -Future _reconnectToPortDelay() async { - await Future.delayed(Duration(minutes: 5) + Duration(seconds: 15)); - return; -} - -Future _connectToPort(Worker worker) async { - return worker.evaluate(_portConnectionJs); -} - -final _portConnectionJs = ''' - async () => { - return new Promise((resolve, reject) => { - chrome.runtime.onConnect.addListener((port) => { - if (port.name == 'keepAlive') { - resolve(true); - } else { - reject(false); - } - }); - }); - } -''';