Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: dart-lang/webdev
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 63e09e5
Choose a base ref
..
head repository: dart-lang/webdev
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8375cd6
Choose a head ref
4 changes: 3 additions & 1 deletion dwds/debug_extension_mv3/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: mv3_extension
publish_to: none
version: 2.0.0
version: 2.1.0
homepage: https://github.com/dart-lang/webdev
description: >-
A Chrome extension for Dart debugging.
@@ -14,12 +14,14 @@ dependencies:
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

50 changes: 32 additions & 18 deletions dwds/debug_extension_mv3/web/background.dart
Original file line number Diff line number Diff line change
@@ -55,16 +55,6 @@ void _registerListeners() {

chrome.commands.onCommand
.addListener(allowInterop(_maybeSendCopyAppIdRequest));

// Detect clicks on the Dart Debug Extension icon.
onExtensionIconClicked(
allowInterop(
(Tab tab) => attachDebugger(
tab.id,
trigger: Trigger.extensionIcon,
),
),
);
}

Future<void> _handleRuntimeMessages(
@@ -137,6 +127,20 @@ Future<void> _handleRuntimeMessages(
},
);

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

interceptMessage<String>(
message: jsRequest,
expectedType: MessageType.multipleAppsDetected,
@@ -154,7 +158,7 @@ Future<void> _handleRuntimeMessages(
value: multipleAppsDetected,
tabId: dartTab.id,
);
_setWarningIcon();
_setWarningIcon(dartTab.id);
},
);

@@ -181,7 +185,7 @@ Future<void> _detectNavigationAwayFromDartApp(
final debugInfo = await _fetchDebugInfo(navigationInfo.tabId);
if (debugInfo == null) return;
if (debugInfo.tabUrl != navigationInfo.url) {
_setDefaultIcon();
_setDefaultIcon(navigationInfo.tabId);
await clearStaleDebugSession(tabId);
await removeStorageObject(type: StorageObject.debugInfo, tabId: tabId);
await detachDebugger(
@@ -240,28 +244,38 @@ Future<bool> _maybeSendCopyAppIdRequest(String command, [Tab? tab]) async {
Future<void> _updateIcon(int activeTabId) async {
final debugInfo = await _fetchDebugInfo(activeTabId);
if (debugInfo == null) {
_setDefaultIcon();
_setDefaultIcon(activeTabId);
return;
}
final multipleApps = await fetchStorageObject<String>(
type: StorageObject.multipleAppsDetected,
tabId: activeTabId,
);
multipleApps == null ? _setDebuggableIcon() : _setWarningIcon();
multipleApps == null
? _setDebuggableIcon(activeTabId)
: _setWarningIcon(activeTabId);
}

void _setDebuggableIcon() {
void _setDebuggableIcon(int tabId) {
setExtensionIcon(IconInfo(path: 'static_assets/dart.png'));
setExtensionPopup(
PopupDetails(popup: 'static_assets/popup.html', tabId: tabId),
);
}

void _setWarningIcon() {
setExtensionIcon(IconInfo(path: 'static_assets/dart_warning.png'));
void _setWarningIcon(int tabId) {
setExtensionPopup(
PopupDetails(popup: 'static_assets/popup.html', tabId: tabId),
);
}

void _setDefaultIcon() {
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<DebugInfo?> _fetchDebugInfo(int tabId) {
5 changes: 2 additions & 3 deletions dwds/debug_extension_mv3/web/manifest_mv2.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Dart Debug Extension",
"version": "2.0",
"version": "2.1",
"manifest_version": 2,
"devtools_page": "static_assets/devtools.html",
"browser_action": {
@@ -37,6 +37,5 @@
"description": "Copy the app ID"
}
},
"web_accessible_resources": ["debug_info.dart.js"],
"options_page": "static_assets/settings.html"
"web_accessible_resources": ["debug_info.dart.js"]
}
5 changes: 2 additions & 3 deletions dwds/debug_extension_mv3/web/manifest_mv3.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Dart Debug Extension",
"version": "2.0",
"version": "2.1",
"manifest_version": 3,
"devtools_page": "static_assets/devtools.html",
"action": {
@@ -43,6 +43,5 @@
"matches": ["<all_urls>"],
"resources": ["debug_info.dart.js"]
}
],
"options_page": "static_assets/settings.html"
]
}
3 changes: 2 additions & 1 deletion dwds/debug_extension_mv3/web/messaging.dart
Original file line number Diff line number Diff line change
@@ -25,7 +25,8 @@ enum Script {
background,
copier,
debuggerPanel,
detector;
detector,
popup;

factory Script.fromString(String value) {
return Script.values.byName(value);
170 changes: 170 additions & 0 deletions dwds/debug_extension_mv3/web/popup.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// Copyright (c) 2023, 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 popup;

import 'dart:async';
import 'dart:convert';
import 'dart:html';

import 'package:dwds/data/debug_info.dart';
import 'package:js/js.dart';

import 'data_serializers.dart';
import 'data_types.dart';
import 'messaging.dart';
import 'storage.dart';
import 'utils.dart';

const _appIdContainerId = 'appIdContainer';
const _appIdDividerId = 'appIdDivider';
const _appIdSpanId = 'appId';
const _copyIdButtonId = 'copyIdButton';
const _copiedSuccessId = 'copiedSuccess';
const _fileBugButtonId = 'fileBugButton';
const _hiddenClass = 'hidden';
const _launchDevToolsButtonId = 'launchDevToolsButton';
const _loadingSpinnerId = 'loadingSpinner';
const _windowOption = 'windowOption';
const _tabOption = 'tabOption';

Future<int?> get _tabId async {
final tab = await activeTab;
return tab?.id;
}

String? _appId;

Future<void> main() async {
_registerListeners();
await _loadUiAndHideSpinner();
}

void _registerListeners() {
final launchDevToolsButton =
document.getElementById(_launchDevToolsButtonId) as ButtonElement;
launchDevToolsButton.addEventListener('click', _launchDevTools);

final copyButton = document.getElementById(_copyIdButtonId) as ButtonElement;
copyButton.addEventListener('click', _copyAppId);

final fileABugButton =
document.getElementById(_fileBugButtonId) as ButtonElement;
fileABugButton.addEventListener('click', _openIssueTracker);

document.addEventListener('DOMContentLoaded', _updateSettingsFromStorage);

final windowOption = document.getElementById(_windowOption) as InputElement;
windowOption.addEventListener('change', (Event _) {
_saveSettingsToStorage(windowOption.value);
});

final tabOption = document.getElementById(_tabOption) as InputElement;
tabOption.addEventListener('change', (Event _) {
_saveSettingsToStorage(tabOption.value);
});
}

Future<void> _loadUiAndHideSpinner() async {
final inserted = await _insertAppId();
if (inserted) {
_updateElementVisibility(_appIdContainerId, visible: true);
_updateElementVisibility(_appIdDividerId, visible: true);
}
_updateElementVisibility(_loadingSpinnerId, visible: false);
}

Future<DebugInfo?> _fetchDebugInfo(int? tabId) async {
if (tabId == null) return null;
final debugInfo = await fetchStorageObject<DebugInfo>(
type: StorageObject.debugInfo,
tabId: tabId,
);
return debugInfo;
}

Future<bool> _insertAppId() async {
final tabId = await _tabId;
final debugInfo = await _fetchDebugInfo(tabId);
if (debugInfo == null) return false;
final isInternalBuild = debugInfo.isInternalBuild ?? false;
final workspaceName = debugInfo.workspaceName;
if (isInternalBuild && workspaceName != null) {
_appId = '$workspaceName-$tabId';
final appIdSpan = document.getElementById(_appIdSpanId) as SpanElement;
appIdSpan.setInnerHtml(_appId);
return true;
}
return false;
}

Future<void> _openIssueTracker(Event _) async {
final debugInfo = await _fetchDebugInfo(await _tabId);
final isInternalBuild = debugInfo?.isInternalBuild ?? false;
final issueTrackerLink = isInternalBuild
? 'http://b/issues/new?component=775375&template=1791321'
: 'https://github.com/dart-lang/webdev/issues/new?labels=dart-debug-extension&projects=&template=dart_debug_extension.md';
await createTab(issueTrackerLink);
}

Future<void> _launchDevTools(Event _) async {
final tabId = await _tabId;
final json = jsonEncode(
serializers.serialize(
DebugStateChange(
(b) => b
..tabId = tabId
..newState = DebugStateChange.startDebugging,
),
),
);
await sendRuntimeMessage(
type: MessageType.debugStateChange,
body: json,
sender: Script.popup, // change to popup
recipient: Script.background,
);
}

void _copyAppId(Event _) {
if (_appId == null) return;
final clipboard = window.navigator.clipboard;
if (clipboard == null) return;
clipboard.writeText(_appId!);
_updateElementVisibility(_copiedSuccessId, visible: true);
}

Future<void> _updateSettingsFromStorage(Event _) async {
final devToolsOpener = await fetchStorageObject<DevToolsOpener>(
type: StorageObject.devToolsOpener,
);
final openInNewWindow = devToolsOpener?.newWindow ?? false;
_getRadioButton(_windowOption).checked = openInNewWindow;
_getRadioButton(_tabOption).checked = !openInNewWindow;
}

Future<void> _saveSettingsToStorage(String? devToolsOpener) async {
if (devToolsOpener == null) return;
await setStorageObject<DevToolsOpener>(
type: StorageObject.devToolsOpener,
value: DevToolsOpener(
(b) => b..newWindow = devToolsOpener == 'window',
),
);
}

RadioButtonInputElement _getRadioButton(String id) {
return document.getElementById(id) as RadioButtonInputElement;
}

void _updateElementVisibility(String elementId, {required bool visible}) {
final element = document.getElementById(elementId);
if (element == null) return;
if (visible) {
element.classes.remove(_hiddenClass);
} else {
element.classes.add(_hiddenClass);
}
}
Loading