initServiceExtensions method Null safety
- RegisterServiceExtensionCallback registerServiceExtensionCallback
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 registerServiceExtensionCallback) {
final FlutterExceptionHandler defaultExceptionHandler = FlutterError.presentError;
if (isStructuredErrorsEnabled()) {
FlutterError.presentError = _reportStructuredError;
}
_registerServiceExtensionCallback = registerServiceExtensionCallback;
assert(!_debugServiceExtensionsRegistered);
assert(() {
_debugServiceExtensionsRegistered = true;
return true;
}());
SchedulerBinding.instance.addPersistentFrameCallback(_onFrameStart);
_registerBoolServiceExtension(
name: 'structuredErrors',
getter: () async => FlutterError.presentError == _reportStructuredError,
setter: (bool value) {
FlutterError.presentError = value ? _reportStructuredError : defaultExceptionHandler;
return Future<void>.value();
},
);
_registerBoolServiceExtension(
name: 'show',
getter: () async => WidgetsApp.debugShowWidgetInspectorOverride,
setter: (bool value) {
if (WidgetsApp.debugShowWidgetInspectorOverride == value) {
return Future<void>.value();
}
WidgetsApp.debugShowWidgetInspectorOverride = value;
return forceRebuild();
},
);
if (isWidgetCreationTracked()) {
// Service extensions that are only supported if widget creation locations
// are tracked.
_registerBoolServiceExtension(
name: 'trackRebuildDirtyWidgets',
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;
}
},
);
_registerBoolServiceExtension(
name: 'trackRepaintWidgets',
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);
}
final RenderObject root = RendererBinding.instance.renderView;
markTreeNeedsPaint(root);
} else {
debugOnProfilePaint = null;
}
},
);
}
_registerSignalServiceExtension(
name: 'disposeAllGroups',
callback: () async {
disposeAllGroups();
return null;
},
);
_registerObjectGroupServiceExtension(
name: 'disposeGroup',
callback: (String name) async {
disposeGroup(name);
return null;
},
);
_registerSignalServiceExtension(
name: 'isWidgetTreeReady',
callback: isWidgetTreeReady,
);
_registerServiceExtensionWithArg(
name: 'disposeId',
callback: (String? objectId, String objectGroup) async {
disposeId(objectId, objectGroup);
return null;
},
);
_registerServiceExtensionVarArgs(
name: 'setPubRootDirectories',
callback: (List<String> args) async {
setPubRootDirectories(args);
return null;
},
);
_registerServiceExtensionVarArgs(
name: 'addPubRootDirectories',
callback: (List<String> args) async {
addPubRootDirectories(args);
return null;
},
);
_registerServiceExtensionVarArgs(
name: 'removePubRootDirectories',
callback: (List<String> args) async {
removePubRootDirectories(args);
return null;
},
);
_registerServiceExtensionWithArg(
name: 'setSelectionById',
callback: setSelectionById,
);
_registerServiceExtensionWithArg(
name: 'getParentChain',
callback: _getParentChain,
);
_registerServiceExtensionWithArg(
name: 'getProperties',
callback: _getProperties,
);
_registerServiceExtensionWithArg(
name: 'getChildren',
callback: _getChildren,
);
_registerServiceExtensionWithArg(
name: 'getChildrenSummaryTree',
callback: _getChildrenSummaryTree,
);
_registerServiceExtensionWithArg(
name: 'getChildrenDetailsSubtree',
callback: _getChildrenDetailsSubtree,
);
_registerObjectGroupServiceExtension(
name: 'getRootWidget',
callback: _getRootWidget,
);
_registerObjectGroupServiceExtension(
name: 'getRootRenderObject',
callback: _getRootRenderObject,
);
_registerObjectGroupServiceExtension(
name: 'getRootWidgetSummaryTree',
callback: _getRootWidgetSummaryTree,
);
registerServiceExtension(
name: 'getDetailsSubtree',
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,
),
};
},
);
_registerServiceExtensionWithArg(
name: 'getSelectedRenderObject',
callback: _getSelectedRenderObject,
);
_registerServiceExtensionWithArg(
name: 'getSelectedWidget',
callback: _getSelectedWidget,
);
_registerServiceExtensionWithArg(
name: 'getSelectedSummaryWidget',
callback: _getSelectedSummaryWidget,
);
_registerSignalServiceExtension(
name: 'isWidgetCreationTracked',
callback: isWidgetCreationTracked,
);
registerServiceExtension(
name: 'screenshot',
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);
return <String, Object>{
'result': base64.encoder.convert(Uint8List.view(byteData!.buffer)),
};
},
);
}