From ec34001666866f37c290b641674b8c6bafa9da52 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Wed, 29 Apr 2026 15:29:07 -0700 Subject: [PATCH 1/4] Use default service extension states in UI even when they are not available. --- .../lib/src/service/service_extension_widgets.dart | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/devtools_app/lib/src/service/service_extension_widgets.dart b/packages/devtools_app/lib/src/service/service_extension_widgets.dart index 2c631484552..7fdd4b4ad9a 100644 --- a/packages/devtools_app/lib/src/service/service_extension_widgets.dart +++ b/packages/devtools_app/lib/src/service/service_extension_widgets.dart @@ -538,12 +538,9 @@ class _ServiceExtensionCheckboxState extends State void _onMainIsolateChanged() => _initExtensionState(); void _initExtensionState() { - if (serviceConnection.serviceManager.serviceExtensionManager - .isServiceExtensionAvailable(widget.serviceExtension.extension)) { - final state = serviceConnection.serviceManager.serviceExtensionManager - .getServiceExtensionState(widget.serviceExtension.extension); - _setValueFromState(state.value); - } + final state = serviceConnection.serviceManager.serviceExtensionManager + .getServiceExtensionState(widget.serviceExtension.extension); + _setValueFromState(state.value); unawaited( serviceConnection.serviceManager.serviceExtensionManager From 052a03deb4af1b3adedea4c6dee02ec83dd26733 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Wed, 29 Apr 2026 16:22:01 -0700 Subject: [PATCH 2/4] Add test and release notes --- .../release_notes/NEXT_RELEASE_NOTES.md | 3 +- .../service_extension_widgets_test.dart | 55 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md index 639875d1ad6..805d1ad4719 100644 --- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md +++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md @@ -24,7 +24,8 @@ TODO: Remove this section if there are not any updates. ## Performance updates -TODO: Remove this section if there are not any updates. +- Fixed an issue where 'More Debug Options' showed options as unselected in +profile mode even when selected. [TODO](https://github.com/flutter/devtools/pull/TODO) ## CPU profiler updates diff --git a/packages/devtools_app/test/service/service_extension_widgets_test.dart b/packages/devtools_app/test/service/service_extension_widgets_test.dart index e100a754e81..13df7a612e6 100644 --- a/packages/devtools_app/test/service/service_extension_widgets_test.dart +++ b/packages/devtools_app/test/service/service_extension_widgets_test.dart @@ -222,6 +222,61 @@ void main() { expect(toggle.value, false, reason: 'The extension is disabled.'); }); }); + + group('ServiceExtensionCheckbox', () { + testWidgets('shows value state even when unavailable', (WidgetTester tester) async { + final ext = extensions.disableClipLayers; + final customFake = _UnavailableServiceExtensionManager(); + customFake.makeUnavailable(ext.extension); + + // Override the serviceExtensionManager on mockServiceManager + when(mockServiceManager.serviceExtensionManager).thenReturn(customFake); + + // Set state to enabled: false (which means clips not disabled -> checked true) + await customFake.setServiceExtensionState( + ext.extension, + enabled: false, + value: false, + ); + + final checkbox = ServiceExtensionCheckbox(serviceExtension: ext); + await tester.pumpWidget( + wrap(Scaffold(body: Center(child: checkbox))), + ); + await tester.pumpAndSettle(); + + final checkboxFinder = find.byType(Checkbox); + expect(checkboxFinder, findsOneWidget); + + final checkboxWidget = tester.widget(checkboxFinder); + expect(checkboxWidget.value, isTrue); + expect(checkboxWidget.onChanged, isNull); + }); + }); +} + +base class _UnavailableServiceExtensionManager extends FakeServiceExtensionManager { + final _unavailableExtensions = {}; + + void makeUnavailable(String name) { + _unavailableExtensions.add(name); + } + + @override + Future waitForServiceExtensionAvailable(String name) { + if (_unavailableExtensions.contains(name)) { + return Future.value(false); + } + return super.waitForServiceExtensionAvailable(name); + } + + @override + bool isServiceExtensionAvailable(String name) { + if (_unavailableExtensions.contains(name)) { + return false; + } + return super.isServiceExtensionAvailable(name); + } } void registerServiceExtension( From fa78fdaa9142bf21f305f92bb3320d912f80946b Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Wed, 29 Apr 2026 16:28:09 -0700 Subject: [PATCH 3/4] add pr number --- packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md index 805d1ad4719..787e89cb3ba 100644 --- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md +++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md @@ -25,7 +25,7 @@ TODO: Remove this section if there are not any updates. ## Performance updates - Fixed an issue where 'More Debug Options' showed options as unselected in -profile mode even when selected. [TODO](https://github.com/flutter/devtools/pull/TODO) +profile mode even when selected. [#9813](https://github.com/flutter/devtools/issues/9813) ## CPU profiler updates From eeb5fe68820d07a4429d80d4e8d687b52ceff099 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Thu, 30 Apr 2026 09:16:05 -0700 Subject: [PATCH 4/4] format --- .../service_extension_widgets_test.dart | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/devtools_app/test/service/service_extension_widgets_test.dart b/packages/devtools_app/test/service/service_extension_widgets_test.dart index 13df7a612e6..109ca9a1608 100644 --- a/packages/devtools_app/test/service/service_extension_widgets_test.dart +++ b/packages/devtools_app/test/service/service_extension_widgets_test.dart @@ -224,30 +224,30 @@ void main() { }); group('ServiceExtensionCheckbox', () { - testWidgets('shows value state even when unavailable', (WidgetTester tester) async { + testWidgets('shows value state even when unavailable', ( + WidgetTester tester, + ) async { final ext = extensions.disableClipLayers; final customFake = _UnavailableServiceExtensionManager(); customFake.makeUnavailable(ext.extension); - + // Override the serviceExtensionManager on mockServiceManager when(mockServiceManager.serviceExtensionManager).thenReturn(customFake); - + // Set state to enabled: false (which means clips not disabled -> checked true) await customFake.setServiceExtensionState( ext.extension, enabled: false, value: false, ); - + final checkbox = ServiceExtensionCheckbox(serviceExtension: ext); - await tester.pumpWidget( - wrap(Scaffold(body: Center(child: checkbox))), - ); + await tester.pumpWidget(wrap(Scaffold(body: Center(child: checkbox)))); await tester.pumpAndSettle(); - + final checkboxFinder = find.byType(Checkbox); expect(checkboxFinder, findsOneWidget); - + final checkboxWidget = tester.widget(checkboxFinder); expect(checkboxWidget.value, isTrue); expect(checkboxWidget.onChanged, isNull); @@ -255,7 +255,8 @@ void main() { }); } -base class _UnavailableServiceExtensionManager extends FakeServiceExtensionManager { +base class _UnavailableServiceExtensionManager + extends FakeServiceExtensionManager { final _unavailableExtensions = {}; void makeUnavailable(String name) {