From 32abb8261f22c2684b78ac5f3e0637ebf2ec250d Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Fri, 20 Oct 2023 16:29:49 -0700 Subject: [PATCH 01/15] Not quite working --- dwds/debug_extension_mv3/web/background.dart | 49 +++++--- dwds/debug_extension_mv3/web/popup.dart | 112 ++++++++++++++++++ .../web/static_assets/popup.html | 52 ++++++++ dwds/debug_extension_mv3/web/utils.dart | 30 +++++ 4 files changed, 227 insertions(+), 16 deletions(-) create mode 100644 dwds/debug_extension_mv3/web/popup.dart create mode 100644 dwds/debug_extension_mv3/web/static_assets/popup.html diff --git a/dwds/debug_extension_mv3/web/background.dart b/dwds/debug_extension_mv3/web/background.dart index b24d44629..29d5c2586 100644 --- a/dwds/debug_extension_mv3/web/background.dart +++ b/dwds/debug_extension_mv3/web/background.dart @@ -54,16 +54,23 @@ void _registerListeners() { .addListener(allowInterop(_detectNavigationAwayFromDartApp)); // Detect clicks on the Dart Debug Extension icon. - onExtensionIconClicked( - allowInterop( - (Tab tab) => attachDebugger( - tab.id, - trigger: Trigger.extensionIcon, - ), - ), - ); + // onExtensionIconClicked( + // allowInterop( + // (Tab tab) => attachDebugger( + // tab.id, + // trigger: Trigger.extensionIcon, + // ), + // ), + // ); } +// void _handleExtensionIconClick(Tab tab) { +// if (!isDevMode) { +// attachDebugger(tab.id, trigger: Trigger.extensionIcon); +// return; +// } +// } + Future _handleRuntimeMessages( dynamic jsRequest, MessageSender sender, @@ -152,7 +159,7 @@ Future _handleRuntimeMessages( value: multipleAppsDetected, tabId: dartTab.id, ); - _setWarningIcon(); + _setWarningIcon(dartTab.id); }, ); } @@ -167,7 +174,7 @@ Future _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( @@ -209,28 +216,38 @@ DebugInfo _addTabInfo(DebugInfo debugInfo, {required Tab tab}) { Future _updateIcon(int activeTabId) async { final debugInfo = await _fetchDebugInfo(activeTabId); if (debugInfo == null) { - _setDefaultIcon(); + _setDefaultIcon(activeTabId); return; } final multipleApps = await fetchStorageObject( 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 _fetchDebugInfo(int tabId) { diff --git a/dwds/debug_extension_mv3/web/popup.dart b/dwds/debug_extension_mv3/web/popup.dart new file mode 100644 index 000000000..decfb095c --- /dev/null +++ b/dwds/debug_extension_mv3/web/popup.dart @@ -0,0 +1,112 @@ +// 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 _hiddenClass = 'hidden'; +const _launchDevToolsButtonId = 'launchDevToolsButton'; +const _copyButtonId = 'copyButton'; +const _appIdSpanId = 'appId'; +const _appIdContainerId = 'appIdContainer'; +const _loadingSpinnerId = "loadingSpinner"; +const _copiedSuccessId = "copiedSuccess"; + +Future get _tabId async { + final tab = await activeTab; + return tab?.id; +} + +String? _appId; + +Future main() async { + _registerListeners(); + + final inserted = await _insertAppId(); + if (inserted) { + _updateElementVisibility(_appIdContainerId, visible: true); + } + // _updateElementVisibility(_loadingSpinnerId, visible: false); +} + +void _registerListeners() { + final launchDevToolsButton = + document.getElementById(_launchDevToolsButtonId) as ButtonElement; + launchDevToolsButton.addEventListener('click', _launchDevTools); + + final copyButton = document.getElementById(_copyButtonId) as ButtonElement; + copyButton.addEventListener('click', _copyAppId); +} + +Future _insertAppId() async { + final tabId = await _tabId; + final debugInfo = await fetchStorageObject( + type: StorageObject.debugInfo, + tabId: tabId, + ); + if (debugInfo == null || tabId == null) return false; + // final isInternalBuild = debugInfo.isInternalBuild ?? false; + // if (isInternalBuild) { + final _appId = _createAppId(debugInfo: debugInfo, tabId: tabId); + final appIdSpan = document.getElementById(_appIdSpanId) as SpanElement; + appIdSpan.setInnerHtml(_appId); + // } + // return isInternalBuild; + return true; +} + +String _createAppId({required DebugInfo debugInfo, required int tabId}) { + final workspaceName = debugInfo.workspaceName; + return '$workspaceName-$tabId'; +} + +Future _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.debuggerPanel, // 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); +} + +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); + } +} diff --git a/dwds/debug_extension_mv3/web/static_assets/popup.html b/dwds/debug_extension_mv3/web/static_assets/popup.html new file mode 100644 index 000000000..26ff598ad --- /dev/null +++ b/dwds/debug_extension_mv3/web/static_assets/popup.html @@ -0,0 +1,52 @@ + + + + + + + + + + +
    +
  • + +
  • + + +
+ + + + + diff --git a/dwds/debug_extension_mv3/web/utils.dart b/dwds/debug_extension_mv3/web/utils.dart index afd79082f..36f1f3dce 100644 --- a/dwds/debug_extension_mv3/web/utils.dart +++ b/dwds/debug_extension_mv3/web/utils.dart @@ -110,6 +110,22 @@ void setExtensionIcon(IconInfo info) { } } +void setExtensionPopup(PopupDetails details) { + if (isMV3) { + _setExtensionPopupMV3( + details, + // callback + null, + ); + } else { + _setExtensionPopupMV2( + details, + // callback + null, + ); + } +} + bool? _isDevMode; bool get isDevMode { @@ -164,6 +180,12 @@ external void _setExtensionIconMV2(IconInfo iconInfo, Function? callback); @JS('chrome.action.setIcon') external void _setExtensionIconMV3(IconInfo iconInfo, Function? callback); +@JS('chrome.browserAction.setPopup') +external void _setExtensionPopupMV2(PopupDetails details, Function? callback); + +@JS('chrome.action.setPopup') +external void _setExtensionPopupMV3(PopupDetails details, Function? callback); + @JS() @anonymous class IconInfo { @@ -171,6 +193,14 @@ class IconInfo { external factory IconInfo({required String path}); } +@JS() +@anonymous +class PopupDetails { + external int get tabId; + external String get popup; + external factory PopupDetails({required int tabId, required String popup}); +} + @JS('chrome.scripting.executeScript') external Object _executeScriptMV3(_InjectDetails details); From f79609aaa56645d492025afe7bacc30e2b90c249 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Mon, 23 Oct 2023 14:54:06 -0700 Subject: [PATCH 02/15] wip --- dwds/debug_extension_mv3/web/popup.dart | 3 ++ .../web/static_assets/popup.html | 15 ++++--- .../web/static_assets/styles.css | 41 +++++++++++++++++-- 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/dwds/debug_extension_mv3/web/popup.dart b/dwds/debug_extension_mv3/web/popup.dart index decfb095c..1fd99b5ad 100644 --- a/dwds/debug_extension_mv3/web/popup.dart +++ b/dwds/debug_extension_mv3/web/popup.dart @@ -14,6 +14,7 @@ import 'package:js/js.dart'; import 'data_serializers.dart'; import 'data_types.dart'; +import 'logger.dart'; import 'messaging.dart'; import 'storage.dart'; import 'utils.dart'; @@ -36,7 +37,9 @@ String? _appId; Future main() async { _registerListeners(); + debugLog('inserting app id'); final inserted = await _insertAppId(); + debugLog('done inserting app id'); if (inserted) { _updateElementVisibility(_appIdContainerId, visible: true); } diff --git a/dwds/debug_extension_mv3/web/static_assets/popup.html b/dwds/debug_extension_mv3/web/static_assets/popup.html index 26ff598ad..2be451486 100644 --- a/dwds/debug_extension_mv3/web/static_assets/popup.html +++ b/dwds/debug_extension_mv3/web/static_assets/popup.html @@ -15,7 +15,7 @@ @@ -25,27 +25,30 @@
  • -
  • - + + blah-blah-blah
  • - + diff --git a/dwds/debug_extension_mv3/web/static_assets/styles.css b/dwds/debug_extension_mv3/web/static_assets/styles.css index f5da6a7f6..1e6162e79 100644 --- a/dwds/debug_extension_mv3/web/static_assets/styles.css +++ b/dwds/debug_extension_mv3/web/static_assets/styles.css @@ -57,16 +57,16 @@ iframe { } .debugger-card > .mdl-card__title { + background: url("debugger_settings.png"); background-position: center; background-repeat: no-repeat; - background: url("debugger_settings.png"); height: 200px; } .inspector-card > .mdl-card__title { + background: url("inspect_widget.png"); background-position: center; background-repeat: no-repeat; - background: url("inspect_widget.png"); height: 300px; } @@ -87,8 +87,8 @@ h6 { } .snackbar > a { - font-weight: bold; color: #eeeeee; + font-weight: bold; } .snackbar--info { @@ -109,6 +109,10 @@ h6 { visibility: none; } +.small-padding { + margin: 0 16px; +} + @-webkit-keyframes fadein { from { bottom: 0; @@ -152,3 +156,34 @@ h6 { opacity: 0; } } + +@keyframes spinner { + to { + transform: rotate(360deg); + } +} + +.spinner:before { + animation: spinner 0.9s linear infinite; + border: 6px solid #ffffff; + border-radius: 50%; + border-top-color: #4489ff; + box-sizing: border-box; + content: ""; + height: 50px; + left: 50%; + margin-left: -10px; + margin-top: -10px; + position: absolute; + top: 50%; + width: 50px; +} + +.spinner-overlay { + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; + background: #ffffff; +} From ff5eca912acbeb53cab36a831048e20c2ef7eafe Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Mon, 23 Oct 2023 16:30:55 -0700 Subject: [PATCH 03/15] Popup is working as expected --- dwds/debug_extension_mv3/web/background.dart | 14 +++++++ dwds/debug_extension_mv3/web/messaging.dart | 3 +- dwds/debug_extension_mv3/web/popup.dart | 37 ++++++++----------- .../web/static_assets/popup.html | 10 ++--- 4 files changed, 36 insertions(+), 28 deletions(-) diff --git a/dwds/debug_extension_mv3/web/background.dart b/dwds/debug_extension_mv3/web/background.dart index 29d5c2586..c8d20fad1 100644 --- a/dwds/debug_extension_mv3/web/background.dart +++ b/dwds/debug_extension_mv3/web/background.dart @@ -142,6 +142,20 @@ Future _handleRuntimeMessages( }, ); + interceptMessage( + 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( message: jsRequest, expectedType: MessageType.multipleAppsDetected, diff --git a/dwds/debug_extension_mv3/web/messaging.dart b/dwds/debug_extension_mv3/web/messaging.dart index 95f27deae..a7c4de056 100644 --- a/dwds/debug_extension_mv3/web/messaging.dart +++ b/dwds/debug_extension_mv3/web/messaging.dart @@ -17,7 +17,8 @@ import 'logger.dart'; enum Script { background, debuggerPanel, - detector; + detector, + popup; factory Script.fromString(String value) { return Script.values.byName(value); diff --git a/dwds/debug_extension_mv3/web/popup.dart b/dwds/debug_extension_mv3/web/popup.dart index 1fd99b5ad..9a3633702 100644 --- a/dwds/debug_extension_mv3/web/popup.dart +++ b/dwds/debug_extension_mv3/web/popup.dart @@ -14,18 +14,17 @@ import 'package:js/js.dart'; import 'data_serializers.dart'; import 'data_types.dart'; -import 'logger.dart'; import 'messaging.dart'; import 'storage.dart'; import 'utils.dart'; +const _appIdContainerId = 'appIdContainer'; +const _appIdSpanId = 'appId'; +const _copyIdButtonId = 'copyIdButton'; +const _copiedSuccessId = "copiedSuccess"; const _hiddenClass = 'hidden'; const _launchDevToolsButtonId = 'launchDevToolsButton'; -const _copyButtonId = 'copyButton'; -const _appIdSpanId = 'appId'; -const _appIdContainerId = 'appIdContainer'; const _loadingSpinnerId = "loadingSpinner"; -const _copiedSuccessId = "copiedSuccess"; Future get _tabId async { final tab = await activeTab; @@ -37,13 +36,11 @@ String? _appId; Future main() async { _registerListeners(); - debugLog('inserting app id'); final inserted = await _insertAppId(); - debugLog('done inserting app id'); if (inserted) { _updateElementVisibility(_appIdContainerId, visible: true); } - // _updateElementVisibility(_loadingSpinnerId, visible: false); + _updateElementVisibility(_loadingSpinnerId, visible: false); } void _registerListeners() { @@ -51,7 +48,7 @@ void _registerListeners() { document.getElementById(_launchDevToolsButtonId) as ButtonElement; launchDevToolsButton.addEventListener('click', _launchDevTools); - final copyButton = document.getElementById(_copyButtonId) as ButtonElement; + final copyButton = document.getElementById(_copyIdButtonId) as ButtonElement; copyButton.addEventListener('click', _copyAppId); } @@ -62,19 +59,15 @@ Future _insertAppId() async { tabId: tabId, ); if (debugInfo == null || tabId == null) return false; - // final isInternalBuild = debugInfo.isInternalBuild ?? false; - // if (isInternalBuild) { - final _appId = _createAppId(debugInfo: debugInfo, tabId: tabId); - final appIdSpan = document.getElementById(_appIdSpanId) as SpanElement; - appIdSpan.setInnerHtml(_appId); - // } - // return isInternalBuild; - return true; -} - -String _createAppId({required DebugInfo debugInfo, required int tabId}) { + final isInternalBuild = debugInfo.isInternalBuild ?? false; final workspaceName = debugInfo.workspaceName; - return '$workspaceName-$tabId'; + if (isInternalBuild && workspaceName != null) { + _appId = '$workspaceName-$tabId'; + final appIdSpan = document.getElementById(_appIdSpanId) as SpanElement; + appIdSpan.setInnerHtml(_appId); + return true; + } + return false; } Future _launchDevTools(Event _) async { @@ -91,7 +84,7 @@ Future _launchDevTools(Event _) async { await sendRuntimeMessage( type: MessageType.debugStateChange, body: json, - sender: Script.debuggerPanel, // change to popup + sender: Script.popup, // change to popup recipient: Script.background, ); } diff --git a/dwds/debug_extension_mv3/web/static_assets/popup.html b/dwds/debug_extension_mv3/web/static_assets/popup.html index 2be451486..c196cfaa1 100644 --- a/dwds/debug_extension_mv3/web/static_assets/popup.html +++ b/dwds/debug_extension_mv3/web/static_assets/popup.html @@ -14,7 +14,7 @@ @@ -25,7 +25,7 @@
  • @@ -41,12 +41,12 @@ - - blah-blah-blah + +
  • -