| // Copyright 2023 The Flutter Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. |
| |
| import 'dart:async'; |
| |
| import 'package:devtools_app_shared/utils.dart'; |
| import 'package:flutter/material.dart'; |
| import 'package:flutter_web_plugins/url_strategy.dart'; |
| |
| import 'src/app.dart'; |
| import 'src/framework/framework_core.dart'; |
| import 'src/screens/debugger/syntax_highlighter.dart'; |
| import 'src/shared/analytics/analytics_controller.dart'; |
| import 'src/shared/config_specific/logger/logger_helpers.dart'; |
| import 'src/shared/feature_flags.dart'; |
| import 'src/shared/framework/app_error_handling.dart'; |
| import 'src/shared/globals.dart'; |
| import 'src/shared/primitives/url_utils.dart'; |
| import 'src/shared/primitives/utils.dart'; |
| |
| /// Handles necessary initialization then runs DevTools. |
| /// |
| /// Any initialization that needs to happen before running DevTools, regardless |
| /// of context, should happen here. |
| /// |
| /// If any initialization is specific to running Devtools in google3 or |
| /// externally, then it should be added to that respective main.dart file. |
| /// Alternatively, the [onDevToolsInitialized] callback can be used to perform |
| /// additional logic that runs after DevTools initialization but before running |
| /// the app. |
| void runDevTools({ |
| bool integrationTestMode = false, |
| bool shouldEnableExperiments = false, |
| List<DevToolsJsonFile> sampleData = const [], |
| List<DevToolsScreen>? screens, |
| Future<void> Function()? onDevToolsInitialized, |
| }) { |
| setupErrorHandling(() async { |
| await initializeDevTools( |
| integrationTestMode: integrationTestMode, |
| shouldEnableExperiments: shouldEnableExperiments, |
| ); |
| |
| // Load the Dart syntax highlighting grammar. |
| await SyntaxHighlighter.initialize(); |
| |
| await onDevToolsInitialized?.call(); |
| |
| // Run the app. |
| runApp( |
| DevToolsApp( |
| screens ?? defaultScreens(sampleData: sampleData), |
| await analyticsController, |
| ), |
| ); |
| }); |
| } |
| |
| @visibleForTesting |
| Future<void> initializeDevTools({ |
| bool integrationTestMode = false, |
| bool shouldEnableExperiments = false, |
| }) async { |
| initDevToolsLogging(); |
| |
| // Before switching to URL path strategy, check if this URL is in the legacy |
| // fragment format and redirect if necessary. |
| if (_handleLegacyUrl()) return; |
| |
| usePathUrlStrategy(); |
| |
| _maybeInitForIntegrationTestMode( |
| integrationTestMode: integrationTestMode, |
| enableExperiments: shouldEnableExperiments, |
| ); |
| |
| await FrameworkCore.init(); |
| } |
| |
| /// Initializes some DevTools global fields for our Flutter integration tests. |
| /// |
| /// Since we call [runDevTools] from Dart code, we cannot set environment |
| /// variables before calling [runDevTools], and therefore have to pass in these |
| /// values manually to [runDevTools]. |
| void _maybeInitForIntegrationTestMode({ |
| required bool integrationTestMode, |
| required bool enableExperiments, |
| }) { |
| if (!integrationTestMode) return; |
| |
| setIntegrationTestMode(); |
| if (enableExperiments) { |
| setEnableExperiments(); |
| } |
| } |
| |
| /// Checks if the request is for a legacy URL and if so, redirects to the new |
| /// equivalent. |
| /// |
| /// Returns `true` if a redirect was performed, in which case normal app |
| /// initialization should be skipped. |
| bool _handleLegacyUrl() { |
| final url = getWebUrl(); |
| if (url == null) return false; |
| |
| final newUrl = mapLegacyUrl(url); |
| if (newUrl != null) { |
| webRedirect(newUrl); |
| return true; |
| } |
| |
| return false; |
| } |