diff --git a/.github/labeler.yml b/.github/labeler.yml index 5dfc38faf..b8727694f 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -19,4 +19,3 @@ 'dart-debug-extension': - changed-files: - any-glob-to-any-file: 'dwds/debug_extension/**/*' - - any-glob-to-any-file: 'dwds/debug_extension_mv3/**/*' diff --git a/dwds/analysis_options.yaml b/dwds/analysis_options.yaml index 8f1017c53..e01bd3b72 100644 --- a/dwds/analysis_options.yaml +++ b/dwds/analysis_options.yaml @@ -8,10 +8,7 @@ analyzer: # Ignore generated files - "lib/data/*" # Ignore debug extension builds - - "debug_extension/dev_build/*" - - "debug_extension/prod_build/*" - - "debug_extension_mv3/dev_build/*" - - "debug_extension_mv3/prod_build/*" + - "debug_extension/compiled/*" linter: rules: @@ -32,7 +29,7 @@ dart_code_metrics: metrics-exclude: - test/** rules: - # - arguments-ordering + # - arguments-ordering # - avoid-banned-imports - avoid-cascade-after-if-null - avoid-collection-methods-with-unrelated-types diff --git a/dwds/debug_extension/.gitignore b/dwds/debug_extension/.gitignore index 2c628c415..4878cbe8b 100644 --- a/dwds/debug_extension/.gitignore +++ b/dwds/debug_extension/.gitignore @@ -1,4 +1,3 @@ build/ -prod_build/ -dev_build/ +compiled/ extension_key.txt diff --git a/dwds/debug_extension/CHANGELOG.md b/dwds/debug_extension/CHANGELOG.md deleted file mode 100644 index 70604b8bf..000000000 --- a/dwds/debug_extension/CHANGELOG.md +++ /dev/null @@ -1,109 +0,0 @@ -## 1.30 - -- Batch extension `Debugger.scriptParsed` events and send batches every 1000ms - to the server. -- Enable null-safety. -- Replace manual extension allowlist by configuring `externally_connectable` in - the `manifest.json`. See - https://developer.chrome.com/docs/extensions/mv3/manifest/externally_connectable/ - for details. - -## 1.29 - -- Notify the debugger and inspector panels when the debug session is - disconnected. -- Provide a detailed error message when the debugger fails to connect. -- Send an event to the server when the debugger is detached. -- Fix compilation errors when the extension is built with DDC. - -## 1.28 - -- Support Chrome 100 updates to the remote debugging protocol. - -## 1.27 - -- Support embedded debugger and inspector in Chrome DevTools for Flutter Web - apps. - -## 1.26 - -- Support embedded debugging experience in environments with no Dart app ID. - -## 1.25 - -- Embed Dart DevTools in Chrome DevTools. - -## 1.24 - -- Detect Dart applications in multi-app environments and show an alert. - -## 1.23 - -- Depend on the latest `package:sse` to improve stability of the connection with - many concurrent requests. - -## 1.22 - -- Detect Dart applications and update the icon accordingly. - -## 1.21 - -- Detect authentication issues and prompt accordingly. - -## 1.20 - -- Return response when `dwds.startDebugging` is called. - -## 1.19 - -- Support cross-extension communication for use with Google specific extensions. - -## 1.18 - -- Depend on the latest `package:sse`. - -## 1.17 - -- Depend on the latest `package:sse`. - -## 1.16 - -- Depend on the latest `package:sse`. - -## 1.15 - -- No longer send script parsed events when skipLists are supported, improving - the IPL of Dart DevTools. - -## 1.14 - -- Depend on the latest `package:sse`. - -## 1.13 - -- Add support for using WebSockets for connection debug backend. - -## 1.12 - -- Update error message to potentially direct users to enable debugging. - -## 1.11 - -- Fix issue where the extension would provide an invalid alert when attempting - to launch for a non Dart application. - -## 1.10 - -- Properly handle `sendCommand` errors. - -## 1.9 - -- Look for Dart applications nested in iframes. - -## 1.8 - -- Add support for batching scriptParsed events. - -## 1.7 - -- Depend on latest `package:sse` to get retry logic. diff --git a/dwds/debug_extension/CONTRIBUTING.md b/dwds/debug_extension/CONTRIBUTING.md index 313f2c503..7f55d0914 100644 --- a/dwds/debug_extension/CONTRIBUTING.md +++ b/dwds/debug_extension/CONTRIBUTING.md @@ -1,22 +1,9 @@ ## Building -> Note: First make the script executable: `chmod +x tool/build_extension.sh` +- For development: `dart run tool/build_extension.dart` +- For release: ` dart run tool/build_extension.dart --prod` -### With DDC (for development): - -``` -./tool/build_extension.sh -``` - -- The DDC-compiled extension will be located in the `/dev_build/web` directory. - -### With dart2js (for release): - -``` -./tool/build_extension.sh prod -``` - -- The dart2js-compiled extension will be located in the `/prod_build` directory. +The dart2js-compiled extension will be located in the `/compiled` directory. ## Local Development @@ -33,7 +20,7 @@ - Visit chrome://extensions - Toggle "Developer mode" on - Click the "Load unpacked" button -- Select the extension directory: `dev_build/web` +- Select the extension directory: `/compiled` ### Debug your local extension @@ -48,42 +35,41 @@ ## Release process -1. Update the version in `web/manifest.json`, `pubspec.yaml`, and in the - `CHANGELOG`. -1. Follow the instructions above to build the dart2js-compiled release version - of the extension. +- Update the version in `web/manifest_mv2.json`, `web/manifest_mv3.json`, `pubspec.yaml`, and in the + `CHANGELOG`. +- Follow the instructions above to build the release version of the extension. > \*At this point, you should manually verify that everything is working by > following the steps in [Local Development](#local-development), except load -> the extension from the `prod_build` directory. You will need to add an -> extension key to the `manifest.json` file in `prod_build` to test locally. +> the extension from the `compiled` directory. You will need to add an extension +> key to the `manifest.json` file in `compiled` to test locally. -3. Open a PR to submit the version change. -1. Once submitted, pull the changes down to your local branch, and create a zip - of the `prod_build` directory (NOT `dev_build/web`). **Remove the Googler - extension key that was added by the builder to the `manifest.json` file.** -1. Rename the zip `version_XX.XX.XX.zip` (eg, `version_1.24.0.zip`) and add it - to the go/dart-debug-extension-zips folder +- Open a PR to submit the version change. +- Once submitted, pull the changes down to your local branch, and create a zip + of the `compiled` directory. **Remove the Googler extension key that was added + by the builder to the `manifest.json` file.** +- Rename the zip `version_XX.XX.XX.zip` (eg, `version_1.24.0.zip`) and add it to + the go/dart-debug-extension-zips folder -> *You must be a Googler to do this. Ask for help if not.* +> _You must be a Googler to do this. Ask for help if not._ -6. Go to the - [Chrome Web Store Developer Dashboard](https://chrome.google.com/webstore/devconsole). -1. At the top-right, under Publisher, select dart-bat. +- Go to the + [Chrome Web Store Developer Dashboard](https://chrome.google.com/webstore/devconsole). +- At the top-right, under Publisher, select dart-bat. -> *If you don’t see dart-bat as an option, you will need someone on the Dart -> team to add you to the dart-bat Google group.* +> _If you don’t see dart-bat as an option, you will need someone on the Dart +> team to add you to the dart-bat Google group._ -7. Under Items, select the "Dart Debug Extension". -1. Go to “Package” then select “Upload new package”. +- Under Items, select the "Dart Debug Extension". +- Go to “Package” then select “Upload new package”. -> *The first time you do this, you will be asked to pay a $5 registration fee. -> The registration fee can be expensed.* +> _The first time you do this, you will be asked to pay a $5 registration fee. +> The registration fee can be expensed._ -9. Upload the zip file you created in step 4. -1. Save as draft, and verify that the new version is correct. -1. Publish. The extension will be published immediately after going through the - review process. +- Upload the zip file you created in step 4. +- Save as draft, and verify that the new version is correct. +- Publish. The extension will be published immediately after going through the + review process. ## Rollback process @@ -92,15 +78,15 @@ > still have to go through the review process, which can take anywhere from a > few hours (most common) to a few days. -1. Find the previous version you want to rollback to in the - go/dart-debug-extension-zips folder. +- Find the previous version you want to rollback to in the + go/dart-debug-extension-zips folder. -> > *You must be a Googler to do this. Ask for help if not.* +> _You must be a Googler to do this. Ask for help if not._ -2. Unzip the version you have chosen, and in `manifest.json` edit the version - number to be the next sequential version after the current "bad" version (eg, - the bad version is `1.28.0` and you are rolling back to version `1.27.0`. - Therefore you change `1.27.0` to `1.29.0`). -1. Re-zip the directory and rename it to the new version number. Add it to the - go/dart-debug-extension-zips folder. -1. Now, follow steps 6 - 11 in [Release process](#release-process). +- Unzip the version you have chosen, and in `manifest.json` edit the version + number to be the next sequential version after the current "bad" version (eg, + the bad version is `1.28.0` and you are rolling back to version `1.27.0`. + Therefore you change `1.27.0` to `1.29.0`). +- Re-zip the directory and rename it to the new version number. Add it to the + go/dart-debug-extension-zips folder. +- Now, follow steps 6 - 11 in [Release process](#release-process). diff --git a/dwds/debug_extension/README.md b/dwds/debug_extension/README.md deleted file mode 100644 index b6455134e..000000000 --- a/dwds/debug_extension/README.md +++ /dev/null @@ -1,12 +0,0 @@ -A Chrome extension for enabling Dart application debugging over an SSE -connection with package:dwds. - -## Installation - -The extension is available on the -[Chrome Web Store](https://chrome.google.com/webstore/detail/dart-debug-extension/eljbmlghnomdjgdjmbdekegdkbabckhm). - -## Usage - -The extension requires disabling 'Throttle expensive background timers' in -`chrome://flags` to ensure proper performance. diff --git a/dwds/debug_extension/build.yaml b/dwds/debug_extension/build.yaml index 624cdad00..3785809c2 100644 --- a/dwds/debug_extension/build.yaml +++ b/dwds/debug_extension/build.yaml @@ -4,28 +4,26 @@ targets: build_web_compilers|entrypoint: options: dart2js_args: - - -O4 # Note: Change to -01 for unminified JS. + - -O1 # Note: Change to -04 for minified JS. - --csp generate_for: - web/**.dart - extension|client_js_copy_builder: + mv3_extension|client_js_copy_builder: enabled: true builders: client_js_copy_builder: + required_inputs: [".js", ".png", ".html", ".css", ".json"] import: "tool/copy_builder.dart" builder_factories: - copyBuilder build_extensions: { - "web/{{}}.dart.js": ["prod_build/{{}}.js"], - "web/{{}}.png": ["prod_build/{{}}.png"], - "web/{{}}.html": ["prod_build/{{}}.html"], - "web/{{}}.css": ["prod_build/{{}}.css"], - "web/manifest.json": ["prod_build/manifest.json"], - "web/panel.js": ["prod_build/panel.js"], - "web/detector.js": ["prod_build/detector.js"], - "web/devtools.js": ["prod_build/devtools.js"], + "web/{{}}.dart.js": ["compiled/{{}}.dart.js"], + "web/static_assets/{{}}.png": ["compiled/static_assets/{{}}.png"], + "web/static_assets/{{}}.html": ["compiled/static_assets/{{}}.html"], + "web/static_assets/{{}}.css": ["compiled/static_assets/{{}}.css"], + "web/manifest.json": ["compiled/manifest.json"], } auto_apply: none build_to: source diff --git a/dwds/debug_extension/pubspec.yaml b/dwds/debug_extension/pubspec.yaml index c51aeb4ab..82d1cd109 100644 --- a/dwds/debug_extension/pubspec.yaml +++ b/dwds/debug_extension/pubspec.yaml @@ -1,25 +1,30 @@ -name: extension +name: mv3_extension publish_to: none -version: 1.30.0 +version: 2.1.4 homepage: https://github.com/dart-lang/webdev description: >- - A chrome extension for Dart debugging. + A Chrome extension for Dart debugging. environment: sdk: ^3.2.0-36.0.dev dependencies: - async: ^2.3.0 + built_value: ^8.3.0 collection: ^1.15.0 js: ^0.6.1+1 - pub_semver: ^2.0.0 - sse: ^4.1.0 - web_socket_channel: ^2.0.0 dev_dependencies: + args: ^2.3.1 build: ^2.0.0 - build_web_compilers: ^4.0.4 build_runner: ^2.4.0 built_collection: ^5.0.0 - dwds: ^11.0.0 - webdev: ^2.0.0 + built_value_generator: ^8.3.0 + build_web_compilers: ^4.0.4 + dwds: ^16.0.0 + path: ^1.8.1 + sse: ^4.1.2 + web_socket_channel: ^2.2.0 + +dependency_overrides: + dwds: + path: .. diff --git a/dwds/debug_extension/pubspec_overrides.yaml b/dwds/debug_extension/pubspec_overrides.yaml index 4da474653..581552eac 100644 --- a/dwds/debug_extension/pubspec_overrides.yaml +++ b/dwds/debug_extension/pubspec_overrides.yaml @@ -1,5 +1,3 @@ dependency_overrides: - webdev: - path: ../../webdev dwds: path: .. diff --git a/dwds/debug_extension_mv3/tool/build_extension.dart b/dwds/debug_extension/tool/build_extension.dart similarity index 89% rename from dwds/debug_extension_mv3/tool/build_extension.dart rename to dwds/debug_extension/tool/build_extension.dart index 66bc1cb4c..c3425a844 100644 --- a/dwds/debug_extension_mv3/tool/build_extension.dart +++ b/dwds/debug_extension/tool/build_extension.dart @@ -10,7 +10,6 @@ // Run from the extension root directory: // - For dev: dart run tool/build_extension.dart // - For prod: dart run tool/build_extension.dart --prod -// - For MV2: dart run tool/build_extension.dart --mv2 import 'dart:convert'; import 'dart:io'; @@ -23,8 +22,7 @@ const _mv2Flag = 'mv2'; void main(List arguments) async { final parser = ArgParser() - ..addFlag(_prodFlag, negatable: true, defaultsTo: false) - ..addFlag(_mv2Flag, negatable: true, defaultsTo: false); + ..addFlag(_prodFlag, negatable: true, defaultsTo: false); final argResults = parser.parse(arguments); exitCode = await run( @@ -38,7 +36,7 @@ void main(List arguments) async { Future run({required bool isProd, required bool isMV2}) async { _logInfo( - 'Building ${isMV2 ? 'MV2' : 'MV3'} extension for ${isProd ? 'prod' : 'dev'}', + 'Building extension for ${isProd ? 'prod' : 'dev'}', ); _logInfo('Compiling extension with dart2js to /compiled directory'); final compileStep = await Process.start( @@ -50,10 +48,9 @@ Future run({required bool isProd, required bool isMV2}) async { if (compileExitCode != 0) { return compileExitCode; } - final manifestFileName = isMV2 ? 'manifest_mv2' : 'manifest_mv3'; _logInfo('Copying manifest.json to /compiled directory'); try { - File(p.join('web', '$manifestFileName.json')).copySync( + File(p.join('web', 'manifest.json')).copySync( p.join('compiled', 'manifest.json'), ); } catch (error) { diff --git a/dwds/debug_extension/tool/build_extension.sh b/dwds/debug_extension/tool/build_extension.sh deleted file mode 100755 index 7afbba74c..000000000 --- a/dwds/debug_extension/tool/build_extension.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -# Copyright 2022 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# INSTRUCTIONS: - -# Building DDC-compiled app (for development work): -# ./tool/build_extension.sh - -# Building dart2js-compiled app (for release): -# ./tool/build_extension.sh prod - -prod="false" - -case "$1" in - prod) - prod="true" - shift;; -esac - -if [ $prod == true ]; then - echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - echo "Building dart2js-compiled extension to /prod_build directory." - echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" - dart run build_runner build web --delete-conflicting-outputs --output build --release - exit 1 -fi - -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" -echo "Building DDC-compiled extension to dev_build/web directory." -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" -dart run build_runner build web --delete-conflicting-outputs --output dev_build -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" -echo "Updating files in dev_build/web directory to add dev-signifiers." -echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" -dart tool/update_dev_files.dart diff --git a/dwds/debug_extension/tool/copy_builder.dart b/dwds/debug_extension/tool/copy_builder.dart index 07abcac09..4a5e5d04f 100644 --- a/dwds/debug_extension/tool/copy_builder.dart +++ b/dwds/debug_extension/tool/copy_builder.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. @@ -10,14 +10,11 @@ Builder copyBuilder(_) => _CopyBuilder(); class _CopyBuilder extends Builder { @override Map> get buildExtensions => { - "web/{{}}.dart.js": ["prod_build/{{}}.js"], - "web/{{}}.png": ["prod_build/{{}}.png"], - "web/{{}}.html": ["prod_build/{{}}.html"], - "web/{{}}.css": ["prod_build/{{}}.css"], - "web/manifest.json": ["prod_build/manifest.json"], - "web/panel.js": ["prod_build/panel.js"], - "web/detector.js": ["prod_build/detector.js"], - "web/devtools.js": ["prod_build/devtools.js"], + "web/{{}}.dart.js": ["compiled/{{}}.dart.js"], + "web/static_assets/{{}}.png": ["compiled/static_assets/{{}}.png"], + "web/static_assets/{{}}.html": ["compiled/static_assets/{{}}.html"], + "web/static_assets/{{}}.css": ["compiled/static_assets/{{}}.css"], + "web/manifest.json": ["compiled/manifest.json"], }; @override diff --git a/dwds/debug_extension/tool/update_dev_files.dart b/dwds/debug_extension/tool/update_dev_files.dart index 87e2dee61..1659c5c15 100644 --- a/dwds/debug_extension/tool/update_dev_files.dart +++ b/dwds/debug_extension/tool/update_dev_files.dart @@ -5,13 +5,12 @@ import 'dart:io'; void main() async { - await Future.wait([_updateManifestJson(), _updateDevtoolsJs()]); + await _updateManifestJson(); } -/// Adds the Googler extension key, updates the extension icon, and prefixes the -/// extension name with "[DEV]". +/// Adds the Googler extension key, and prefixes the extension name with "DEV". Future _updateManifestJson() async { - final manifestJson = File('dev_build/web/manifest.json'); + final manifestJson = File('compiled/manifest.json'); final extensionKeyTxt = File('extension_key.txt'); final extensionKey = await extensionKeyTxt.exists() ? await extensionKeyTxt.readAsString() @@ -31,22 +30,12 @@ Future _updateManifestJson() async { newValue: extensionKey, ), ]; - } - if (_matchesKey(line: line, key: 'default_icon')) { + } else if (_matchesKey(line: line, key: 'default_icon')) { return [ _newKeyValue( oldLine: line, newKey: 'default_icon', - newValue: 'dart_dev.png', - ), - ]; - } - if (_matchesValue(line: line, value: 'background.js')) { - return [ - _newKeyValue( - oldLine: line, - newKey: null, - newValue: 'background.dart.js', + newValue: 'static_assets/dart_dev.png', ), ]; } else { @@ -55,28 +44,6 @@ Future _updateManifestJson() async { }); } -/// Prefixes the names of the panels that are added to Chrome DevTools with -/// "[DEV]". -Future _updateDevtoolsJs() async { - final devtoolsJs = File('dev_build/web/devtools.js'); - return _transformDevFile(devtoolsJs, (line) { - final originalDebuggerLine = "const DEBUGGER_PANEL_NAME = 'Dart Debugger';"; - final modifiedDebuggerLine = - "const DEBUGGER_PANEL_NAME = '[DEV] Dart Debugger';"; - final originalInspectorLine = - "const INSPECTOR_PANEL_NAME = 'Flutter Inspector';"; - final modifiedInspectorLine = - "const INSPECTOR_PANEL_NAME = '[DEV] Flutter Inspector';"; - if (_matchesLine(line: line, match: originalDebuggerLine)) { - return [_newLine(oldLine: line, newLine: modifiedDebuggerLine)]; - } - if (_matchesLine(line: line, match: originalInspectorLine)) { - return [_newLine(oldLine: line, newLine: modifiedInspectorLine)]; - } - return [line]; - }); -} - Future _transformDevFile( File devFile, List Function(String) transformLine, @@ -94,15 +61,6 @@ bool _matchesKey({required String line, required String key}) { return line.trimLeft().startsWith('"$key":'); } -bool _matchesValue({required String line, required String value}) { - return line.trimRight().endsWith('"$value"') || - line.trimRight().endsWith('"$value",'); -} - -bool _matchesLine({required String line, required String match}) { - return line.trim() == match; -} - String _newKeyValue({ required String oldLine, String? newKey, @@ -115,14 +73,6 @@ String _newKeyValue({ return '$lineStart$key$value$lineEnd'; } -String _newLine({ - required String oldLine, - required String newLine, -}) { - final lineStart = oldLine.leftPadding(); - return '$lineStart$newLine'; -} - extension LeftPaddingExtension on String { String leftPadding() { String padding = ''; diff --git a/dwds/debug_extension/web/background.dart b/dwds/debug_extension/web/background.dart index 68533b191..5efd5307f 100644 --- a/dwds/debug_extension/web/background.dart +++ b/dwds/debug_extension/web/background.dart @@ -1,898 +1,297 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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 background; -import 'dart:async'; -import 'dart:convert'; -import 'dart:html'; - -import 'package:built_collection/built_collection.dart'; -// TODO(elliette): The format_and_analyze Github actions complains about this -// import because it is looking for it in DWDS' pubspec, not in the extension's -// pubspec. We should fix the Github action and / or unnest the extension from -// the DWDS directory. -// ignore: depend_on_referenced_packages -import 'package:collection/collection.dart' show IterableExtension; -import 'package:dwds/data/devtools_request.dart'; -import 'package:dwds/data/extension_request.dart'; -import 'package:dwds/data/serializers.dart'; -import 'package:dwds/shared/batched_stream.dart'; -import 'package:dwds/src/sockets.dart'; +import 'package:dwds/data/debug_info.dart'; import 'package:js/js.dart'; -import 'package:js/js_util.dart' as js_util; -import 'package:pub_semver/pub_semver.dart'; -import 'package:sse/client/sse_client.dart'; -import 'package:web_socket_channel/web_socket_channel.dart'; import 'chrome_api.dart'; -import 'web_api.dart'; - -const _notADartAppAlert = 'No Dart application detected.' - ' Are you trying to debug an application that includes a Chrome hosted app' - ' (an application listed in chrome://apps)? If so, debugging is disabled.' - ' You can fix this by removing the application from chrome://apps. Please' - ' see https://bugs.chromium.org/p/chromium/issues/detail?id=885025#c11.'; - -// Extensions allowed for cross-extension communication. -// -// This is only used to forward outgoing messages, as incoming messages are -// restricted by `externally_connectable` in the extension manifest.json. -const _allowedExtensions = { - 'nbkbficgbembimioedhceniahniffgpl', // AngularDart DevTools -}; - -// Events forwarded to allowed extensions. -const _allowedEvents = {'Overlay.inspectNodeRequested'}; - -// Map of Chrome tab ID to encoded vm service protocol URI. -final _tabIdToEncodedUri = {}; - -// Map of Chrome tab ID to warnings for that tab. -final _tabIdToWarning = {}; - -final _debuggableTabs = {}; - -final _tabsToAttach = {}; - -final _debugSessions = []; - -final _devToolsPanelsNotifier = - Notifier>([]); - -// Keeps track of the most recent Dart tab that was opened. This is a heuristic -// to let us guess which tab the user is trying to debug if they start debugging -// from the Chrome DevTools Dart panel (which doesn't have a tab ID). -Tab? _mostRecentDartTab; - -// Keeps track of how debugging was triggered. This lets us know if we should -// open Dart DevTools in a new window/tab or embed it in Chrome DevTools. -DebuggerTrigger? _debuggerTrigger; - -class DebugSession { - // The tab ID that contains the running Dart application. - final int appTabId; - - // The Dart app ID. - final String appId; - - // The tab ID that contains the corresponding Dart DevTools. - int? devtoolsTabId; - - // Socket client for communication with dwds extension backend. - final SocketClient _socketClient; - - // How often to send batched events. - static const int _batchDelayMilliseconds = 1000; - - // Collect events into batches to be send periodically to the server. - final _batchController = - BatchedStreamController(delay: _batchDelayMilliseconds); - late final StreamSubscription> _batchSubscription; - - DebugSession(this._socketClient, this.appTabId, this.appId) { - // 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), - ), - ), - ), - ); - }); - } - - void sendEvent(ExtensionEvent event) { - _socketClient.sink.add(jsonEncode(serializers.serialize(event))); - } - - void sendBatchedEvent(ExtensionEvent event) { - _batchController.sink.add(event); - } +import 'cider_connection.dart'; +import 'cross_extension_communication.dart'; +import 'data_types.dart'; +import 'debug_session.dart'; +import 'logger.dart'; +import 'messaging.dart'; +import 'storage.dart'; +import 'utils.dart'; - void close() { - _socketClient.close(); - _batchSubscription.cancel(); - _batchController.close(); - } -} - -class DevToolsPanel { - // The Dart app ID. - final String? appId; - - // The Chrome DevTools panel ID. - String? panelId; - - // The URI for the embedded Dart DevTools, or an empty string if the debugger - // is disconnected. - String devToolsUri = ''; - - DevToolsPanel(this.appId); +void main() { + _registerListeners(); } -enum DebuggerTrigger { extensionIcon, dartPanel, dwds } - -void main() { - // Start debugging when a user clicks the Dart Debug Extension: - chrome.browserAction.onClicked.addListener( - allowInterop((_) { - _startDebugging(DebuggerTrigger.extensionIcon); - }), +void _registerListeners() { + chrome.runtime.onMessage.addListener( + allowInterop(_handleRuntimeMessages), ); - -// Handles any incoming messages from the content scripts (detector, panel). - chrome.runtime.onMessage - .addListener(allowInterop(_handleMessageFromContentScripts)); - - // Attaches a debug session to the app when the extension receives a - // Runtime.executionContextCreated event from Chrome: - chrome.debugger.onEvent.addListener(allowInterop(_maybeAttachDebugSession)); - - // When a Dart application tab is closed, detach the corresponding debug - // session: - chrome.tabs.onRemoved - .addListener(allowInterop(_removeAndDetachDebugSessionForTab)); - - // When a debug session is detached, remove the reference to it: - chrome.debugger.onDetach.addListener( - allowInterop((Debuggee source, String reason) { - _removeDebugSessionForTab(source.tabId); - }), + // The only extension allowed to send messages to this extension is the + // AngularDart DevTools extension. Its permission is set in the manifest.json + // externally_connectable field. + chrome.runtime.onMessageExternal.addListener( + allowInterop(handleMessagesFromAngularDartDevTools), ); - - // Save the tab ID for the opened DevTools. - chrome.tabs.onCreated.addListener(allowInterop(_maybeSaveDevToolsTabId)); - - // Forward debugger events to the backend if applicable. - chrome.debugger.onEvent.addListener(allowInterop(_filterAndForwardToBackend)); - - // Maybe update the extension icon when a user clicks the tab: + // The only external service that sends messages to the Dart Debug Extension + // is Cider. + chrome.runtime.onConnectExternal + .addListener(allowInterop(handleCiderConnectRequest)); + // Update the extension icon on tab navigation: chrome.tabs.onActivated.addListener( - allowInterop((ActiveInfo info) { - _updateIcon(); + allowInterop((ActiveInfo info) async { + await _updateIcon(info.tabId); }), ); - - // Message handler enabling communication with external Chrome extensions: - chrome.runtime.onMessageExternal - .addListener(allowInterop(_handleMessageFromExternalExtensions)); - - // Message forwarder enabling communication with external Chrome extensions: - chrome.debugger.onEvent - .addListener(allowInterop(_forwardMessageToExternalExtensions)); - - // Maybe update the extension icon when the window focus changes: chrome.windows.onFocusChanged.addListener( - allowInterop((_) { - _updateIcon(); - }), - ); - - // Maybe update the extension icon during tab navigation: - chrome.webNavigation.onCommitted - .addListener(allowInterop(_updateIconOnNavigation)); - - // Notify the panel script controlling the Dart DevTools panel in Chrome - // DevTools of any relevant changes so that it can update accordingly: - final devToolsPanelListener = - Listener>(_notifyPanelScriptOfChanges); - _devToolsPanelsNotifier.addListener(devToolsPanelListener); - - /// Everything after this is for testing only. - /// TODO(elliette): Figure out if there is a workaround that would allow us to - /// remove this. - /// - /// An automated click on the extension icon is not supported by WebDriver. - /// We initiate a fake click from the `debug_extension_test` - /// after the extension is loaded. - onFakeClick = allowInterop(() { - _startDebugging(DebuggerTrigger.extensionIcon); - }); - - /// This is how we determine the extension tab to connect to during E2E tests. - isDartDebugExtension = true; -} - -// Gets the current tab, then attaches the debugger to it: -void _startDebugging(DebuggerTrigger debuggerTrigger) { - // Set how the debugging request was triggered. This will determine whether we - // launch Dart DevTools in a new Chrome window / tab or in the Chrome DevTools - // Dart panel: - _debuggerTrigger = debuggerTrigger; - - final getCurrentTabQuery = QueryInfo(active: true, currentWindow: true); - - // Sends commands to debugger attached to the current tab. - // Extracts the extension backend port from the injected JS. - final attachDebuggerToTab = allowInterop(_attachDebuggerToTab); - - chrome.tabs.query( - getCurrentTabQuery, - allowInterop((List tabs) { - if (tabs.isNotEmpty) { - attachDebuggerToTab(tabs.first as Tab); - } else if (_mostRecentDartTab != null) { - attachDebuggerToTab(_mostRecentDartTab!); - } else { - window.alert(''' - Could not find a Dart app to start debugging. - The Dart Debug Extension will turn blue when - a Dart application is detected. - '''); + allowInterop((_) async { + final currentTab = await activeTab; + if (currentTab?.id != null) { + await _updateIcon(currentTab!.id); } }), ); -} - -Future _attachDebuggerToTab(Tab currentTab) async { - if (!_debuggableTabs.contains(currentTab.id)) return; - - if (_tabIdToWarning.containsKey(currentTab.id)) { - window.alert(_tabIdToWarning[currentTab.id]); - return; - } - - chrome.debugger.attach( - Debuggee(tabId: currentTab.id), - '1.3', - allowInterop(() async { - if (chrome.runtime.lastError != null) { - String alertMessage; - if (chrome.runtime.lastError!.message.contains('Cannot access') || - chrome.runtime.lastError!.message.contains('Cannot attach')) { - alertMessage = _notADartAppAlert; - } else { - alertMessage = 'DevTools is already opened on a different window.'; - } - window.alert(alertMessage); - return; - } - _tabsToAttach.add(currentTab); - chrome.debugger.sendCommand( - Debuggee(tabId: currentTab.id), - 'Runtime.enable', - EmptyParam(), - allowInterop((e) {}), - ); - }), - ); -} - -void _handleMessageFromContentScripts( - dynamic jsRequest, - MessageSender sender, - Function sendResponse, -) { - if (jsRequest == null) return; - final request = jsRequest as Request; - switch (request.sender) { - case 'detector-script': - _maybeMarkTabAsDebuggable(request, sender, sendResponse); - break; - case 'panel-script': - _handleMessageFromPanelScript(request, sender); - break; - } -} - -void _handleMessageFromPanelScript(Request request, MessageSender sender) { - switch (request.message) { - case 'devtools-open': - _updateOrCreateDevToolsPanel(request.dartAppId, (panel) { - panel.panelId = sender.id; - }); - break; - case 'start-debugging': - _startDebugging(DebuggerTrigger.dartPanel); - break; - } -} - -Future _maybeMarkTabAsDebuggable( - Request request, - MessageSender sender, - Function sendResponse, -) async { - // Register any warnings for the tab: - if (request.warning != '') { - _tabIdToWarning[sender.tab!.id] = request.warning; - } - _debuggableTabs.add(sender.tab!.id); - _updateIcon(); - // TODO(grouma) - We can conditionally auto start debugging here. - // For example: _startDebugging(null); - sendResponse(true); -} - -Future _maybeAttachDebugSession( - Debuggee source, - String method, - Object? params, -) async { - // Return early if it's not a Runtime.executionContextCreated event (sent from - // Chrome): - if (method != 'Runtime.executionContextCreated') return; - if (params == null) return; - - final context = json.decode(JSON.stringify(params))['context']; - final tab = _tabsToAttach.firstWhereOrNull((tab) => tab.id == source.tabId); - final contextId = context['id'] as int?; - if (tab != null && contextId != null) { - final launchInChromeDevTools = - _debuggerTrigger == DebuggerTrigger.dartPanel; - if (await _tryAttach(contextId, tab, launchInChromeDevTools)) { - _tabsToAttach.remove(tab); - } - } -} - -// Tries to remove the debug session for the specified tab, and detach the -// debugger associated with that debug session. -void _removeAndDetachDebugSessionForTab(int tabId, _) { - final removedTabId = _removeDebugSessionForTab(tabId); - - if (removedTabId != -1) { - chrome.debugger.detach(Debuggee(tabId: removedTabId), allowInterop(() {})); - } -} - -// Tries to remove the debug session for the specified tab. If no session is -// found, returns -1. Otherwise returns the tab ID. -int _removeDebugSessionForTab(int tabId) { - final session = _debugSessions.firstWhereOrNull( - (session) => session.appTabId == tabId || session.devtoolsTabId == tabId, - ); - if (session != null) { - // Note: package:sse will try to keep the connection alive, even after the - // client has been closed. Therefore the extension sends an event to notify - // DWDS that we should close the connection, instead of relying on the done - // event sent when the client is closed. See details: - // https://github.com/dart-lang/webdev/pull/1595#issuecomment-1116773378 - final event = - _extensionEventFor('DebugExtension.detached', js_util.jsify({})); - session.sendEvent(event); - session.close(); - _debugSessions.remove(session); - - // Notify the Dart DevTools panel that the session has been detached by - // setting the URI to an empty string: - _updateOrCreateDevToolsPanel(session.appId, (panel) { - panel.devToolsUri = ''; - }); - - return session.appTabId; - } else { - return -1; - } -} + chrome.webNavigation.onCommitted + .addListener(allowInterop(_detectNavigationAwayFromDartApp)); -Future _maybeSaveDevToolsTabId(Tab tab) async { - // Remembers the ID of the DevTools tab. - // - // This assumes that the next launched tab after a session is created is the - // DevTools tab. - if (_debugSessions.isNotEmpty) _debugSessions.last.devtoolsTabId ??= tab.id; + chrome.commands.onCommand + .addListener(allowInterop(_maybeSendCopyAppIdRequest)); } -Future _handleMessageFromExternalExtensions( +Future _handleRuntimeMessages( dynamic jsRequest, MessageSender sender, Function sendResponse, ) async { - if (jsRequest == null) return; - final request = jsRequest as Request; - if (request.name == 'chrome.debugger.sendCommand') { - try { - final options = request.options as SendCommandOptions; - - void sendResponseOrError([e]) { - // No arguments indicate that an error occurred. - if (e == null) { - sendResponse( - ErrorResponse()..error = JSON.stringify(chrome.runtime.lastError), - ); - } else { - sendResponse(e); - } - } - - chrome.debugger.sendCommand( - Debuggee(tabId: request.tabId), - options.method, - options.commandParams, - allowInterop(sendResponseOrError), - ); - } catch (e) { - sendResponse(ErrorResponse()..error = '$e'); - } - } else if (request.name == 'dwds.encodedUri') { - sendResponse(_tabIdToEncodedUri[request.tabId] ?? ''); - } else if (request.name == 'dwds.startDebugging') { - _startDebugging(DebuggerTrigger.dwds); - // TODO(grouma) - Actually determine if debugging initiated - // successfully. - sendResponse(true); - } else { - sendResponse( - ErrorResponse()..error = 'Unknown request name: ${request.name}', - ); - } -} - -Future _forwardMessageToExternalExtensions( - Debuggee source, - String method, - Object? params, -) async { - if (_allowedEvents.contains(method)) { - sendMessageToExtensions( - ExternalExtensionRequest( - name: 'chrome.debugger.event', - tabId: source.tabId, - options: DebugEvent(method: method, params: params), - ), - ); - } -} - -void _notifyPanelScriptOfChanges(List panels) { - final panelsList = List.from(panels); - for (final panel in panelsList) { - chrome.runtime.sendMessage( - panel.panelId, - SimpleMessage(recipient: 'panel-script', body: panel.devToolsUri), - null, - null, - ); - } -} - -void sendMessageToExtensions(ExternalExtensionRequest request) { - for (var extensionId in _allowedExtensions) { - try { - chrome.runtime.sendMessage( - extensionId, - request, - null, - allowInterop(([e]) { - if (e == null) { - // Error sending message. Check lastError to silently fail. - chrome.runtime.lastError; - } - }), - ); - } catch (_) {} - } -} - -/// Attempts to attach to the Dart application in the provided Tab and execution -/// context. -Future _tryAttach( - int contextId, - Tab tab, - bool launchInChromeDevTools, -) async { - final successCompleter = Completer(); - chrome.debugger.sendCommand( - Debuggee(tabId: tab.id), - 'Runtime.evaluate', - InjectedParams( - expression: - '[window.\$dartExtensionUri, window.\$dartAppId, window.\$dartAppInstanceId, window.\$dwdsVersion]', - returnByValue: true, - contextId: contextId, - ), - allowInterop((dynamic response) { - final evalResponse = response as EvalResponse; - final value = evalResponse.result.value; - final extensionUri = value?[0]; - final appId = value?[1]; - final instanceId = value?[2]; - final dwdsVersion = value?[3]; - if (extensionUri == null || appId == null || instanceId == null) { - window.console.warn( - 'Unable to debug app. Missing Dart debugging global variables', - ); - successCompleter.complete(false); + if (jsRequest is! String) return; + + interceptMessage( + message: jsRequest, + expectedType: MessageType.isAuthenticated, + expectedSender: Script.detector, + expectedRecipient: Script.background, + sender: sender, + messageHandler: (String isAuthenticated) async { + final dartTab = sender.tab; + if (dartTab == null) { + debugWarn('Received auth info but tab is missing.'); return; } - _startSseClient( - Uri.parse(extensionUri), - appId, - instanceId, - contextId, - tab, - dwdsVersion ?? '0.0.0', - launchInChromeDevTools, + // Save the authentication info in storage: + await setStorageObject( + type: StorageObject.isAuthenticated, + value: isAuthenticated, + tabId: dartTab.id, ); - successCompleter.complete(true); - }), + }, ); - return successCompleter.future; -} -// Starts an SSE client. -// -// Initiates a [DevToolsRequest], handles an [ExtensionRequest], -// and sends an [ExtensionEvent]. -Future _startSseClient( - Uri uri, - String appId, - String instanceId, - int contextId, - Tab currentTab, - String dwdsVersion, - bool launchInChromeDevTools, -) async { - if (Version.parse(dwdsVersion) >= Version.parse('9.1.0')) { - var authUri = uri.replace(path: authenticationPath); - if (authUri.scheme == 'ws') authUri = authUri.replace(scheme: 'http'); - if (authUri.scheme == 'wss') authUri = authUri.replace(scheme: 'https'); - final authUrl = authUri.toString(); - try { - final response = await HttpRequest.request( - authUrl, - method: 'GET', - withCredentials: true, - ); - final responseText = response.responseText ?? ''; - if (!responseText.contains('Dart Debug Authentication Success!')) { - throw Exception('Not authenticated.'); + interceptMessage( + message: jsRequest, + expectedType: MessageType.debugInfo, + expectedSender: Script.detector, + expectedRecipient: Script.background, + sender: sender, + messageHandler: (DebugInfo debugInfo) async { + final dartTab = sender.tab; + if (dartTab == null) { + debugWarn('Received debug info but tab is missing.'); + return; } - } catch (_) { - if (window.confirm( - 'Authentication required.\n\nClick OK to authenticate then try again.', - )) { - // TODO(grouma) - see if we can get a callback on a successful auth - // and automatically reinitiate the dev workflow. - window.open(authUrl, 'Dart DevTools Authentication'); - chrome.debugger - .detach(Debuggee(tabId: currentTab.id), allowInterop(() {})); + // If this is a new Dart app, we need to clear old debug session data: + if (!await _matchesAppInStorage(debugInfo.appId, tabId: dartTab.id)) { + await clearStaleDebugSession(dartTab.id); } - return; - } - } - - // Specifies whether the debugger is attached. - // - // A debugger is detached if it is closed by user or the target is closed. - final client = uri.isScheme('ws') || uri.isScheme('wss') - ? WebSocketClient(WebSocketChannel.connect(uri)) - : SseSocketClient(SseClient(uri.toString())); - _debugSessions.add(DebugSession(client, currentTab.id, appId)); - print('Connected to DWDS version $dwdsVersion with appId=$appId'); - client.stream.listen( - (data) { - final message = serializers.deserialize(jsonDecode(data)); - if (message is ExtensionRequest) { - final messageParams = message.commandParams ?? '{}'; - final params = - BuiltMap(json.decode(messageParams)).toMap(); - chrome.debugger.sendCommand( - Debuggee(tabId: currentTab.id), - message.command, - js_util.jsify(params), - allowInterop(([e]) { - // No arguments indicate that an error occurred. - if (e == null) { - client.sink.add( - jsonEncode( - serializers.serialize( - ExtensionResponse( - (b) => b - ..id = message.id - ..success = false - ..result = JSON.stringify(chrome.runtime.lastError), - ), - ), - ), - ); - } else { - client.sink.add( - jsonEncode( - serializers.serialize( - ExtensionResponse( - (b) => b - ..id = message.id - ..success = true - ..result = JSON.stringify(e), - ), - ), - ), - ); - } - }), - ); - } else if (message is ExtensionEvent) { - if (message.method == 'dwds.encodedUri') { - sendMessageToExtensions( - ExternalExtensionRequest( - name: 'dwds.encodedUri', - tabId: currentTab.id, - options: message.params, - ), - ); - _tabIdToEncodedUri[currentTab.id] = message.params; - } - - if (message.method == 'dwds.devtoolsUri') { - _updateOrCreateDevToolsPanel(appId, (panel) { - panel.devToolsUri = message.params; - }); - } + // Save the debug info for the Dart app in storage: + await setStorageObject( + type: StorageObject.debugInfo, + value: _addTabInfo(debugInfo, tab: dartTab), + tabId: dartTab.id, + ); + // Update the icon to show that a Dart app has been detected: + final currentTab = await activeTab; + if (currentTab?.id == dartTab.id) { + await _updateIcon(dartTab.id); } }, - onDone: () { - _tabIdToEncodedUri.remove(currentTab.id); - _removeAndDetachDebugSessionForTab(currentTab.id, null); - return; - }, - onError: (_) { - _tabIdToEncodedUri.remove(currentTab.id); - window.alert('Lost app connection.'); - _removeAndDetachDebugSessionForTab(currentTab.id, null); - }, - cancelOnError: true, ); - client.sink.add( - jsonEncode( - serializers.serialize( - DevToolsRequest( - (b) => b - ..appId = appId - ..instanceId = instanceId - ..contextId = contextId - ..tabUrl = currentTab.url - ..uriOnly = launchInChromeDevTools, - ), - ), - ), + interceptMessage( + message: jsRequest, + expectedType: MessageType.debugStateChange, + expectedSender: Script.debuggerPanel, + expectedRecipient: Script.background, + sender: sender, + messageHandler: (DebugStateChange debugStateChange) { + final newState = debugStateChange.newState; + final tabId = debugStateChange.tabId; + if (newState == DebugStateChange.startDebugging) { + attachDebugger(tabId, trigger: Trigger.extensionPanel); + } + }, ); - chrome.debugger.sendCommand( - Debuggee(tabId: currentTab.id), - 'Runtime.enable', - EmptyParam(), - allowInterop((e) {}), + interceptMessage( + message: jsRequest, + expectedType: MessageType.debugStateChange, + expectedSender: Script.popup, + expectedRecipient: Script.background, + sender: sender, + messageHandler: (DebugStateChange debugStateChange) { + final newState = debugStateChange.newState; + final tabId = debugStateChange.tabId; + if (newState == DebugStateChange.startDebugging) { + attachDebugger(tabId, trigger: Trigger.extensionIcon); + } + }, ); -} - -void _updateOrCreateDevToolsPanel( - String appId, - void Function(DevToolsPanel panel) update, -) { - final devToolsPanels = - List.from(_devToolsPanelsNotifier.value); - var panelAlreadyExists = false; - for (final panel in devToolsPanels) { - if (panel.appId == appId) { - panelAlreadyExists = true; - update(panel); - } - } - if (!panelAlreadyExists) { - final newPanel = DevToolsPanel(appId); - update(newPanel); - devToolsPanels.add(newPanel); - } - _devToolsPanelsNotifier.setValue(devToolsPanels); -} - -void _updateIcon() { - final query = QueryInfo(active: true, currentWindow: true); - chrome.tabs.query( - query, - allowInterop((List tabs) { - // If tabList is empty, the user has likely navigated to a different window. - // Therefore, do not update the icon: - if (tabs.isEmpty) return; - final tab = tabs.first as Tab; - if (_tabIdToWarning.containsKey(tab.id)) { - // Set the warning icon (red): - chrome.browserAction.setIcon(IconInfo(path: 'dart_warning.png'), null); - } else if (_debuggableTabs.contains(tab.id)) { - // Set the debuggable icon (blue): - _mostRecentDartTab = tab; - chrome.browserAction.setIcon(IconInfo(path: 'dart.png'), null); - } else { - // Set the default icon (grey): - chrome.browserAction.setIcon(IconInfo(path: 'dart_grey.png'), null); + interceptMessage( + message: jsRequest, + expectedType: MessageType.multipleAppsDetected, + expectedSender: Script.detector, + expectedRecipient: Script.background, + sender: sender, + messageHandler: (String multipleAppsDetected) async { + final dartTab = sender.tab; + if (dartTab == null) { + debugWarn('Received multiple apps detected but tab is missing.'); + return; } - }), + // Save the multiple apps info in storage: + await setStorageObject( + type: StorageObject.multipleAppsDetected, + value: multipleAppsDetected, + tabId: dartTab.id, + ); + _setWarningIcon(dartTab.id); + }, ); -} - -void _updateIconOnNavigation(NavigationInfo navigationInfo) { - if (navigationInfo.transitionType != 'auto_subframe' && - _debuggableTabs.remove(navigationInfo.tabId)) { - _updateIcon(); - } -} - -/// Construct an [ExtensionEvent] from [method] and [params]. -ExtensionEvent _extensionEventFor(String method, dynamic params) => - ExtensionEvent( - (b) => b - ..params = jsonEncode(json.decode(JSON.stringify(params))) - ..method = jsonEncode(method), - ); -/// Forward debugger events to the backend if applicable. -void _filterAndForwardToBackend( - Debuggee source, - String method, - dynamic params, -) { - final debugSession = _debugSessions - .firstWhereOrNull((session) => session.appTabId == source.tabId); - - if (debugSession == null) return; - - final event = _extensionEventFor(method, params); + interceptMessage( + message: jsRequest, + expectedType: MessageType.appId, + expectedSender: Script.copier, + expectedRecipient: Script.background, + sender: sender, + messageHandler: (String appId) { + displayNotification('Copied app ID: $appId'); + }, + ); - if (method == 'Debugger.scriptParsed') { - debugSession.sendBatchedEvent(event); - } else { - debugSession.sendEvent(event); - } + sendResponse(defaultResponse); } -class Notifier { - Notifier(T value) : _value = value; - - T _value; - final List> _listeners = >[]; - - T get value => _value; - - void setValue(T value) { - _value = value; - notifyListeners(); - } - - void addListener(Listener listener) { - _listeners.add(listener); - } - - void notifyListeners() { - for (final listener in _listeners) { - listener.onChange(_value); - } +Future _detectNavigationAwayFromDartApp( + NavigationInfo navigationInfo, +) async { + // Ignore any navigation events within the page itself (e.g., opening a link, + // reloading the page, reloading an IFRAME, etc): + if (_isInternalNavigation(navigationInfo)) return; + final tabId = navigationInfo.tabId; + final debugInfo = await _fetchDebugInfo(navigationInfo.tabId); + if (debugInfo == null) return; + if (debugInfo.tabUrl != navigationInfo.url) { + _setDefaultIcon(navigationInfo.tabId); + await clearStaleDebugSession(tabId); + await removeStorageObject(type: StorageObject.debugInfo, tabId: tabId); + await detachDebugger( + tabId, + type: TabType.dartApp, + reason: DetachReason.navigatedAwayFromApp, + ); } } -class Listener { - Listener(this.onChange); - - void Function(T value) onChange; -} - -@JS() -@anonymous -class SimpleMessage { - external String get recipient; - external String get body; - external factory SimpleMessage({ - required String recipient, - required String body, - }); -} - -@JS() -@anonymous -class ExternalExtensionRequest { - external int get tabId; - external String get name; - external dynamic get options; - external factory ExternalExtensionRequest({ - required int tabId, - required String name, - required dynamic options, - }); -} - -@JS() -@anonymous -class DebugEvent { - external factory DebugEvent({String method, Object? params}); +bool _isInternalNavigation(NavigationInfo navigationInfo) { + return [ + 'auto_subframe', + 'form_submit', + 'link', + 'manual_subframe', + 'reload', + ].contains(navigationInfo.transitionType); +} + +DebugInfo _addTabInfo(DebugInfo debugInfo, {required Tab tab}) { + return DebugInfo( + (b) => b + ..appEntrypointPath = debugInfo.appEntrypointPath + ..appId = debugInfo.appId + ..appInstanceId = debugInfo.appInstanceId + ..appOrigin = debugInfo.appOrigin + ..appUrl = debugInfo.appUrl + ..authUrl = debugInfo.authUrl + ..extensionUrl = debugInfo.extensionUrl + ..isInternalBuild = debugInfo.isInternalBuild + ..isFlutterApp = debugInfo.isFlutterApp + ..workspaceName = debugInfo.workspaceName + ..tabUrl = tab.url + ..tabId = tab.id, + ); } -@JS() -@anonymous -class ErrorResponse { - external set error(String error); +Future _maybeSendCopyAppIdRequest(String command, [Tab? tab]) async { + if (command != 'copyAppId') return false; + final tabId = (tab ?? await activeTab)?.id; + if (tabId == null) return false; + final debugInfo = await _fetchDebugInfo(tabId); + final workspaceName = debugInfo?.workspaceName; + if (workspaceName == null) return false; + final appId = '$workspaceName-$tabId'; + return sendTabsMessage( + tabId: tabId, + type: MessageType.appId, + body: appId, + sender: Script.background, + recipient: Script.copier, + ); } -@JS() -@anonymous -class EmptyParam { - external factory EmptyParam(); +Future _updateIcon(int activeTabId) async { + final debugInfo = await _fetchDebugInfo(activeTabId); + if (debugInfo == null) { + _setDefaultIcon(activeTabId); + return; + } + final multipleApps = await fetchStorageObject( + type: StorageObject.multipleAppsDetected, + tabId: activeTabId, + ); + multipleApps == null + ? _setDebuggableIcon(activeTabId) + : _setWarningIcon(activeTabId); } -@JS() -@anonymous -class InjectedParams { - external String get expresion; - external bool get returnByValue; - external int get contextId; - external factory InjectedParams({ - String? expression, - bool? returnByValue, - int? contextId, - }); +void _setDebuggableIcon(int tabId) { + setExtensionIcon(IconInfo(path: 'static_assets/dart.png')); + setExtensionPopup( + PopupDetails(popup: 'static_assets/popup.html', tabId: tabId), + ); } -@JS() -@anonymous -class SendCommandOptions { - external String get method; - external Object get commandParams; +void _setWarningIcon(int tabId) { + setExtensionPopup( + PopupDetails(popup: 'static_assets/popup.html', tabId: tabId), + ); } -@JS() -@anonymous -class Request { - external String get dartAppId; - external String get sender; - external int get tabId; - external String get name; - external dynamic get options; - external String get warning; - external String get message; - external factory Request({ - required int tabId, - required String name, - required dynamic options, - }); +void _setDefaultIcon(int tabId) { + final iconPath = + isDevMode ? 'static_assets/dart_dev.png' : 'static_assets/dart_grey.png'; + setExtensionIcon(IconInfo(path: iconPath)); + setExtensionPopup( + PopupDetails(popup: '', tabId: tabId), + ); } -@JS() -@anonymous -class EvalResponse { - external EvalResult get result; +Future _fetchDebugInfo(int tabId) { + return fetchStorageObject( + type: StorageObject.debugInfo, + tabId: tabId, + ); } -@JS() -@anonymous -class EvalResult { - external List? get value; +Future _matchesAppInStorage(String? appId, {required int tabId}) async { + final debugInfo = await _fetchDebugInfo(tabId); + return appId != null && appId == debugInfo?.appId; } - -/// For testing only. -// -/// An automated click on the extension icon is not supported by WebDriver. -/// We initiate a fake click from the `debug_extension_test` -/// after the extension is loaded. -@JS('fakeClick') -external set onFakeClick(void Function() f); - -@JS('window.isDartDebugExtension') -external set isDartDebugExtension(_); diff --git a/dwds/debug_extension/web/chrome_api.dart b/dwds/debug_extension/web/chrome_api.dart index 443287baa..bb085cf8e 100644 --- a/dwds/debug_extension/web/chrome_api.dart +++ b/dwds/debug_extension/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() @@ -10,44 +12,45 @@ external Chrome get chrome; @JS() @anonymous class Chrome { - external BrowserAction get browserAction; + external Commands get commands; external Debugger get debugger; + external Devtools get devtools; + external Notifications get notifications; external Runtime get runtime; + external Storage get storage; external Tabs get tabs; external WebNavigation get webNavigation; external Windows get windows; } +/// chrome.debugger APIs: +/// https://developer.chrome.com/docs/extensions/reference/debugger + @JS() @anonymous -class BrowserAction { - // https://developer.chrome.com/docs/extensions/reference/browserAction/#method-setIcon - external void setIcon(IconInfo iconInfo, Function? callback); - - // https://developer.chrome.com/docs/extensions/reference/browserAction/#event-onClicked - external OnClickedHandler get onClicked; +class Commands { + external OnCommandHandler get onCommand; } @JS() @anonymous -class OnClickedHandler { - external void addListener(void Function(Tab tab) callback); +class OnCommandHandler { + external void addListener( + void Function(String commandName, [Tab? tab]) callback, + ); } @JS() @anonymous class Debugger { - // https://developer.chrome.com/docs/extensions/reference/debugger/#method-attach external void attach( Debuggee target, String requiredVersion, Function? callback, ); - // https://developer.chrome.com/docs/extensions/reference/debugger/#method-detach external void detach(Debuggee target, Function? callback); - // https://developer.chrome.com/docs/extensions/reference/debugger/#method-sendCommand external void sendCommand( Debuggee target, String method, @@ -55,10 +58,8 @@ class Debugger { Function? callback, ); - // https://developer.chrome.com/docs/extensions/reference/debugger/#event-onDetach external OnDetachHandler get onDetach; - // https://developer.chrome.com/docs/extensions/reference/debugger/#event-onEvent external OnEventHandler get onEvent; } @@ -78,10 +79,107 @@ class OnEventHandler { ); } +@JS() +@anonymous +class Debuggee { + external int get tabId; + external String get extensionId; + external String get targetId; + 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 String get themeName; + + 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 + +@JS() +@anonymous +class Notifications { + external void create( + String? notificationId, + NotificationOptions options, + Function? callback, + ); + + external OnClickedHandler get onClicked; +} + +@JS() +@anonymous +class OnClickedHandler { + external void addListener( + void Function(String) callback, + ); +} + +@JS() +@anonymous +class NotificationOptions { + external factory NotificationOptions({ + String title, + String message, + String iconUrl, + String type, + }); +} + +/// chrome.runtime APIs: +/// https://developer.chrome.com/docs/extensions/reference/runtime + @JS() @anonymous class Runtime { - // https://developer.chrome.com/docs/extensions/reference/runtime/#method-sendMessage + external void connect(String? extensionId, ConnectInfo info); + external void sendMessage( String? id, Object? message, @@ -89,87 +187,158 @@ class Runtime { Function? callback, ); - // https://developer.chrome.com/docs/extensions/reference/runtime/#property-lastError + external Object getManifest(); + + external String getURL(String path); + + external String get id; + // Note: Not checking the lastError when one occurs throws a runtime exception. external ChromeError? get lastError; - // https://developer.chrome.com/docs/extensions/reference/runtime/#event-onMessage + external ConnectionHandler get onConnect; + + external ConnectionHandler get onConnectExternal; + external OnMessageHandler get onMessage; - // https://developer.chrome.com/docs/extensions/reference/runtime/#event-onMessageExternal external OnMessageHandler get onMessageExternal; } +@JS() +class ChromeError { + external String get message; +} + @JS() @anonymous -class OnMessageHandler { - external void addListener( - void Function(dynamic, MessageSender, Function) callback, - ); +class ConnectInfo { + external String? get name; + external factory ConnectInfo({String? name}); } @JS() @anonymous -class Tabs { - // https://developer.chrome.com/docs/extensions/reference/tabs/#method-query - external List query( - QueryInfo queryInfo, - void Function(List) callback, +class Port { + external String? get name; + external void disconnect(); + external void postMessage(Object message); + external OnPortMessageHandler get onMessage; + external ConnectionHandler get onDisconnect; +} + +@JS() +@anonymous +class OnPortMessageHandler { + external void addListener( + void Function(dynamic, Port) callback, ); +} - // https://developer.chrome.com/docs/extensions/reference/tabs/#event-onActivated - external OnActivatedHandler get onActivated; +@JS() +@anonymous +class ConnectionHandler { + external void addListener(void Function(Port) callback); +} - // https://developer.chrome.com/docs/extensions/reference/tabs/#event-onCreated - external OnCreatedHandler get onCreated; +@JS() +@anonymous +class OnMessageHandler { + external void addListener( + dynamic Function(dynamic, MessageSender, Function) callback, + ); +} - // https://developer.chrome.com/docs/extensions/reference/tabs/#event-onRemoved - external OnRemovedHandler get onRemoved; +@JS() +@anonymous +class MessageSender { + external String? get id; + external Tab? get tab; + external String? get url; + external String? get origin; + external factory MessageSender({String? id, String? url, Tab? tab}); } @JS() @anonymous -class OnActivatedHandler { - external void addListener(void Function(ActiveInfo activeInfo) callback); +class Target { + external int get tabId; + external factory Target({int tabId}); } +/// chrome.storage APIs +/// https://developer.chrome.com/docs/extensions/reference/storage + @JS() @anonymous -class OnCreatedHandler { - external void addListener(void Function(Tab tab) callback); +class Storage { + external StorageArea get local; + + external StorageArea get session; + + external OnChangedHandler get onChanged; } @JS() @anonymous -class OnRemovedHandler { - external void addListener( - void Function(int tabId, RemoveInfo removeInfo) callback, +class StorageArea { + external Object get( + List? keys, + void Function(Object result) callback, ); + + external Object set(Object items, void Function()? callback); + + external Object remove(List keys, void Function()? callback); } @JS() @anonymous -class WebNavigation { - // https://developer.chrome.com/docs/extensions/reference/webNavigation/#event-onCommitted - external OnCommittedHandler get onCommitted; +class OnChangedHandler { + external void addListener( + void Function(Object changes, String areaName) callback, + ); } +/// chrome.tabs APIs +/// https://developer.chrome.com/docs/extensions/reference/tabs + @JS() @anonymous -class OnCommittedHandler { - external void addListener(void Function(NavigationInfo details) callback); +class Tabs { + external dynamic query( + QueryInfo queryInfo, + void Function(List) callback, + ); + + external dynamic create(TabInfo tabInfo, void Function(Tab) callback); + + external dynamic get(int tabId, void Function(Tab?) callback); + + external dynamic remove(int tabId, void Function()? callback); + + external Object sendMessage( + int tabId, + Object? message, + Object? options, + void Function() callback, + ); + + external OnActivatedHandler get onActivated; + + external OnRemovedHandler get onRemoved; } @JS() @anonymous -class Windows { - external OnFocusChangedHandler get onFocusChanged; +class OnActivatedHandler { + external void addListener(void Function(ActiveInfo activeInfo) callback); } @JS() @anonymous -class OnFocusChangedHandler { - external void addListener(void Function(int windowId) callback); +class OnRemovedHandler { + external void addListener(void Function(int tabId, dynamic info) callback); } @JS() @@ -179,33 +348,44 @@ class ActiveInfo { } @JS() -class ChromeError { - external String get message; +@anonymous +class TabInfo { + external bool? get active; + external bool? get pinned; + external String? get url; + external factory TabInfo({bool? active, bool? pinned, String? url}); } @JS() @anonymous -class Debuggee { - external int get tabId; - external String get extensionId; - external String get targetId; - external factory Debuggee({int tabId, String? extensionId, String? targetId}); +class QueryInfo { + external bool get active; + external bool get currentWindow; + external String get url; + external factory QueryInfo({bool? active, bool? currentWindow, String? url}); } @JS() @anonymous -class IconInfo { - external String get path; - external factory IconInfo({String path}); +class Tab { + external int get id; + external String get url; } +/// chrome.webNavigation APIs +/// https://developer.chrome.com/docs/extensions/reference/webNavigation + @JS() @anonymous -class MessageSender { - external String? get id; - external Tab? get tab; - external String? get url; - external factory MessageSender({String? id, String? url, Tab? tab}); +class WebNavigation { + // https://developer.chrome.com/docs/extensions/reference/webNavigation/#event-onCommitted + external OnCommittedHandler get onCommitted; +} + +@JS() +@anonymous +class OnCommittedHandler { + external void addListener(void Function(NavigationInfo details) callback); } @JS() @@ -213,35 +393,37 @@ class MessageSender { class NavigationInfo { external String get transitionType; external int get tabId; + external String get url; } +/// chrome.windows APIs +/// https://developer.chrome.com/docs/extensions/reference/windows + @JS() @anonymous -class QueryInfo { - external bool get active; - external bool get currentWindow; - external factory QueryInfo({bool? active, bool? currentWindow}); +class Windows { + external dynamic create(WindowInfo? createData, Function(WindowObj) callback); + + external OnFocusChangedHandler get onFocusChanged; } @JS() @anonymous -class RemoveInfo { - external int get windowId; - external bool get isWindowClosing; +class OnFocusChangedHandler { + external void addListener(void Function(int windowId) callback); } @JS() @anonymous -class Tab { - external int get id; - external String get url; +class WindowInfo { + external bool? get focused; + external String? get url; + external factory WindowInfo({bool? focused, String? url}); } @JS() @anonymous -class UrlFilter { - external String? get hostContains; - external String? get hostEquals; - external String? get hostPrefix; - external String? get hostSuffix; +class WindowObj { + external int get id; + external List get tabs; } diff --git a/dwds/debug_extension_mv3/web/cider_connection.dart b/dwds/debug_extension/web/cider_connection.dart similarity index 100% rename from dwds/debug_extension_mv3/web/cider_connection.dart rename to dwds/debug_extension/web/cider_connection.dart diff --git a/dwds/debug_extension_mv3/web/copier.dart b/dwds/debug_extension/web/copier.dart similarity index 100% rename from dwds/debug_extension_mv3/web/copier.dart rename to dwds/debug_extension/web/copier.dart diff --git a/dwds/debug_extension_mv3/web/cross_extension_communication.dart b/dwds/debug_extension/web/cross_extension_communication.dart similarity index 100% rename from dwds/debug_extension_mv3/web/cross_extension_communication.dart rename to dwds/debug_extension/web/cross_extension_communication.dart diff --git a/dwds/debug_extension_mv3/web/data_serializers.dart b/dwds/debug_extension/web/data_serializers.dart similarity index 100% rename from dwds/debug_extension_mv3/web/data_serializers.dart rename to dwds/debug_extension/web/data_serializers.dart diff --git a/dwds/debug_extension_mv3/web/data_serializers.g.dart b/dwds/debug_extension/web/data_serializers.g.dart similarity index 100% rename from dwds/debug_extension_mv3/web/data_serializers.g.dart rename to dwds/debug_extension/web/data_serializers.g.dart diff --git a/dwds/debug_extension_mv3/web/data_types.dart b/dwds/debug_extension/web/data_types.dart similarity index 100% rename from dwds/debug_extension_mv3/web/data_types.dart rename to dwds/debug_extension/web/data_types.dart diff --git a/dwds/debug_extension_mv3/web/data_types.g.dart b/dwds/debug_extension/web/data_types.g.dart similarity index 100% rename from dwds/debug_extension_mv3/web/data_types.g.dart rename to dwds/debug_extension/web/data_types.g.dart diff --git a/dwds/debug_extension_mv3/web/debug_info.dart b/dwds/debug_extension/web/debug_info.dart similarity index 100% rename from dwds/debug_extension_mv3/web/debug_info.dart rename to dwds/debug_extension/web/debug_info.dart diff --git a/dwds/debug_extension_mv3/web/debug_session.dart b/dwds/debug_extension/web/debug_session.dart similarity index 100% rename from dwds/debug_extension_mv3/web/debug_session.dart rename to dwds/debug_extension/web/debug_session.dart diff --git a/dwds/debug_extension/web/debugger_panel.html b/dwds/debug_extension/web/debugger_panel.html deleted file mode 100644 index 5972b7636..000000000 --- a/dwds/debug_extension/web/debugger_panel.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - -
-
- -

Please read:

-

Before debugging, please disable focus on the Sources panel for breakpoints:

- Settings > Preferences > Sources > uncheck "Focus Sources panel when triggering a breakpoint" - Picture of the setting in Chrome DevTools to disable. -
-
-
- - - - - - \ No newline at end of file diff --git a/dwds/debug_extension_mv3/web/detector.dart b/dwds/debug_extension/web/detector.dart similarity index 100% rename from dwds/debug_extension_mv3/web/detector.dart rename to dwds/debug_extension/web/detector.dart diff --git a/dwds/debug_extension/web/detector.js b/dwds/debug_extension/web/detector.js deleted file mode 100644 index 174a5c457..000000000 --- a/dwds/debug_extension/web/detector.js +++ /dev/null @@ -1,37 +0,0 @@ -(function loadDetectorScript() { - const DETECTOR_SCRIPT = 'detector-script'; - const MULTIPLE_APPS_ATTRIBUTE = 'data-multiple-dart-apps'; - - const MULTIPLE_APPS_WARNING = 'It appears that you are running multiple Dart apps ' + - 'and/or sub-apps. Dart debugging is currently not supported in a multi-app ' + - 'environment.'; - - function sendMessage(e) { - const hasMultipleApps = document - .documentElement - .getAttribute(MULTIPLE_APPS_ATTRIBUTE); - const warning = hasMultipleApps == 'true' ? MULTIPLE_APPS_WARNING : ''; - chrome.runtime.sendMessage(Object.assign(e, { warning: warning, sender: DETECTOR_SCRIPT })); - } - - document.addEventListener('dart-app-ready', function (e) { - sendMessage(e); - }); - - function multipleDartAppsCallback(mutationList) { - mutationList.forEach(function (mutation) { - if (mutation.type !== "attributes") return; - if (mutation.attributeName === MULTIPLE_APPS_ATTRIBUTE) { - sendMessage({}); - } - }); - }; - - // Watch for changes to the multiple apps data-attribute and update accordingly: - var multipleDartAppsObserver = new MutationObserver(multipleDartAppsCallback); - multipleDartAppsObserver.observe(document.documentElement, { - attributeFilter: [MULTIPLE_APPS_ATTRIBUTE] - }); -}()); - - diff --git a/dwds/debug_extension_mv3/web/devtools.dart b/dwds/debug_extension/web/devtools.dart similarity index 100% rename from dwds/debug_extension_mv3/web/devtools.dart rename to dwds/debug_extension/web/devtools.dart diff --git a/dwds/debug_extension/web/devtools.html b/dwds/debug_extension/web/devtools.html deleted file mode 100644 index c7f22f4d8..000000000 --- a/dwds/debug_extension/web/devtools.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/dwds/debug_extension/web/devtools.js b/dwds/debug_extension/web/devtools.js deleted file mode 100644 index 4f2189a3a..000000000 --- a/dwds/debug_extension/web/devtools.js +++ /dev/null @@ -1,67 +0,0 @@ -(function loadDevToolsScript() { - const DDR_DART_APP_ATTRIBUTE = 'data-ddr-dart-app'; - // Note: Changes to the DEBUGGER_PANEL_NAME and INSPECTOR_PANEL_NAME - // must be reflected in `tool/update_dev_files.dart` as well. - const DEBUGGER_PANEL_NAME = 'Dart Debugger'; - const INSPECTOR_PANEL_NAME = 'Flutter Inspector'; - - let debuggerCreated = false; - let inspectorCreated = false; - let checkDartCount = 0; - let checkFlutterCount = 0; - - chrome.devtools.network.onNavigated.addListener(createDebuggerPanelIfDartApp) - const checkDartAppInterval = setInterval(createDebuggerPanelIfDartApp, 1000) - createDebuggerPanelIfDartApp() - - function createDebuggerPanelIfDartApp() { - if (debuggerCreated || checkDartCount++ > 20) { - clearInterval(checkDartAppInterval); - return; - } - - checkIsDartApp(); - } - - function checkIsDartApp() { - // TODO(elliette): Remove the DDR data attribute check when we are ready to launch externally, - // and instead replace it with the following: !!window.$dartAppId - // Note: we must remove the useContentScriptContext option as well. - chrome.devtools.inspectedWindow.eval( - `document.documentElement.hasAttribute("${DDR_DART_APP_ATTRIBUTE}")`, - { useContentScriptContext: true }, - function (isDartApp) { - if (!isDartApp) return; - - chrome.devtools.panels.create( - DEBUGGER_PANEL_NAME, '', 'debugger_panel.html' - ); - debuggerCreated = true; - createInspectorPanelIfFlutterApp(); - }); - } - - function createInspectorPanelIfFlutterApp() { - const checkFlutterAppInterval = setInterval(function () { - if (inspectorCreated || checkFlutterCount++ > 10) { - clearInterval(checkFlutterAppInterval); - return; - } - - // The following value is loaded asynchronously, which is why - // we check for it every 1 second: - chrome.devtools.inspectedWindow.eval( - '!!window._flutter_web_set_location_strategy', - function (isFlutterWeb) { - if (isFlutterWeb) { - chrome.devtools.panels.create( - INSPECTOR_PANEL_NAME, '', 'inspector_panel.html' - ); - inspectorCreated = true; - } - } - ); - }, 1000) - } -}()); - diff --git a/dwds/debug_extension/web/devtools_settings.png b/dwds/debug_extension/web/devtools_settings.png deleted file mode 100644 index 48b39130a..000000000 Binary files a/dwds/debug_extension/web/devtools_settings.png and /dev/null differ diff --git a/dwds/debug_extension/web/inspector_panel.html b/dwds/debug_extension/web/inspector_panel.html deleted file mode 100644 index d3880e5a4..000000000 --- a/dwds/debug_extension/web/inspector_panel.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - -
-
- -
-
-
- - - - - - \ No newline at end of file diff --git a/dwds/debug_extension_mv3/web/logger.dart b/dwds/debug_extension/web/logger.dart similarity index 100% rename from dwds/debug_extension_mv3/web/logger.dart rename to dwds/debug_extension/web/logger.dart diff --git a/dwds/debug_extension/web/manifest.json b/dwds/debug_extension/web/manifest.json index 9c83bd302..83ecae394 100644 --- a/dwds/debug_extension/web/manifest.json +++ b/dwds/debug_extension/web/manifest.json @@ -1,38 +1,47 @@ { - "name": "Dart Debug Extension", - "version": "1.30", - "minimum_chrome_version": "10.0", - "devtools_page": "devtools.html", - "externally_connectable": { - "ids": [ - "nbkbficgbembimioedhceniahniffgpl" - ] - }, - "manifest_version": 2, - "browser_action": { - "default_icon": "dart_grey.png" - }, - "permissions": [ - "debugger", - "tabs", - "webNavigation", - "http://*/*", - "https://*/*" - ], - "background": { - "scripts": [ - "background.js" - ] - }, - "content_scripts": [ - { - "matches": [ - "" - ], - "js": [ - "detector.js" - ], - "run_at": "document_end" - } + "name": "Dart Debug Extension", + "version": "2.1.4", + "manifest_version": 3, + "devtools_page": "static_assets/devtools.html", + "action": { + "default_icon": "static_assets/dart_grey.png" + }, + "externally_connectable": { + "ids": ["nbkbficgbembimioedhceniahniffgpl"], + "matches": [ + "https://cider.corp.google.com/*", + "https://cider-staging.corp.google.com/*", + "https://cider-test.corp.google.com/*", + "https://cider-v.corp.google.com/*", + "https://cider-v-staging.corp.google.com/*", + "https://cider-v-test.corp.google.com/*" ] -} \ No newline at end of file + }, + "permissions": ["debugger", "notifications", "storage", "webNavigation"], + "host_permissions": [""], + "background": { + "service_worker": "background.dart.js" + }, + "content_scripts": [ + { + "matches": [""], + "js": ["detector.dart.js", "copier.dart.js"], + "run_at": "document_end" + } + ], + "commands": { + "copyAppId": { + "suggestedKey": { + "default": "Ctrl+Shift+7", + "mac": "Command+Shift+7" + }, + "description": "Copy the app ID" + } + }, + "web_accessible_resources": [ + { + "matches": [""], + "resources": ["debug_info.dart.js"] + } + ] +} diff --git a/dwds/debug_extension_mv3/web/messaging.dart b/dwds/debug_extension/web/messaging.dart similarity index 100% rename from dwds/debug_extension_mv3/web/messaging.dart rename to dwds/debug_extension/web/messaging.dart diff --git a/dwds/debug_extension/web/panel.css b/dwds/debug_extension/web/panel.css deleted file mode 100644 index b9b069ceb..000000000 --- a/dwds/debug_extension/web/panel.css +++ /dev/null @@ -1,132 +0,0 @@ -body { - font-family: Arial, Helvetica, sans-serif; -} - -h1 { - font-size: 20px; -} - -p { - font-size: 16px; -} - -code { - font-size: 16px; -} - -img { - padding: 12px; -} - -iframe { - border: 0pt none; - height: 100%; - left: 0px; - position: absolute; - top: 0px; - width: 100%; -} - -.flex-row { - align-items: center; - display: flex; - justify-content: center; -} - -.flex-column { - align-items: center; - display: flex; - flex-direction: column; -} - -.material-button { - background-color: #2196f3; - border-radius: 4px; - border: none; - box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12); - box-sizing: border-box; - color: #ffffff; - cursor: pointer; - display: inline-block; - font-family: Arial, Helvetica, sans-serif; - font-size: 14px; - font-weight: 500; - height: 36px; - line-height: 36px; - margin: 12px; - min-width: 64px; - outline: none; - overflow: hidden; - padding: 0 16px; - position: relative; - text-align: center; - text-overflow: ellipsis; - text-transform: uppercase; - transition: box-shadow 0.2s; - vertical-align: middle; -} - -.material-button::-moz-focus-inner { - border: none; -} - -.material-button::before { - background-color: #ffffff; - bottom: 0; - content: ""; - left: 0; - opacity: 0; - position: absolute; - right: 0; - top: 0; - transition: opacity 0.2s; -} - -.material-button::after { - background-color: #ffffff; - border-radius: 50%; - content: ""; - height: 32px; - left: 50%; - opacity: 0; - padding: 50%; - position: absolute; - top: 50%; - transform: translate(-50%, -50%) scale(1); - transition: opacity 1s, transform 0.5s; - width: 32px; -} - -.material-button:hover, -.material-button:focus { - box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12); -} - -.material-button:hover::before { - opacity: 0.08; -} - -.material-button:focus::before { - opacity: 0.24; -} - -.material-button:hover:focus::before { - opacity: 0.3; -} - -.material-button:active { - box-shadow: 0 5px 5px -3px #4D000000, 0 8px 10px 1px #4D000000, 0 3px 14px 2px #4D000000; -} - -.material-button:active::after { - opacity: 0.32; - transform: translate(-50%, -50%) scale(0); - transition: transform 0s; -} - -.material-button:disabled { - background-color: #d3d3d3; - color: #696969; - box-shadow: none; - cursor: initial; -} \ No newline at end of file diff --git a/dwds/debug_extension_mv3/web/panel.dart b/dwds/debug_extension/web/panel.dart similarity index 100% rename from dwds/debug_extension_mv3/web/panel.dart rename to dwds/debug_extension/web/panel.dart diff --git a/dwds/debug_extension/web/panel.js b/dwds/debug_extension/web/panel.js deleted file mode 100644 index 2f82ed205..000000000 --- a/dwds/debug_extension/web/panel.js +++ /dev/null @@ -1,86 +0,0 @@ -(function loadPanelScript() { - // Variables: - const IFRAME_TAG = 'iframe'; - const IFRAME_CONTAINER = 'iframeContainer'; - const IFRAME_ID = 'dartDevToolsEmbed'; - const DEBUGGING_BUTTON = 'debuggingButton'; - const CHROME_DARK = 'dark'; - const DARK_COLOR = '202125'; - const LIGHT_COLOR = 'ffffff'; - const PANEL_SCRIPT = 'panel-script'; - const START_DEBUGGING = 'start-debugging'; - const DEVTOOLS_OPEN = 'devtools-open'; - const PANEL_BODY = 'panelBody'; - const PANEL_ATTRIBUTE = 'data-panel'; - - const chromeTheme = chrome.devtools.panels.themeName; - const backgroundColor = chromeTheme == CHROME_DARK ? DARK_COLOR : LIGHT_COLOR; - const fontColor = chromeTheme == CHROME_DARK ? LIGHT_COLOR : DARK_COLOR; - - let appId = null; - let currentDevToolsUrl = ''; - let panel = ''; - - // Helper functions: - function sendStartDebuggingRequest() { - if (!appId) return; - document.getElementById(DEBUGGING_BUTTON).setAttribute('disabled', true); - chrome.runtime.sendMessage({ sender: PANEL_SCRIPT, message: START_DEBUGGING, dartAppId: appId }); - } - - window.onload = function () { - panel = document.getElementById(PANEL_BODY).getAttribute(PANEL_ATTRIBUTE) - document.getElementById(DEBUGGING_BUTTON).addEventListener('click', sendStartDebuggingRequest); - // Set the background and text color of the panel to match the Chrome theme: - document.body.style.backgroundColor = `#${backgroundColor}`; - document.body.style.color = `#${fontColor}`; - }; - - chrome.runtime.onMessage.addListener(function (request) { - // Only listen for messages meant for the panel: - if (request.recipient != PANEL_SCRIPT) return; - - const devToolsUrl = request.body; - const iframeContainer = document.getElementById(IFRAME_CONTAINER); - - if (devToolsUrl != currentDevToolsUrl) { - currentDevToolsUrl = devToolsUrl; - - if (!devToolsUrl) { - // Debugger has been disconnected, remove the IFRAME for Dart DevTools - // and enable the start debugging button: - document.getElementById(DEBUGGING_BUTTON).removeAttribute('disabled'); - const iframe = document.getElementById(IFRAME_ID); - if (!!iframe) iframeContainer.removeChild(iframe); - } else { - // Debugger has benn connected, add an IFRAME for Dart DevTools: - const iframe = document.createElement(IFRAME_TAG); - if (panel == '') return; - const src = `${devToolsUrl}&embed=true&page=${panel}&backgroundColor=${backgroundColor}`; - iframe.setAttribute('src', src); - iframe.setAttribute('scrolling', 'no'); - iframe.id = IFRAME_ID; - iframeContainer.appendChild(iframe); - } - } - - }); - - chrome.devtools.inspectedWindow.eval( - ` - function findDartAppId(frame) { - if (frame.$dartAppId) return frame.$dartAppId; - const frames = frame.frames; - for (let i = 0; i < frames.length; i++) { - return findDartAppId(frames[i]); - } - } - findDartAppId(window); - `, - function (dartAppId) { - appId = dartAppId; - document.getElementById(DEBUGGING_BUTTON).removeAttribute('disabled'); - chrome.runtime.sendMessage({ sender: PANEL_SCRIPT, message: DEVTOOLS_OPEN, dartAppId: dartAppId }); - }, - ); -}()); \ No newline at end of file diff --git a/dwds/debug_extension_mv3/web/popup.dart b/dwds/debug_extension/web/popup.dart similarity index 100% rename from dwds/debug_extension_mv3/web/popup.dart rename to dwds/debug_extension/web/popup.dart diff --git a/dwds/debug_extension/web/dart.png b/dwds/debug_extension/web/static_assets/dart.png similarity index 100% rename from dwds/debug_extension/web/dart.png rename to dwds/debug_extension/web/static_assets/dart.png diff --git a/dwds/debug_extension/web/dart_dev.png b/dwds/debug_extension/web/static_assets/dart_dev.png similarity index 100% rename from dwds/debug_extension/web/dart_dev.png rename to dwds/debug_extension/web/static_assets/dart_dev.png diff --git a/dwds/debug_extension/web/dart_grey.png b/dwds/debug_extension/web/static_assets/dart_grey.png similarity index 100% rename from dwds/debug_extension/web/dart_grey.png rename to dwds/debug_extension/web/static_assets/dart_grey.png diff --git a/dwds/debug_extension/web/dart_warning.png b/dwds/debug_extension/web/static_assets/dart_warning.png similarity index 100% rename from dwds/debug_extension/web/dart_warning.png rename to dwds/debug_extension/web/static_assets/dart_warning.png diff --git a/dwds/debug_extension_mv3/web/static_assets/debugger_panel.html b/dwds/debug_extension/web/static_assets/debugger_panel.html similarity index 100% rename from dwds/debug_extension_mv3/web/static_assets/debugger_panel.html rename to dwds/debug_extension/web/static_assets/debugger_panel.html diff --git a/dwds/debug_extension_mv3/web/static_assets/debugger_settings.png b/dwds/debug_extension/web/static_assets/debugger_settings.png similarity index 100% rename from dwds/debug_extension_mv3/web/static_assets/debugger_settings.png rename to dwds/debug_extension/web/static_assets/debugger_settings.png diff --git a/dwds/debug_extension_mv3/web/static_assets/devtools.html b/dwds/debug_extension/web/static_assets/devtools.html similarity index 100% rename from dwds/debug_extension_mv3/web/static_assets/devtools.html rename to dwds/debug_extension/web/static_assets/devtools.html diff --git a/dwds/debug_extension_mv3/web/static_assets/inspect_widget.png b/dwds/debug_extension/web/static_assets/inspect_widget.png similarity index 100% rename from dwds/debug_extension_mv3/web/static_assets/inspect_widget.png rename to dwds/debug_extension/web/static_assets/inspect_widget.png diff --git a/dwds/debug_extension_mv3/web/static_assets/inspector_panel.html b/dwds/debug_extension/web/static_assets/inspector_panel.html similarity index 100% rename from dwds/debug_extension_mv3/web/static_assets/inspector_panel.html rename to dwds/debug_extension/web/static_assets/inspector_panel.html diff --git a/dwds/debug_extension_mv3/web/static_assets/popup.html b/dwds/debug_extension/web/static_assets/popup.html similarity index 100% rename from dwds/debug_extension_mv3/web/static_assets/popup.html rename to dwds/debug_extension/web/static_assets/popup.html diff --git a/dwds/debug_extension_mv3/web/static_assets/styles.css b/dwds/debug_extension/web/static_assets/styles.css similarity index 100% rename from dwds/debug_extension_mv3/web/static_assets/styles.css rename to dwds/debug_extension/web/static_assets/styles.css diff --git a/dwds/debug_extension_mv3/web/storage.dart b/dwds/debug_extension/web/storage.dart similarity index 100% rename from dwds/debug_extension_mv3/web/storage.dart rename to dwds/debug_extension/web/storage.dart diff --git a/dwds/debug_extension_mv3/web/utils.dart b/dwds/debug_extension/web/utils.dart similarity index 100% rename from dwds/debug_extension_mv3/web/utils.dart rename to dwds/debug_extension/web/utils.dart diff --git a/dwds/debug_extension/web/web_api.dart b/dwds/debug_extension/web/web_api.dart index 70e4b28d6..1a5134475 100644 --- a/dwds/debug_extension/web/web_api.dart +++ b/dwds/debug_extension/web/web_api.dart @@ -1,6 +1,8 @@ // 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 'dart:html'; +import 'dart:js_util' as js_util; import 'package:js/js.dart'; @@ -14,3 +16,51 @@ class Json { // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify external String stringify(o); } + +// Custom implementation of Fetch API until the Dart implementation supports +// credentials. See https://github.com/dart-lang/http/issues/595. +@JS('fetch') +external Object _nativeJsFetch(String resourceUrl, FetchOptions options); + +Future fetchRequest(String resourceUrl) async { + try { + final options = FetchOptions( + method: 'GET', + credentials: 'include', + ); + final response = + await promiseToFuture(_nativeJsFetch(resourceUrl, options)); + final body = + await promiseToFuture(js_util.callMethod(response, 'text', [])); + final ok = js_util.getProperty(response, 'ok'); + final status = js_util.getProperty(response, 'status'); + return FetchResponse(status: status, ok: ok, body: body); + } catch (error) { + return FetchResponse( + status: 400, + ok: false, + body: 'Error fetching $resourceUrl: $error', + ); + } +} + +@JS() +@anonymous +class FetchOptions { + external factory FetchOptions({ + required String method, // e.g., 'GET', 'POST' + required String credentials, // e.g., 'omit', 'same-origin', 'include' + }); +} + +class FetchResponse { + final int status; + final bool ok; + final String? body; + + FetchResponse({ + required this.status, + required this.ok, + required this.body, + }); +} diff --git a/dwds/debug_extension_mv3/.gitignore b/dwds/debug_extension_mv3/.gitignore deleted file mode 100644 index 4878cbe8b..000000000 --- a/dwds/debug_extension_mv3/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -build/ -compiled/ -extension_key.txt diff --git a/dwds/debug_extension_mv3/CONTRIBUTING.md b/dwds/debug_extension_mv3/CONTRIBUTING.md deleted file mode 100644 index 7f55d0914..000000000 --- a/dwds/debug_extension_mv3/CONTRIBUTING.md +++ /dev/null @@ -1,92 +0,0 @@ -## Building - -- For development: `dart run tool/build_extension.dart` -- For release: ` dart run tool/build_extension.dart --prod` - -The dart2js-compiled extension will be located in the `/compiled` directory. - -## Local Development - -### \[For Googlers\] Create an `extension_key.txt` file: - -- Create a `extension_key.txt` file at the root of `/debug_extension`. Paste in - the value of one of the whitelisted developer keys into this txt file. - IMPORTANT: DO NOT COMMIT THE KEY. It will be copied into the `manifest.json` - when you build the extension. - -### Build and upload your local extension - -- Build the extension following the instructions above -- Visit chrome://extensions -- Toggle "Developer mode" on -- Click the "Load unpacked" button -- Select the extension directory: `/compiled` - -### Debug your local extension - -- Click the Extensions puzzle piece, and pin the Dart Debug Extension with the - dev icon (unpin the published version so you don't confuse them) -- You can now use the extension normally by clicking it when a local Dart web - application has loaded in a Chrome tab -- To debug, visit chrome://extensions and click "Inspect view on background - page" to open Chrome DevTools for the extension -- More debugging information can be found in the - [Chrome Developers documentation](https://developer.chrome.com/docs/extensions/mv3/devguide/) - -## Release process - -- Update the version in `web/manifest_mv2.json`, `web/manifest_mv3.json`, `pubspec.yaml`, and in the - `CHANGELOG`. -- Follow the instructions above to build the release version of the extension. - -> \*At this point, you should manually verify that everything is working by -> following the steps in [Local Development](#local-development), except load -> the extension from the `compiled` directory. You will need to add an extension -> key to the `manifest.json` file in `compiled` to test locally. - -- Open a PR to submit the version change. -- Once submitted, pull the changes down to your local branch, and create a zip - of the `compiled` directory. **Remove the Googler extension key that was added - by the builder to the `manifest.json` file.** -- Rename the zip `version_XX.XX.XX.zip` (eg, `version_1.24.0.zip`) and add it to - the go/dart-debug-extension-zips folder - -> _You must be a Googler to do this. Ask for help if not._ - -- Go to the - [Chrome Web Store Developer Dashboard](https://chrome.google.com/webstore/devconsole). -- At the top-right, under Publisher, select dart-bat. - -> _If you don’t see dart-bat as an option, you will need someone on the Dart -> team to add you to the dart-bat Google group._ - -- Under Items, select the "Dart Debug Extension". -- Go to “Package” then select “Upload new package”. - -> _The first time you do this, you will be asked to pay a $5 registration fee. -> The registration fee can be expensed._ - -- Upload the zip file you created in step 4. -- Save as draft, and verify that the new version is correct. -- Publish. The extension will be published immediately after going through the - review process. - -## Rollback process - -> The Chrome Web Store Developer Dashboard does not support rollbacks. Instead -> you must re-publish an earlier version. This means that the extension will -> still have to go through the review process, which can take anywhere from a -> few hours (most common) to a few days. - -- Find the previous version you want to rollback to in the - go/dart-debug-extension-zips folder. - -> _You must be a Googler to do this. Ask for help if not._ - -- Unzip the version you have chosen, and in `manifest.json` edit the version - number to be the next sequential version after the current "bad" version (eg, - the bad version is `1.28.0` and you are rolling back to version `1.27.0`. - Therefore you change `1.27.0` to `1.29.0`). -- Re-zip the directory and rename it to the new version number. Add it to the - go/dart-debug-extension-zips folder. -- Now, follow steps 6 - 11 in [Release process](#release-process). diff --git a/dwds/debug_extension_mv3/build.yaml b/dwds/debug_extension_mv3/build.yaml deleted file mode 100644 index 3785809c2..000000000 --- a/dwds/debug_extension_mv3/build.yaml +++ /dev/null @@ -1,29 +0,0 @@ -targets: - $default: - builders: - build_web_compilers|entrypoint: - options: - dart2js_args: - - -O1 # Note: Change to -04 for minified JS. - - --csp - generate_for: - - web/**.dart - mv3_extension|client_js_copy_builder: - enabled: true - -builders: - client_js_copy_builder: - required_inputs: [".js", ".png", ".html", ".css", ".json"] - import: "tool/copy_builder.dart" - builder_factories: - - copyBuilder - build_extensions: - { - "web/{{}}.dart.js": ["compiled/{{}}.dart.js"], - "web/static_assets/{{}}.png": ["compiled/static_assets/{{}}.png"], - "web/static_assets/{{}}.html": ["compiled/static_assets/{{}}.html"], - "web/static_assets/{{}}.css": ["compiled/static_assets/{{}}.css"], - "web/manifest.json": ["compiled/manifest.json"], - } - auto_apply: none - build_to: source diff --git a/dwds/debug_extension_mv3/pubspec.yaml b/dwds/debug_extension_mv3/pubspec.yaml deleted file mode 100644 index 82d1cd109..000000000 --- a/dwds/debug_extension_mv3/pubspec.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: mv3_extension -publish_to: none -version: 2.1.4 -homepage: https://github.com/dart-lang/webdev -description: >- - A Chrome extension for Dart debugging. - -environment: - sdk: ^3.2.0-36.0.dev - -dependencies: - built_value: ^8.3.0 - collection: ^1.15.0 - js: ^0.6.1+1 - -dev_dependencies: - args: ^2.3.1 - build: ^2.0.0 - build_runner: ^2.4.0 - built_collection: ^5.0.0 - built_value_generator: ^8.3.0 - build_web_compilers: ^4.0.4 - dwds: ^16.0.0 - path: ^1.8.1 - sse: ^4.1.2 - web_socket_channel: ^2.2.0 - -dependency_overrides: - dwds: - path: .. diff --git a/dwds/debug_extension_mv3/pubspec_overrides.yaml b/dwds/debug_extension_mv3/pubspec_overrides.yaml deleted file mode 100644 index 581552eac..000000000 --- a/dwds/debug_extension_mv3/pubspec_overrides.yaml +++ /dev/null @@ -1,3 +0,0 @@ -dependency_overrides: - dwds: - path: .. diff --git a/dwds/debug_extension_mv3/tool/copy_builder.dart b/dwds/debug_extension_mv3/tool/copy_builder.dart deleted file mode 100644 index 4a5e5d04f..000000000 --- a/dwds/debug_extension_mv3/tool/copy_builder.dart +++ /dev/null @@ -1,47 +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 'package:build/build.dart'; - -/// Factory for the build script. -Builder copyBuilder(_) => _CopyBuilder(); - -class _CopyBuilder extends Builder { - @override - Map> get buildExtensions => { - "web/{{}}.dart.js": ["compiled/{{}}.dart.js"], - "web/static_assets/{{}}.png": ["compiled/static_assets/{{}}.png"], - "web/static_assets/{{}}.html": ["compiled/static_assets/{{}}.html"], - "web/static_assets/{{}}.css": ["compiled/static_assets/{{}}.css"], - "web/manifest.json": ["compiled/manifest.json"], - }; - - @override - Future build(BuildStep buildStep) async { - final inputAsset = buildStep.inputId; - final allowedOutputs = buildStep.allowedOutputs; - - if (allowedOutputs.length != 1) { - return; - } - - final outputAsset = allowedOutputs.first; - await _copyBinaryFile( - buildStep, - inputAsset: inputAsset, - outputAsset: outputAsset, - ); - } - - Future _copyBinaryFile( - BuildStep buildStep, { - required AssetId inputAsset, - required AssetId outputAsset, - }) { - return buildStep.writeAsBytes( - outputAsset, - buildStep.readAsBytes(inputAsset), - ); - } -} diff --git a/dwds/debug_extension_mv3/tool/update_dev_files.dart b/dwds/debug_extension_mv3/tool/update_dev_files.dart deleted file mode 100644 index 1659c5c15..000000000 --- a/dwds/debug_extension_mv3/tool/update_dev_files.dart +++ /dev/null @@ -1,92 +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 'dart:io'; - -void main() async { - await _updateManifestJson(); -} - -/// Adds the Googler extension key, and prefixes the extension name with "DEV". -Future _updateManifestJson() async { - final manifestJson = File('compiled/manifest.json'); - final extensionKeyTxt = File('extension_key.txt'); - final extensionKey = await extensionKeyTxt.exists() - ? await extensionKeyTxt.readAsString() - : null; - return _transformDevFile(manifestJson, (line) { - if (_matchesKey(line: line, key: 'name')) { - return [ - _newKeyValue( - oldLine: line, - newKey: 'name', - newValue: '[DEV] Dart Debug Extension', - ), - if (extensionKey != null) - _newKeyValue( - oldLine: line, - newKey: 'key', - newValue: extensionKey, - ), - ]; - } else if (_matchesKey(line: line, key: 'default_icon')) { - return [ - _newKeyValue( - oldLine: line, - newKey: 'default_icon', - newValue: 'static_assets/dart_dev.png', - ), - ]; - } else { - return [line]; - } - }); -} - -Future _transformDevFile( - File devFile, - List Function(String) transformLine, -) async { - final lines = devFile.readAsLinesSync(); - final newLines = []; - for (final line in lines) { - newLines.addAll(transformLine(line)); - } - final content = newLines.joinWithNewLine(); - return devFile.writeAsStringSync(content); -} - -bool _matchesKey({required String line, required String key}) { - return line.trimLeft().startsWith('"$key":'); -} - -String _newKeyValue({ - required String oldLine, - String? newKey, - String? newValue, -}) { - final lineStart = oldLine.leftPadding(); - final key = newKey != null ? '"$newKey": ' : ''; - final value = newValue != null ? '"$newValue"' : ''; - final lineEnd = oldLine.trim().endsWith(',') ? ',' : ''; - return '$lineStart$key$value$lineEnd'; -} - -extension LeftPaddingExtension on String { - String leftPadding() { - String padding = ''; - int idx = 0; - while (idx < length && this[idx] == ' ') { - padding += ' '; - idx++; - } - return padding; - } -} - -extension JoinExtension on List { - String joinWithNewLine() { - return '${join('\n')}\n'; - } -} diff --git a/dwds/debug_extension_mv3/web/background.dart b/dwds/debug_extension_mv3/web/background.dart deleted file mode 100644 index 5efd5307f..000000000 --- a/dwds/debug_extension_mv3/web/background.dart +++ /dev/null @@ -1,297 +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. - -@JS() -library background; - -import 'package:dwds/data/debug_info.dart'; -import 'package:js/js.dart'; - -import 'chrome_api.dart'; -import 'cider_connection.dart'; -import 'cross_extension_communication.dart'; -import 'data_types.dart'; -import 'debug_session.dart'; -import 'logger.dart'; -import 'messaging.dart'; -import 'storage.dart'; -import 'utils.dart'; - -void main() { - _registerListeners(); -} - -void _registerListeners() { - chrome.runtime.onMessage.addListener( - allowInterop(_handleRuntimeMessages), - ); - // The only extension allowed to send messages to this extension is the - // AngularDart DevTools extension. Its permission is set in the manifest.json - // externally_connectable field. - chrome.runtime.onMessageExternal.addListener( - allowInterop(handleMessagesFromAngularDartDevTools), - ); - // The only external service that sends messages to the Dart Debug Extension - // is Cider. - chrome.runtime.onConnectExternal - .addListener(allowInterop(handleCiderConnectRequest)); - // Update the extension icon on tab navigation: - chrome.tabs.onActivated.addListener( - allowInterop((ActiveInfo info) async { - await _updateIcon(info.tabId); - }), - ); - chrome.windows.onFocusChanged.addListener( - allowInterop((_) async { - final currentTab = await activeTab; - if (currentTab?.id != null) { - await _updateIcon(currentTab!.id); - } - }), - ); - chrome.webNavigation.onCommitted - .addListener(allowInterop(_detectNavigationAwayFromDartApp)); - - chrome.commands.onCommand - .addListener(allowInterop(_maybeSendCopyAppIdRequest)); -} - -Future _handleRuntimeMessages( - dynamic jsRequest, - MessageSender sender, - Function sendResponse, -) async { - if (jsRequest is! String) return; - - interceptMessage( - message: jsRequest, - expectedType: MessageType.isAuthenticated, - expectedSender: Script.detector, - expectedRecipient: Script.background, - sender: sender, - messageHandler: (String isAuthenticated) async { - final dartTab = sender.tab; - if (dartTab == null) { - debugWarn('Received auth info but tab is missing.'); - return; - } - // Save the authentication info in storage: - await setStorageObject( - type: StorageObject.isAuthenticated, - value: isAuthenticated, - tabId: dartTab.id, - ); - }, - ); - - interceptMessage( - message: jsRequest, - expectedType: MessageType.debugInfo, - expectedSender: Script.detector, - expectedRecipient: Script.background, - sender: sender, - messageHandler: (DebugInfo debugInfo) async { - final dartTab = sender.tab; - if (dartTab == null) { - debugWarn('Received debug info but tab is missing.'); - return; - } - // If this is a new Dart app, we need to clear old debug session data: - if (!await _matchesAppInStorage(debugInfo.appId, tabId: dartTab.id)) { - await clearStaleDebugSession(dartTab.id); - } - // Save the debug info for the Dart app in storage: - await setStorageObject( - type: StorageObject.debugInfo, - value: _addTabInfo(debugInfo, tab: dartTab), - tabId: dartTab.id, - ); - // Update the icon to show that a Dart app has been detected: - final currentTab = await activeTab; - if (currentTab?.id == dartTab.id) { - await _updateIcon(dartTab.id); - } - }, - ); - - interceptMessage( - message: jsRequest, - expectedType: MessageType.debugStateChange, - expectedSender: Script.debuggerPanel, - expectedRecipient: Script.background, - sender: sender, - messageHandler: (DebugStateChange debugStateChange) { - final newState = debugStateChange.newState; - final tabId = debugStateChange.tabId; - if (newState == DebugStateChange.startDebugging) { - attachDebugger(tabId, trigger: Trigger.extensionPanel); - } - }, - ); - - interceptMessage( - message: jsRequest, - expectedType: MessageType.debugStateChange, - expectedSender: Script.popup, - expectedRecipient: Script.background, - sender: sender, - messageHandler: (DebugStateChange debugStateChange) { - final newState = debugStateChange.newState; - final tabId = debugStateChange.tabId; - if (newState == DebugStateChange.startDebugging) { - attachDebugger(tabId, trigger: Trigger.extensionIcon); - } - }, - ); - - interceptMessage( - message: jsRequest, - expectedType: MessageType.multipleAppsDetected, - expectedSender: Script.detector, - expectedRecipient: Script.background, - sender: sender, - messageHandler: (String multipleAppsDetected) async { - final dartTab = sender.tab; - if (dartTab == null) { - debugWarn('Received multiple apps detected but tab is missing.'); - return; - } - // Save the multiple apps info in storage: - await setStorageObject( - type: StorageObject.multipleAppsDetected, - value: multipleAppsDetected, - tabId: dartTab.id, - ); - _setWarningIcon(dartTab.id); - }, - ); - - interceptMessage( - message: jsRequest, - expectedType: MessageType.appId, - expectedSender: Script.copier, - expectedRecipient: Script.background, - sender: sender, - messageHandler: (String appId) { - displayNotification('Copied app ID: $appId'); - }, - ); - - sendResponse(defaultResponse); -} - -Future _detectNavigationAwayFromDartApp( - NavigationInfo navigationInfo, -) async { - // Ignore any navigation events within the page itself (e.g., opening a link, - // reloading the page, reloading an IFRAME, etc): - if (_isInternalNavigation(navigationInfo)) return; - final tabId = navigationInfo.tabId; - final debugInfo = await _fetchDebugInfo(navigationInfo.tabId); - if (debugInfo == null) return; - if (debugInfo.tabUrl != navigationInfo.url) { - _setDefaultIcon(navigationInfo.tabId); - await clearStaleDebugSession(tabId); - await removeStorageObject(type: StorageObject.debugInfo, tabId: tabId); - await detachDebugger( - tabId, - type: TabType.dartApp, - reason: DetachReason.navigatedAwayFromApp, - ); - } -} - -bool _isInternalNavigation(NavigationInfo navigationInfo) { - return [ - 'auto_subframe', - 'form_submit', - 'link', - 'manual_subframe', - 'reload', - ].contains(navigationInfo.transitionType); -} - -DebugInfo _addTabInfo(DebugInfo debugInfo, {required Tab tab}) { - return DebugInfo( - (b) => b - ..appEntrypointPath = debugInfo.appEntrypointPath - ..appId = debugInfo.appId - ..appInstanceId = debugInfo.appInstanceId - ..appOrigin = debugInfo.appOrigin - ..appUrl = debugInfo.appUrl - ..authUrl = debugInfo.authUrl - ..extensionUrl = debugInfo.extensionUrl - ..isInternalBuild = debugInfo.isInternalBuild - ..isFlutterApp = debugInfo.isFlutterApp - ..workspaceName = debugInfo.workspaceName - ..tabUrl = tab.url - ..tabId = tab.id, - ); -} - -Future _maybeSendCopyAppIdRequest(String command, [Tab? tab]) async { - if (command != 'copyAppId') return false; - final tabId = (tab ?? await activeTab)?.id; - if (tabId == null) return false; - final debugInfo = await _fetchDebugInfo(tabId); - final workspaceName = debugInfo?.workspaceName; - if (workspaceName == null) return false; - final appId = '$workspaceName-$tabId'; - return sendTabsMessage( - tabId: tabId, - type: MessageType.appId, - body: appId, - sender: Script.background, - recipient: Script.copier, - ); -} - -Future _updateIcon(int activeTabId) async { - final debugInfo = await _fetchDebugInfo(activeTabId); - if (debugInfo == null) { - _setDefaultIcon(activeTabId); - return; - } - final multipleApps = await fetchStorageObject( - type: StorageObject.multipleAppsDetected, - tabId: activeTabId, - ); - multipleApps == null - ? _setDebuggableIcon(activeTabId) - : _setWarningIcon(activeTabId); -} - -void _setDebuggableIcon(int tabId) { - setExtensionIcon(IconInfo(path: 'static_assets/dart.png')); - setExtensionPopup( - PopupDetails(popup: 'static_assets/popup.html', tabId: tabId), - ); -} - -void _setWarningIcon(int tabId) { - setExtensionPopup( - PopupDetails(popup: 'static_assets/popup.html', tabId: tabId), - ); -} - -void _setDefaultIcon(int tabId) { - final iconPath = - isDevMode ? 'static_assets/dart_dev.png' : 'static_assets/dart_grey.png'; - setExtensionIcon(IconInfo(path: iconPath)); - setExtensionPopup( - PopupDetails(popup: '', tabId: tabId), - ); -} - -Future _fetchDebugInfo(int tabId) { - return fetchStorageObject( - type: StorageObject.debugInfo, - tabId: tabId, - ); -} - -Future _matchesAppInStorage(String? appId, {required int tabId}) async { - final debugInfo = await _fetchDebugInfo(tabId); - return appId != null && appId == debugInfo?.appId; -} diff --git a/dwds/debug_extension_mv3/web/chrome_api.dart b/dwds/debug_extension_mv3/web/chrome_api.dart deleted file mode 100644 index bb085cf8e..000000000 --- a/dwds/debug_extension_mv3/web/chrome_api.dart +++ /dev/null @@ -1,429 +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 'dart:html'; - -import 'package:js/js.dart'; - -@JS() -external Chrome get chrome; - -@JS() -@anonymous -class Chrome { - external Commands get commands; - external Debugger get debugger; - external Devtools get devtools; - external Notifications get notifications; - external Runtime get runtime; - external Storage get storage; - external Tabs get tabs; - external WebNavigation get webNavigation; - external Windows get windows; -} - -/// chrome.debugger APIs: -/// https://developer.chrome.com/docs/extensions/reference/debugger - -@JS() -@anonymous -class Commands { - external OnCommandHandler get onCommand; -} - -@JS() -@anonymous -class OnCommandHandler { - external void addListener( - void Function(String commandName, [Tab? tab]) callback, - ); -} - -@JS() -@anonymous -class Debugger { - external void attach( - Debuggee target, - String requiredVersion, - Function? callback, - ); - - external void detach(Debuggee target, Function? callback); - - external void sendCommand( - Debuggee target, - String method, - Object? commandParams, - Function? callback, - ); - - external OnDetachHandler get onDetach; - - external OnEventHandler get onEvent; -} - -@JS() -@anonymous -class OnDetachHandler { - external void addListener( - void Function(Debuggee source, String reason) callback, - ); -} - -@JS() -@anonymous -class OnEventHandler { - external void addListener( - void Function(Debuggee source, String method, Object? params) callback, - ); -} - -@JS() -@anonymous -class Debuggee { - external int get tabId; - external String get extensionId; - external String get targetId; - 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 String get themeName; - - 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 - -@JS() -@anonymous -class Notifications { - external void create( - String? notificationId, - NotificationOptions options, - Function? callback, - ); - - external OnClickedHandler get onClicked; -} - -@JS() -@anonymous -class OnClickedHandler { - external void addListener( - void Function(String) callback, - ); -} - -@JS() -@anonymous -class NotificationOptions { - external factory NotificationOptions({ - String title, - String message, - String iconUrl, - String type, - }); -} - -/// chrome.runtime APIs: -/// https://developer.chrome.com/docs/extensions/reference/runtime - -@JS() -@anonymous -class Runtime { - external void connect(String? extensionId, ConnectInfo info); - - external void sendMessage( - String? id, - Object? message, - Object? options, - Function? callback, - ); - - external Object getManifest(); - - external String getURL(String path); - - external String get id; - - // Note: Not checking the lastError when one occurs throws a runtime exception. - external ChromeError? get lastError; - - external ConnectionHandler get onConnect; - - external ConnectionHandler get onConnectExternal; - - external OnMessageHandler get onMessage; - - external OnMessageHandler get onMessageExternal; -} - -@JS() -class ChromeError { - external String get message; -} - -@JS() -@anonymous -class ConnectInfo { - external String? get name; - external factory ConnectInfo({String? name}); -} - -@JS() -@anonymous -class Port { - external String? get name; - external void disconnect(); - external void postMessage(Object message); - external OnPortMessageHandler get onMessage; - external ConnectionHandler get onDisconnect; -} - -@JS() -@anonymous -class OnPortMessageHandler { - external void addListener( - void Function(dynamic, Port) callback, - ); -} - -@JS() -@anonymous -class ConnectionHandler { - external void addListener(void Function(Port) callback); -} - -@JS() -@anonymous -class OnMessageHandler { - external void addListener( - dynamic Function(dynamic, MessageSender, Function) callback, - ); -} - -@JS() -@anonymous -class MessageSender { - external String? get id; - external Tab? get tab; - external String? get url; - external String? get origin; - external factory MessageSender({String? id, String? url, Tab? tab}); -} - -@JS() -@anonymous -class Target { - external int get tabId; - external factory Target({int tabId}); -} - -/// chrome.storage APIs -/// https://developer.chrome.com/docs/extensions/reference/storage - -@JS() -@anonymous -class Storage { - external StorageArea get local; - - external StorageArea get session; - - external OnChangedHandler get onChanged; -} - -@JS() -@anonymous -class StorageArea { - external Object get( - List? keys, - void Function(Object result) callback, - ); - - external Object set(Object items, void Function()? callback); - - external Object remove(List keys, 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 - -@JS() -@anonymous -class Tabs { - external dynamic query( - QueryInfo queryInfo, - void Function(List) callback, - ); - - external dynamic create(TabInfo tabInfo, void Function(Tab) callback); - - external dynamic get(int tabId, void Function(Tab?) callback); - - external dynamic remove(int tabId, void Function()? callback); - - external Object sendMessage( - int tabId, - Object? message, - Object? options, - void Function() callback, - ); - - external OnActivatedHandler get onActivated; - - external OnRemovedHandler get onRemoved; -} - -@JS() -@anonymous -class OnActivatedHandler { - external void addListener(void Function(ActiveInfo activeInfo) callback); -} - -@JS() -@anonymous -class OnRemovedHandler { - external void addListener(void Function(int tabId, dynamic info) callback); -} - -@JS() -@anonymous -class ActiveInfo { - external int get tabId; -} - -@JS() -@anonymous -class TabInfo { - external bool? get active; - external bool? get pinned; - external String? get url; - external factory TabInfo({bool? active, bool? pinned, String? url}); -} - -@JS() -@anonymous -class QueryInfo { - external bool get active; - external bool get currentWindow; - external String get url; - external factory QueryInfo({bool? active, bool? currentWindow, String? url}); -} - -@JS() -@anonymous -class Tab { - external int get id; - external String get url; -} - -/// chrome.webNavigation APIs -/// https://developer.chrome.com/docs/extensions/reference/webNavigation - -@JS() -@anonymous -class WebNavigation { - // https://developer.chrome.com/docs/extensions/reference/webNavigation/#event-onCommitted - external OnCommittedHandler get onCommitted; -} - -@JS() -@anonymous -class OnCommittedHandler { - external void addListener(void Function(NavigationInfo details) callback); -} - -@JS() -@anonymous -class NavigationInfo { - external String get transitionType; - external int get tabId; - external String get url; -} - -/// chrome.windows APIs -/// https://developer.chrome.com/docs/extensions/reference/windows - -@JS() -@anonymous -class Windows { - external dynamic create(WindowInfo? createData, Function(WindowObj) callback); - - external OnFocusChangedHandler get onFocusChanged; -} - -@JS() -@anonymous -class OnFocusChangedHandler { - external void addListener(void Function(int windowId) callback); -} - -@JS() -@anonymous -class WindowInfo { - external bool? get focused; - external String? get url; - external factory WindowInfo({bool? focused, String? url}); -} - -@JS() -@anonymous -class WindowObj { - external int get id; - external List get tabs; -} diff --git a/dwds/debug_extension_mv3/web/manifest_mv2.json b/dwds/debug_extension_mv3/web/manifest_mv2.json deleted file mode 100644 index 78ce8d184..000000000 --- a/dwds/debug_extension_mv3/web/manifest_mv2.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "Dart Debug Extension", - "version": "2.1", - "manifest_version": 2, - "devtools_page": "static_assets/devtools.html", - "browser_action": { - "default_icon": "static_assets/dart_grey.png" - }, - "externally_connectable": { - "ids": ["nbkbficgbembimioedhceniahniffgpl"], - "matches": [ - "https://cider.corp.google.com/*", - "https://cider-staging.corp.google.com/*", - "https://cider-test.corp.google.com/*", - "https://cider-v.corp.google.com/*", - "https://cider-v-staging.corp.google.com/*", - "https://cider-v-test.corp.google.com/*" - ] - }, - "permissions": ["debugger", "notifications", "storage", "webNavigation"], - "background": { - "scripts": ["background.dart.js"] - }, - "content_scripts": [ - { - "matches": [""], - "js": ["detector.dart.js", "copier.dart.js"], - "run_at": "document_end" - } - ], - "commands": { - "copyAppId": { - "suggestedKey": { - "default": "Ctrl+Shift+7", - "mac": "Command+Shift+7" - }, - "description": "Copy the app ID" - } - }, - "web_accessible_resources": ["debug_info.dart.js"] -} diff --git a/dwds/debug_extension_mv3/web/manifest_mv3.json b/dwds/debug_extension_mv3/web/manifest_mv3.json deleted file mode 100644 index 83ecae394..000000000 --- a/dwds/debug_extension_mv3/web/manifest_mv3.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "Dart Debug Extension", - "version": "2.1.4", - "manifest_version": 3, - "devtools_page": "static_assets/devtools.html", - "action": { - "default_icon": "static_assets/dart_grey.png" - }, - "externally_connectable": { - "ids": ["nbkbficgbembimioedhceniahniffgpl"], - "matches": [ - "https://cider.corp.google.com/*", - "https://cider-staging.corp.google.com/*", - "https://cider-test.corp.google.com/*", - "https://cider-v.corp.google.com/*", - "https://cider-v-staging.corp.google.com/*", - "https://cider-v-test.corp.google.com/*" - ] - }, - "permissions": ["debugger", "notifications", "storage", "webNavigation"], - "host_permissions": [""], - "background": { - "service_worker": "background.dart.js" - }, - "content_scripts": [ - { - "matches": [""], - "js": ["detector.dart.js", "copier.dart.js"], - "run_at": "document_end" - } - ], - "commands": { - "copyAppId": { - "suggestedKey": { - "default": "Ctrl+Shift+7", - "mac": "Command+Shift+7" - }, - "description": "Copy the app ID" - } - }, - "web_accessible_resources": [ - { - "matches": [""], - "resources": ["debug_info.dart.js"] - } - ] -} diff --git a/dwds/debug_extension_mv3/web/static_assets/dart.png b/dwds/debug_extension_mv3/web/static_assets/dart.png deleted file mode 100644 index 47e4b7b7d..000000000 Binary files a/dwds/debug_extension_mv3/web/static_assets/dart.png and /dev/null differ diff --git a/dwds/debug_extension_mv3/web/static_assets/dart_dev.png b/dwds/debug_extension_mv3/web/static_assets/dart_dev.png deleted file mode 100644 index 8d0479209..000000000 Binary files a/dwds/debug_extension_mv3/web/static_assets/dart_dev.png and /dev/null differ diff --git a/dwds/debug_extension_mv3/web/static_assets/dart_grey.png b/dwds/debug_extension_mv3/web/static_assets/dart_grey.png deleted file mode 100644 index 3afba3fbe..000000000 Binary files a/dwds/debug_extension_mv3/web/static_assets/dart_grey.png and /dev/null differ diff --git a/dwds/debug_extension_mv3/web/static_assets/dart_warning.png b/dwds/debug_extension_mv3/web/static_assets/dart_warning.png deleted file mode 100644 index 9608d0d1e..000000000 Binary files a/dwds/debug_extension_mv3/web/static_assets/dart_warning.png and /dev/null differ diff --git a/dwds/debug_extension_mv3/web/web_api.dart b/dwds/debug_extension_mv3/web/web_api.dart deleted file mode 100644 index 1a5134475..000000000 --- a/dwds/debug_extension_mv3/web/web_api.dart +++ /dev/null @@ -1,66 +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 'dart:html'; -import 'dart:js_util' as js_util; - -import 'package:js/js.dart'; - -@JS() -// ignore: non_constant_identifier_names -external Json get JSON; - -@JS() -@anonymous -class Json { -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify - external String stringify(o); -} - -// Custom implementation of Fetch API until the Dart implementation supports -// credentials. See https://github.com/dart-lang/http/issues/595. -@JS('fetch') -external Object _nativeJsFetch(String resourceUrl, FetchOptions options); - -Future fetchRequest(String resourceUrl) async { - try { - final options = FetchOptions( - method: 'GET', - credentials: 'include', - ); - final response = - await promiseToFuture(_nativeJsFetch(resourceUrl, options)); - final body = - await promiseToFuture(js_util.callMethod(response, 'text', [])); - final ok = js_util.getProperty(response, 'ok'); - final status = js_util.getProperty(response, 'status'); - return FetchResponse(status: status, ok: ok, body: body); - } catch (error) { - return FetchResponse( - status: 400, - ok: false, - body: 'Error fetching $resourceUrl: $error', - ); - } -} - -@JS() -@anonymous -class FetchOptions { - external factory FetchOptions({ - required String method, // e.g., 'GET', 'POST' - required String credentials, // e.g., 'omit', 'same-origin', 'include' - }); -} - -class FetchResponse { - final int status; - final bool ok; - final String? body; - - FetchResponse({ - required this.status, - required this.ok, - required this.body, - }); -} diff --git a/dwds/test/puppeteer/extension_common.dart b/dwds/test/puppeteer/extension_common.dart index d7597640b..28edff1e0 100644 --- a/dwds/test/puppeteer/extension_common.dart +++ b/dwds/test/puppeteer/extension_common.dart @@ -19,7 +19,7 @@ import 'package:test/test.dart'; import 'package:test_common/test_sdk_configuration.dart'; import 'package:test_common/utilities.dart'; -import '../../debug_extension_mv3/web/data_serializers.dart'; +import '../../debug_extension/web/data_serializers.dart'; import '../fixtures/context.dart'; import '../fixtures/project.dart'; import '../fixtures/utilities.dart'; diff --git a/dwds/test/puppeteer/test_utils.dart b/dwds/test/puppeteer/test_utils.dart index 5ef574766..906628fbf 100644 --- a/dwds/test/puppeteer/test_utils.dart +++ b/dwds/test/puppeteer/test_utils.dart @@ -23,7 +23,7 @@ final _devToolsLogs = []; final _workerLogs = []; Future buildDebugExtension({required bool isMV3}) async { - final extensionDir = absolutePath(pathFromDwds: 'debug_extension_mv3'); + final extensionDir = absolutePath(pathFromDwds: 'debug_extension'); await Process.run( 'dart', [