blob: 7f984ead4734191417b39900aa1cb2093442fce7 [file] [log] [blame]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert';
import 'dart:developer';
import '../shared/_primitives.dart';
import '../shared/_util.dart';
import '../shared/shared_model.dart';
import 'delivery.dart';
import 'messages.dart';
import 'primitives.dart';
bool _extentsionRegistered = false;
/// Registers service extension to signal that leak tracking is
/// already enabled and other leak tracking systems
/// (for example, the one built into Flutter framework)
/// should not be activated.
///
/// If the extension is already registered, returns false.
bool registerLeakTrackingServiceExtension() => _registerServiceExtension(
(p0, p1) async => ServiceExtensionResponse.result(jsonEncode({})),
);
/// Registers service extension for DevTools integration.
///
/// If the extension is already registered, returns false.
bool setupDevToolsIntegration(
ObjectRef<LeakProvider?> leakProvider,
) {
Future<ServiceExtensionResponse> handler(
String method,
Map<String, String> parameters,
) async {
try {
assert(method == memoryLeakTrackingExtensionName);
final theLeakProvider = leakProvider.value;
if (theLeakProvider == null) {
return ResponseFromApp(LeakTrackingTurnedOffError())
.toServiceResponse();
}
final request = RequestToApp.fromRequestParameters(parameters).message;
if (request is RequestForLeakDetails) {
return ResponseFromApp(theLeakProvider.collectLeaks())
.toServiceResponse();
}
return ResponseFromApp(
UnexpectedRequestTypeError(request.runtimeType),
).toServiceResponse();
} catch (error, stack) {
printToConsole(
'Error handling leak tracking request from DevTools to application.',
);
printToConsole(error);
printToConsole(stack);
return ResponseFromApp(UnexpectedError(error, stack)).toServiceResponse();
}
}
final result = _registerServiceExtension(handler);
EventFromApp(LeakTrackingStarted(appLeakTrackerProtocolVersion)).post();
return result;
}
bool _registerServiceExtension(
Future<ServiceExtensionResponse> Function(String, Map<String, String>)
handler,
) {
if (_extentsionRegistered) return false;
try {
registerExtension(
memoryLeakTrackingExtensionName,
handler,
);
_extentsionRegistered = true;
return true;
} on ArgumentError catch (ex) {
// Return false if extension is already registered.
final bool isAlreadyRegisteredError = ex.toString().contains('registered');
if (isAlreadyRegisteredError) {
return false;
} else {
rethrow;
}
}
}