initServiceExtensions method
- RegisterServiceExtensionCallback registerExtension
Called to register service extensions.
See also:
- github.com/dart-lang/sdk/blob/main/runtime/vm/service/service.md#rpcs-requests-and-responses
- BindingBase.initServiceExtensions, which explains when service extensions can be used.
Implementation
void initServiceExtensions(RegisterServiceExtensionCallback registerExtension) {
final FlutterExceptionHandler defaultExceptionHandler = FlutterError.presentError;
if (isStructuredErrorsEnabled()) {
FlutterError.presentError = _reportStructuredError;
}
assert(!_debugServiceExtensionsRegistered);
assert(() {
_debugServiceExtensionsRegistered = true;
return true;
}());
SchedulerBinding.instance.addPersistentFrameCallback(_onFrameStart);
_registerBoolServiceExtension(
name: WidgetInspectorServiceExtensions.structuredErrors.name,
getter: () async => FlutterError.presentError == _reportStructuredError,
setter: (bool value) {
FlutterError.presentError = value ? _reportStructuredError : defaultExceptionHandler;
return Future<void>.value();
},
registerExtension: registerExtension,
);
_registerBoolServiceExtension(
name: WidgetInspectorServiceExtensions.show.name,
getter: () async => WidgetsBinding.instance.debugShowWidgetInspectorOverride,
setter: (bool value) {
if (WidgetsBinding.instance.debugShowWidgetInspectorOverride != value) {
WidgetsBinding.instance.debugShowWidgetInspectorOverride = value;
}
return Future<void>.value();
},
registerExtension: registerExtension,
);
if (isWidgetCreationTracked()) {
// Service extensions that are only supported if widget creation locations
// are tracked.
_registerBoolServiceExtension(
name: WidgetInspectorServiceExtensions.trackRebuildDirtyWidgets.name,
getter: () async => _trackRebuildDirtyWidgets,
setter: (bool value) async {
if (value == _trackRebuildDirtyWidgets) {
return;
}
_rebuildStats.resetCounts();
_trackRebuildDirtyWidgets = value;
if (value) {
assert(debugOnRebuildDirtyWidget == null);
debugOnRebuildDirtyWidget = _onRebuildWidget;
// Trigger a rebuild so there are baseline stats for rebuilds
// performed by the app.
await forceRebuild();
return;
} else {
debugOnRebuildDirtyWidget = null;
return;
}
},
registerExtension: registerExtension,
);
_registerSignalServiceExtension(
name: WidgetInspectorServiceExtensions.widgetLocationIdMap.name,
callback: () {
return _locationIdMapToJson();
},
registerExtension: registerExtension,
);
_registerBoolServiceExtension(
name: WidgetInspectorServiceExtensions.trackRepaintWidgets.name,
getter: () async => _trackRepaintWidgets,
setter: (bool value) async {
if (value == _trackRepaintWidgets) {
return;
}
_repaintStats.resetCounts();
_trackRepaintWidgets = value;
if (value) {
assert(debugOnProfilePaint == null);
debugOnProfilePaint = _onPaint;
// Trigger an immediate paint so the user has some baseline painting
// stats to view.
void markTreeNeedsPaint(RenderObject renderObject) {
renderObject.markNeedsPaint();
renderObject.visitChildren(markTreeNeedsPaint);
}
RendererBinding.instance.renderViews.forEach(markTreeNeedsPaint);
} else {
debugOnProfilePaint = null;
}
},
registerExtension: registerExtension,
);
}
_registerSignalServiceExtension(
name: WidgetInspectorServiceExtensions.disposeAllGroups.name,
callback: () async {
disposeAllGroups();
return null;
},
registerExtension: registerExtension,
);
_registerObjectGroupServiceExtension(
name: WidgetInspectorServiceExtensions.disposeGroup.name,
callback: (String name) async {
disposeGroup(name);
return null;
},
registerExtension: registerExtension,
);
_registerSignalServiceExtension(
name: WidgetInspectorServiceExtensions.isWidgetTreeReady.name,
callback: isWidgetTreeReady,
registerExtension: registerExtension,
);
_registerServiceExtensionWithArg(
name: WidgetInspectorServiceExtensions.disposeId.name,
callback: (String? objectId, String objectGroup) async {
disposeId(objectId, objectGroup);
return null;
},
registerExtension: registerExtension,
);
_registerServiceExtensionVarArgs(
name: WidgetInspectorServiceExtensions.setPubRootDirectories.name,
callback: (List<String> args) async {
setPubRootDirectories(args);
return null;
},
registerExtension: registerExtension,
);
_registerServiceExtensionVarArgs(
name: WidgetInspectorServiceExtensions.addPubRootDirectories.name,
callback: (List<String> args) async {
addPubRootDirectories(args);
return null;
},
registerExtension: registerExtension,
);
_registerServiceExtensionVarArgs(
name: WidgetInspectorServiceExtensions.removePubRootDirectories.name,
callback: (List<String> args) async {
removePubRootDirectories(args);
return null;
},
registerExtension: registerExtension,
);
registerServiceExtension(
name: WidgetInspectorServiceExtensions.getPubRootDirectories.name,
callback: pubRootDirectories,
registerExtension: registerExtension,
);
_registerServiceExtensionWithArg(
name: WidgetInspectorServiceExtensions.setSelectionById.name,
callback: setSelectionById,
registerExtension: registerExtension,
);
_registerServiceExtensionWithArg(
name: WidgetInspectorServiceExtensions.getParentChain.name,
callback: _getParentChain,
registerExtension: registerExtension,
);
_registerServiceExtensionWithArg(
name: WidgetInspectorServiceExtensions.getProperties.name,
callback: _getProperties,
registerExtension: registerExtension,
);
_registerServiceExtensionWithArg(
name: WidgetInspectorServiceExtensions.getChildren.name,
callback: _getChildren,
registerExtension: registerExtension,
);
_registerServiceExtensionWithArg(
name: WidgetInspectorServiceExtensions.getChildrenSummaryTree.name,
callback: _getChildrenSummaryTree,
registerExtension: registerExtension,
);
_registerServiceExtensionWithArg(
name: WidgetInspectorServiceExtensions.getChildrenDetailsSubtree.name,
callback: _getChildrenDetailsSubtree,
registerExtension: registerExtension,
);
_registerObjectGroupServiceExtension(
name: WidgetInspectorServiceExtensions.getRootWidget.name,
callback: _getRootWidget,
registerExtension: registerExtension,
);
_registerObjectGroupServiceExtension(
name: WidgetInspectorServiceExtensions.getRootWidgetSummaryTree.name,
callback: _getRootWidgetSummaryTree,
registerExtension: registerExtension,
);
registerServiceExtension(
name: WidgetInspectorServiceExtensions.getRootWidgetSummaryTreeWithPreviews.name,
callback: _getRootWidgetSummaryTreeWithPreviews,
registerExtension: registerExtension,
);
registerServiceExtension(
name: WidgetInspectorServiceExtensions.getRootWidgetTree.name,
callback: _getRootWidgetTree,
registerExtension: registerExtension,
);
registerServiceExtension(
name: WidgetInspectorServiceExtensions.getDetailsSubtree.name,
callback: (Map<String, String> parameters) async {
assert(parameters.containsKey('objectGroup'));
final String? subtreeDepth = parameters['subtreeDepth'];
return <String, Object?>{
'result': _getDetailsSubtree(
parameters['arg'],
parameters['objectGroup'],
subtreeDepth != null ? int.parse(subtreeDepth) : 2,
),
};
},
registerExtension: registerExtension,
);
_registerServiceExtensionWithArg(
name: WidgetInspectorServiceExtensions.getSelectedWidget.name,
callback: _getSelectedWidget,
registerExtension: registerExtension,
);
_registerServiceExtensionWithArg(
name: WidgetInspectorServiceExtensions.getSelectedSummaryWidget.name,
callback: _getSelectedSummaryWidget,
registerExtension: registerExtension,
);
_registerSignalServiceExtension(
name: WidgetInspectorServiceExtensions.isWidgetCreationTracked.name,
callback: isWidgetCreationTracked,
registerExtension: registerExtension,
);
registerServiceExtension(
name: WidgetInspectorServiceExtensions.screenshot.name,
callback: (Map<String, String> parameters) async {
assert(parameters.containsKey('id'));
assert(parameters.containsKey('width'));
assert(parameters.containsKey('height'));
final ui.Image? image = await screenshot(
toObject(parameters['id']),
width: double.parse(parameters['width']!),
height: double.parse(parameters['height']!),
margin: parameters.containsKey('margin') ?
double.parse(parameters['margin']!) : 0.0,
maxPixelRatio: parameters.containsKey('maxPixelRatio') ?
double.parse(parameters['maxPixelRatio']!) : 1.0,
debugPaint: parameters['debugPaint'] == 'true',
);
if (image == null) {
return <String, Object?>{'result': null};
}
final ByteData? byteData = await image.toByteData(format:ui.ImageByteFormat.png);
image.dispose();
return <String, Object>{
'result': base64.encoder.convert(Uint8List.view(byteData!.buffer)),
};
},
registerExtension: registerExtension,
);
registerServiceExtension(
name: WidgetInspectorServiceExtensions.getLayoutExplorerNode.name,
callback: _getLayoutExplorerNode,
registerExtension: registerExtension,
);
registerServiceExtension(
name: WidgetInspectorServiceExtensions.setFlexFit.name,
callback: _setFlexFit,
registerExtension: registerExtension,
);
registerServiceExtension(
name: WidgetInspectorServiceExtensions.setFlexFactor.name,
callback: _setFlexFactor,
registerExtension: registerExtension,
);
registerServiceExtension(
name: WidgetInspectorServiceExtensions.setFlexProperties.name,
callback: _setFlexProperties,
registerExtension: registerExtension,
);
}