Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ class EmbeddedExtensionControllerImpl extends EmbeddedExtensionController
}

final basePath = devtoolsAssetsBasePath(
origin: window.location.origin,
// This needs to use the DevTools server URI as the origin because the
// extension assets are served through a DevTools server handler. The
// DevTools server handler loads them directly from their location in the
// user's pub-cache.
origin: devToolsServerUriAsString,
path: window.location.pathname,
);
final baseUri = path.join(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,8 @@ void cancelTimingOperation(String screenName, String timedOperation) {
final operation = _timedOperationsInProgress.remove(operationKey);
assert(
operation != null,
'The operation cannot be cancelled because it does not exist.',
'The operation $screenName.$timedOperation cannot be cancelled because it '
'does not exist.',
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ Future<String> initializePlatform() async {
// Here, we try and initialize the connection between the DevTools web app and
// its local server. DevTools can be launched without the server however, so
// establishing this connection is a best-effort.
// TODO(kenz): investigate it we can remove the DevToolsServerConnection
// code in general. We do not appear to be using the SSE connection.
final connection = await DevToolsServerConnection.connect();
if (connection != null) {
setGlobal(Storage, ServerConnectionStorage());
setGlobal(Storage, server.ServerConnectionStorage());
} else {
setGlobal(Storage, BrowserStorage());
}
Expand Down Expand Up @@ -93,19 +95,6 @@ void _sendKeyPressToParent(KeyboardEvent event) {
);
}

class ServerConnectionStorage implements Storage {
@override
Future<String?> getValue(String key) async {
final value = await server.getPreferenceValue(key);
return value == null ? null : '$value';
}

@override
Future<void> setValue(String key, String value) async {
await server.setPreferenceValue(key, value);
}
}

class BrowserStorage implements Storage {
@override
Future<String?> getValue(String key) async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import '../utils/utils.dart';
part '_cpu_profiler_preferences.dart';
part '_extension_preferences.dart';
part '_inspector_preferences.dart';
part '_memory_preferences.dart';
part '_logging_preferences.dart';
part '_memory_preferences.dart';
part '_network_preferences.dart';
part '_performance_preferences.dart';

Expand Down Expand Up @@ -211,8 +211,17 @@ class PreferencesController extends DisposableController
return;
}

// Whether DevTools was run using the `dt serve --run-app` command, which
// runs DevTools in debug mode using `flutter run` and connects it to an
// instance of the DevTools server.
final usingDebugDevToolsServer =
(const String.fromEnvironment('debug_devtools_server')).isNotEmpty &&
!kReleaseMode;
final shouldEnableWasm =
(enabledFromStorage || enabledFromQueryParams) && kIsWeb;
(enabledFromStorage || enabledFromQueryParams) &&
kIsWeb &&
// Wasm cannot be enabled if DevTools was built using `flutter run`.
!usingDebugDevToolsServer;
assert(kIsWasm == shouldEnableWasm);
// This should be a no-op if the flutter_bootstrap.js logic set the
// renderer properly, but we call this to be safe in case something went
Expand Down
53 changes: 46 additions & 7 deletions packages/devtools_app/lib/src/shared/server/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,49 @@ import 'package:devtools_shared/devtools_shared.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;

import '../development_helpers.dart';
import '../globals.dart';
import '../primitives/storage.dart';
import '../primitives/utils.dart';

part '_analytics_api.dart';
part '_app_size_api.dart';
part '_deep_links_api.dart';
part '_dtd_api.dart';
part '_extensions_api.dart';
part '_preferences_api.dart';
part '_release_notes_api.dart';
part '_survey_api.dart';
part '_dtd_api.dart';

final _log = Logger('devtools_server_client');

// The DevTools server is only available in release mode right now.
// TODO(kenz): design a way to run the DevTools server and DevTools app together
// in debug mode.
bool get isDevToolsServerAvailable => kReleaseMode;
/// Whether the DevTools server is available.
///
/// Since the DevTools server is a web server, it is only available for the
/// web platform.
///
/// In `framework_initialize_web.dart`, we test the DevTools server connection
/// by pinging the server and checking the response. If this is successful, we
/// set the [storage] global to an instance of [ServerConnectionStorage].
bool get isDevToolsServerAvailable =>
kIsWeb && storage is ServerConnectionStorage;

const _debugDevToolsServerFlag = 'debug_devtools_server';

String get devToolsServerUriAsString {
const debugDevToolsServerUriAsString = String.fromEnvironment(
_debugDevToolsServerFlag,
);
// Ensure we only use the debug DevTools server URI in non-release
// builds. By running `dt serve --run-app`, an instance of DevTools ran
// with `flutter run` can be connected to the DevTools server on a
// different port.
return debugDevToolsServerUriAsString.isNotEmpty && !kReleaseMode
? debugDevToolsServerUriAsString
: Uri.base.toString();
}

/// Helper to catch any server request which could fail.
///
Expand All @@ -38,8 +62,10 @@ Future<Response?> request(String url) async {
Response? response;

try {
_log.fine('requesting $url');
response = await post(Uri.parse(url));
// This will be the empty string if this environment declaration was not
// set using `--dart-define`.
const baseUri = String.fromEnvironment(_debugDevToolsServerFlag);
response = await post(Uri.parse(path.join(baseUri, url)));
} catch (_) {}

return response;
Expand Down Expand Up @@ -107,3 +133,16 @@ extension ResponseExtension on Response {
bool get statusForbidden => statusCode == 403;
bool get statusError => statusCode == 500;
}

class ServerConnectionStorage implements Storage {
@override
Future<String?> getValue(String key) async {
final value = await getPreferenceValue(key);
return value == null ? null : '$value';
}

@override
Future<void> setValue(String key, String value) async {
await setPreferenceValue(key, value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'package:logging/logging.dart';
import '../config_specific/notifications/notifications.dart';
import '../framework/framework_controller.dart';
import '../globals.dart';
import 'server.dart';

final _log = Logger('lib/src/shared/server_api_client');

Expand Down Expand Up @@ -46,7 +47,8 @@ class DevToolsServerConnection {
: baseUri.resolve('api/');

static Future<DevToolsServerConnection?> connect() async {
final apiUri = apiUriFor(Uri.base);
final serverUri = Uri.parse(devToolsServerUriAsString);
final apiUri = apiUriFor(serverUri);
final pingUri = apiUri.resolve('ping');

try {
Expand Down
4 changes: 4 additions & 0 deletions packages/devtools_app/web/flutter_bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ const wasmQueryParameterKey = 'wasm';

// Calls the DevTools server API to read the user's wasm preference.
async function getDevToolsWasmPreference() {
// Note: when the DevTools server is running on a different port than the
// DevTools web app, this request path will be incorrect and the request
// will fail. This is okay because DevTools cannot be built with WASM when
// running from `flutter run` anyway.
const request = 'api/getPreferenceValue?key=experiment.wasm';
try {
const response = await fetch(request);
Expand Down
Loading
Loading