Add --unrestricted to DTD command.
NOTE: the tests view better if you turn off whitespaces on the diff.
This command will start a DTD instance that has the FileSystem service restrictions disabled. Which can be used in development environments.
Bug: https://github.com/dart-lang/sdk/issues/54762
Change-Id: I829f83d7c7afc7dd83732fc8a600cb41ffe36f63
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352921
Reviewed-by: Kenzie Davisson <kenzieschmoll@google.com>
Commit-Queue: Dan Chevalier <danchevalier@google.com>
diff --git a/pkg/dtd/test/file_system_service_test.dart b/pkg/dtd/test/file_system_service_test.dart
index b3a9c83..500c340 100644
--- a/pkg/dtd/test/file_system_service_test.dart
+++ b/pkg/dtd/test/file_system_service_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
+import 'dart:math';
import 'package:dtd/dtd.dart';
import 'package:json_rpc_2/json_rpc_2.dart';
@@ -29,17 +30,7 @@
late DTDConnection client;
late String dtdSecret;
late Uri dtdUri;
-
setUp(() async {
- toolingDaemonProcess = ToolingDaemonTestProcess();
- await toolingDaemonProcess.start();
- dtdUri = toolingDaemonProcess.uri;
- dtdSecret = toolingDaemonProcess.trustedSecret;
-
- client = await DartToolingDaemon.connect(
- dtdUri,
- );
-
tmpDirectory = await Directory.systemTemp.createTemp();
// Setup foo dir
@@ -89,296 +80,321 @@
toolingDaemonProcess.kill();
});
- group('FileSystem', () {
- group('setIDEWorkspaceRoots', () {
- test('wrong secret is unauthorized', () {
- expect(
- () => client.setIDEWorkspaceRoots('abc123', [Uri.directory('/')]),
- throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
- );
- expect(
- () => client.readFileAsString(
- aFile.uri,
- ),
- throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
- );
- });
+ group('restricted', () {
+ setUp(() async {
+ toolingDaemonProcess = ToolingDaemonTestProcess(unrestricted: false);
+ await toolingDaemonProcess.start();
+ dtdUri = toolingDaemonProcess.uri;
+ dtdSecret = toolingDaemonProcess.trustedSecret!;
- test('root must have file scheme', () {
- expect(
- () => client.setIDEWorkspaceRoots(
- dtdSecret,
- [Uri.parse('/some/path/')],
- ),
- throwsAnRpcError(RpcErrorCodes.kExpectsUriParamWithFileScheme),
- );
- });
-
- test('no IDE workspace roots', () {
- final file = File(p.join(fooDirectory.path, 'newfile.txt'));
- expect(
- () => client.listDirectoryContents(fooDirectory.uri),
- throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
- );
- expect(
- () => client.readFileAsString(
- file.uri,
- ),
- throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
- );
- expect(
- () => client.writeFileAsString(
- file.uri,
- 'this should not be written',
- ),
- throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
- );
- expect(file.existsSync(), false);
- });
-
- test('one IDE workspace root', () async {
- await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
-
- final fileContents = 'New file contents';
- final listResult = await client.listDirectoryContents(
- fooDirectory.uri,
- );
- expect(
- listResult.uris,
- containsAll(fooDirContents),
- );
-
- await client.writeFileAsString(aFile.uri, fileContents);
-
- final readResult = await client.readFileAsString(
- aFile.uri,
- );
- expect(readResult.content, fileContents);
- });
-
- test('multiple IDE workspace roots', () async {
- await client.setIDEWorkspaceRoots(dtdSecret, [
- fooDirectory.uri,
- barDirectory.uri,
- ]);
-
- // Operate in foo
- final newAFileContents = 'New afile contents';
- final fooListResult = await client.listDirectoryContents(
- fooDirectory.uri,
- );
- expect(
- fooListResult.uris,
- containsAll(fooDirContents),
- );
-
- await client.writeFileAsString(aFile.uri, newAFileContents);
-
- final readResult = await client.readFileAsString(
- aFile.uri,
- );
- expect(readResult.content, newAFileContents);
-
- // Operate in bar
- final newEFileContents = 'New efile contents';
- final barListResult = await client.listDirectoryContents(
- fooDirectory.uri,
- );
- expect(
- barListResult.uris,
- containsAll(fooDirContents),
- );
-
- await client.writeFileAsString(aFile.uri, newEFileContents);
-
- final eReadResult = await client.readFileAsString(
- aFile.uri,
- );
- expect(eReadResult.content, newEFileContents);
- });
-
- test('remove an IDE workspace root', () async {
- await client.setIDEWorkspaceRoots(dtdSecret, [
- fooDirectory.uri,
- barDirectory.uri,
- ]);
- await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
-
- final fileContents = 'New file contents';
- final listResult = await client.listDirectoryContents(
- fooDirectory.uri,
- );
- expect(
- listResult.uris,
- containsAll(fooDirContents),
- );
-
- await client.writeFileAsString(aFile.uri, fileContents);
-
- final readResult = await client.readFileAsString(
- aFile.uri,
- );
- expect(readResult.content, fileContents);
-
- expect(
- () => client.listDirectoryContents(barDirectory.uri),
- throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
- );
- expect(
- () => client.readFileAsString(eFile.uri),
- throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
- );
- expect(
- () => client.writeFileAsString(eFile.uri, fileContents),
- throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
- );
- });
+ client = await DartToolingDaemon.connect(dtdUri);
});
- group('getIDEWorkspaceRoots', () {
- test('empty IDE workspace roots', () async {
- final roots = await client.getIDEWorkspaceRoots();
- expect(roots.ideWorkspaceRoots, isEmpty);
- });
+ group('FileSystem', () {
+ group('setIDEWorkspaceRoots', () {
+ test('wrong secret is unauthorized', () {
+ expect(
+ () => client.setIDEWorkspaceRoots('abc123', [Uri.directory('/')]),
+ throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
+ );
+ expect(
+ () => client.readFileAsString(aFile.uri),
+ throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
+ );
+ });
- test('multiple IDE workspace roots', () async {
- await client.setIDEWorkspaceRoots(dtdSecret, [
- fooDirectory.uri,
- barDirectory.uri,
- ]);
- final roots = await client.getIDEWorkspaceRoots();
- expect(
- roots.ideWorkspaceRoots,
- containsAll([
+ test('root must have file scheme', () {
+ expect(
+ () => client
+ .setIDEWorkspaceRoots(dtdSecret, [Uri.parse('/some/path/')]),
+ throwsAnRpcError(RpcErrorCodes.kExpectsUriParamWithFileScheme),
+ );
+ });
+
+ test('no IDE workspace roots', () {
+ final file = File(p.join(fooDirectory.path, 'newfile.txt'));
+ expect(
+ () => client.listDirectoryContents(fooDirectory.uri),
+ throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
+ );
+ expect(
+ () => client.readFileAsString(
+ file.uri,
+ ),
+ throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
+ );
+ expect(
+ () => client.writeFileAsString(
+ file.uri,
+ 'this should not be written',
+ ),
+ throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
+ );
+ expect(file.existsSync(), false);
+ });
+
+ test('one IDE workspace root', () async {
+ await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
+
+ final fileContents = 'New file contents';
+ final listResult = await client.listDirectoryContents(
+ fooDirectory.uri,
+ );
+ expect(listResult.uris, containsAll(fooDirContents));
+
+ await client.writeFileAsString(aFile.uri, fileContents);
+
+ final readResult = await client.readFileAsString(aFile.uri);
+ expect(readResult.content, fileContents);
+ });
+
+ test('multiple IDE workspace roots', () async {
+ await client.setIDEWorkspaceRoots(dtdSecret, [
fooDirectory.uri,
barDirectory.uri,
- ]),
- );
+ ]);
+
+ // Operate in foo
+ final newAFileContents = 'New afile contents';
+ final fooListResult = await client.listDirectoryContents(
+ fooDirectory.uri,
+ );
+ expect(fooListResult.uris, containsAll(fooDirContents));
+
+ await client.writeFileAsString(aFile.uri, newAFileContents);
+
+ final readResult = await client.readFileAsString(aFile.uri);
+ expect(readResult.content, newAFileContents);
+
+ // Operate in bar
+ final newEFileContents = 'New efile contents';
+ final barListResult = await client.listDirectoryContents(
+ fooDirectory.uri,
+ );
+ expect(barListResult.uris, containsAll(fooDirContents));
+
+ await client.writeFileAsString(aFile.uri, newEFileContents);
+
+ final eReadResult = await client.readFileAsString(aFile.uri);
+ expect(eReadResult.content, newEFileContents);
+ });
+
+ test('remove an IDE workspace root', () async {
+ await client.setIDEWorkspaceRoots(dtdSecret, [
+ fooDirectory.uri,
+ barDirectory.uri,
+ ]);
+ await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
+
+ final fileContents = 'New file contents';
+ final listResult = await client.listDirectoryContents(
+ fooDirectory.uri,
+ );
+ expect(
+ listResult.uris,
+ containsAll(fooDirContents),
+ );
+
+ await client.writeFileAsString(aFile.uri, fileContents);
+
+ final readResult = await client.readFileAsString(aFile.uri);
+ expect(readResult.content, fileContents);
+
+ expect(
+ () => client.listDirectoryContents(barDirectory.uri),
+ throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
+ );
+ expect(
+ () => client.readFileAsString(eFile.uri),
+ throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
+ );
+ expect(
+ () => client.writeFileAsString(eFile.uri, fileContents),
+ throwsAnRpcError(RpcErrorCodes.kPermissionDenied),
+ );
+ });
+ });
+
+ group('getIDEWorkspaceRoots', () {
+ test('empty IDE workspace roots', () async {
+ final roots = await client.getIDEWorkspaceRoots();
+ expect(roots.ideWorkspaceRoots, isEmpty);
+ });
+
+ test('multiple IDE workspace roots', () async {
+ await client.setIDEWorkspaceRoots(dtdSecret, [
+ fooDirectory.uri,
+ barDirectory.uri,
+ ]);
+ final roots = await client.getIDEWorkspaceRoots();
+ expect(
+ roots.ideWorkspaceRoots,
+ containsAll([fooDirectory.uri, barDirectory.uri]),
+ );
+ });
+ });
+
+ group('listDirectoryContents', () {
+ test('listing a file should fail', () async {
+ await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
+ expect(
+ () => client.listDirectoryContents(aFile.uri),
+ throwsAnRpcError(RpcErrorCodes.kDirectoryDoesNotExist),
+ );
+ });
+
+ test('non-existent directory should fail', () async {
+ await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
+ expect(
+ () => client.listDirectoryContents(
+ Uri.directory(p.join(fooDirectory.path, 'A')),
+ ),
+ throwsAnRpcError(RpcErrorCodes.kDirectoryDoesNotExist),
+ );
+ });
+
+ test('should work for an empty directory', () async {
+ await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
+ final emptyFooDir = Directory(p.join(fooDirectory.path, 'emptyDir'));
+ emptyFooDir.createSync();
+
+ final listResult =
+ await client.listDirectoryContents(emptyFooDir.uri);
+ expect(listResult.uris, isEmpty);
+ });
+
+ test('must have a file scheme', () {
+ expect(
+ () => client.listDirectoryContents(
+ Uri.parse('/some/path/'),
+ ),
+ throwsAnRpcError(RpcErrorCodes.kExpectsUriParamWithFileScheme),
+ );
+ });
+ });
+
+ group('readFileAsString', () {
+ test('fails on a non-existent file', () async {
+ await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
+ expect(
+ () => client.readFileAsString(
+ File(p.join(fooDirectory.path, 'nonExistentFile.txt')).uri,
+ ),
+ throwsAnRpcError(RpcErrorCodes.kFileDoesNotExist),
+ );
+ });
+
+ test('must have a file scheme', () {
+ expect(
+ () => client.readFileAsString(Uri.parse('/some/path/')),
+ throwsAnRpcError(RpcErrorCodes.kExpectsUriParamWithFileScheme),
+ );
+ });
+ });
+
+ group('writeFileAsString', () {
+ final newFileContents = 'Some new file contents';
+
+ test('can overwrite an existing file', () async {
+ await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
+
+ expect(aFile.readAsStringSync(), aFileContents);
+
+ await client.writeFileAsString(aFile.uri, newFileContents);
+
+ expect(aFile.readAsStringSync(), newFileContents);
+ });
+
+ test('creates the file if it does not exist', () async {
+ final nonExistentFile = File(
+ p.join(fooDirectory.path, 'nonExistentFile.txt'),
+ );
+ await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
+ expect(nonExistentFile.existsSync(), false);
+ await client.writeFileAsString(nonExistentFile.uri, newFileContents);
+ expect(nonExistentFile.existsSync(), true);
+ expect(nonExistentFile.readAsStringSync(), newFileContents);
+ });
+
+ test('creates sub directories if they don\'t exist', () async {
+ final fileInNonExistentDirectory = File(
+ p.join(
+ fooDirectory.path,
+ 'a',
+ 'b',
+ 'c',
+ 'nonExistentFile.txt',
+ ),
+ );
+ await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
+ expect(fileInNonExistentDirectory.existsSync(), false);
+ await client.writeFileAsString(
+ fileInNonExistentDirectory.uri,
+ newFileContents,
+ );
+ expect(fileInNonExistentDirectory.existsSync(), true);
+ expect(
+ fileInNonExistentDirectory.readAsStringSync(),
+ newFileContents,
+ );
+ });
+
+ test('must have a file scheme', () {
+ expect(
+ () => client.writeFileAsString(
+ Uri.parse('/some/path/'),
+ 'some contents',
+ ),
+ throwsAnRpcError(RpcErrorCodes.kExpectsUriParamWithFileScheme),
+ );
+ });
});
});
+ });
- group('listDirectoryContents', () {
- test('listing a file should fail', () async {
- await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
- expect(
- () => client.listDirectoryContents(aFile.uri),
- throwsAnRpcError(RpcErrorCodes.kDirectoryDoesNotExist),
- );
- });
+ group('unrestricted', () {
+ setUp(() async {
+ toolingDaemonProcess = ToolingDaemonTestProcess(unrestricted: true);
+ await toolingDaemonProcess.start();
+ dtdUri = toolingDaemonProcess.uri;
- test('non-existent directory should fail', () async {
- await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
- expect(
- () => client.listDirectoryContents(
- Uri.directory(p.join(fooDirectory.path, 'A')),
- ),
- throwsAnRpcError(RpcErrorCodes.kDirectoryDoesNotExist),
- );
- });
-
- test('should work for an empty directory', () async {
- await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
- final emptyFooDir = Directory(p.join(fooDirectory.path, 'emptyDir'));
- emptyFooDir.createSync();
-
- final listResult = await client.listDirectoryContents(emptyFooDir.uri);
- expect(listResult.uris, isEmpty);
- });
-
- test('must have a file scheme', () {
- expect(
- () => client.listDirectoryContents(
- Uri.parse('/some/path/'),
- ),
- throwsAnRpcError(RpcErrorCodes.kExpectsUriParamWithFileScheme),
- );
- });
+ client = await DartToolingDaemon.connect(dtdUri);
});
- group('readFileAsString', () {
- test('fails on a non-existent file', () async {
- await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
- expect(
- () => client.readFileAsString(
- File(p.join(fooDirectory.path, 'nonExistentFile.txt')).uri,
- ),
- throwsAnRpcError(RpcErrorCodes.kFileDoesNotExist),
- );
- });
+ test('works when no roots set', () async {
+ final fileContents = 'New file contents';
- test('must have a file scheme', () {
- expect(
- () => client.readFileAsString(
- Uri.parse('/some/path/'),
- ),
- throwsAnRpcError(RpcErrorCodes.kExpectsUriParamWithFileScheme),
- );
- });
+ expect((await client.getIDEWorkspaceRoots()).ideWorkspaceRoots, isEmpty);
+
+ final listResult = await client.listDirectoryContents(fooDirectory.uri);
+ expect(listResult.uris, containsAll(fooDirContents));
+
+ await client.writeFileAsString(aFile.uri, fileContents);
+
+ final readResult = await client.readFileAsString(aFile.uri);
+ expect(readResult.content, fileContents);
});
- group('writeFileAsString', () {
- final newFileContents = 'Some new file contents';
-
- test('can overwrite an existing file', () async {
- await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
-
- expect(aFile.readAsStringSync(), aFileContents);
-
- await client.writeFileAsString(
- aFile.uri,
- newFileContents,
+ test(
+ 'works when ide workspace roots set to a different directory',
+ () async {
+ await client.setIDEWorkspaceRoots(
+ Random().nextInt(10000).toString(),
+ [barDirectory.uri],
);
+ final fileContents = 'New file contents';
+ final listResult = await client.listDirectoryContents(fooDirectory.uri);
+ expect(listResult.uris, containsAll(fooDirContents));
- expect(aFile.readAsStringSync(), newFileContents);
- });
+ await client.writeFileAsString(aFile.uri, fileContents);
- test('creates the file if it does not exist', () async {
- final nonExistentFile = File(
- p.join(
- fooDirectory.path,
- 'nonExistentFile.txt',
- ),
- );
- await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
- expect(nonExistentFile.existsSync(), false);
- await client.writeFileAsString(
- nonExistentFile.uri,
- newFileContents,
- );
- expect(nonExistentFile.existsSync(), true);
- expect(nonExistentFile.readAsStringSync(), newFileContents);
- });
-
- test('creates sub directories if they don\'t exist', () async {
- final fileInNonExistentDirectory = File(
- p.join(
- fooDirectory.path,
- 'a',
- 'b',
- 'c',
- 'nonExistentFile.txt',
- ),
- );
- await client.setIDEWorkspaceRoots(dtdSecret, [fooDirectory.uri]);
- expect(fileInNonExistentDirectory.existsSync(), false);
- await client.writeFileAsString(
- fileInNonExistentDirectory.uri,
- newFileContents,
- );
- expect(fileInNonExistentDirectory.existsSync(), true);
- expect(fileInNonExistentDirectory.readAsStringSync(), newFileContents);
- });
-
- test('must have a file scheme', () {
- expect(
- () => client.writeFileAsString(
- Uri.parse('/some/path/'),
- 'some contents',
- ),
- throwsAnRpcError(RpcErrorCodes.kExpectsUriParamWithFileScheme),
- );
- });
- });
+ final readResult = await client.readFileAsString(aFile.uri);
+ expect(readResult.content, fileContents);
+ expect((await client.getIDEWorkspaceRoots()).ideWorkspaceRoots, [
+ barDirectory.uri,
+ ]);
+ },
+ );
});
}
diff --git a/pkg/dtd/test/utils.dart b/pkg/dtd/test/utils.dart
index e8d9ee5..57d62cc 100644
--- a/pkg/dtd/test/utils.dart
+++ b/pkg/dtd/test/utils.dart
@@ -7,15 +7,21 @@
import 'dart:io';
class ToolingDaemonTestProcess {
- late final String trustedSecret;
+ ToolingDaemonTestProcess({this.unrestricted = false});
+ late final String? trustedSecret;
late final Uri uri;
late final Process? process;
+ final bool unrestricted;
Future<Process> start() async {
final completer = Completer<void>();
process = await Process.start(
Platform.resolvedExecutable,
- ['tooling-daemon', '--machine'],
+ [
+ 'tooling-daemon',
+ '--machine',
+ if (unrestricted) '--unrestricted',
+ ],
);
process!.stdout.transform(utf8.decoder).listen((line) {
stderr.write('DTD stdout: $line');
@@ -23,7 +29,8 @@
final json = jsonDecode(line) as Map<String, Object?>;
final toolingDaemonDetails =
json['tooling_daemon_details'] as Map<String, dynamic>;
- trustedSecret = toolingDaemonDetails['trusted_client_secret'] as String;
+ trustedSecret =
+ toolingDaemonDetails['trusted_client_secret'] as String?;
uri = Uri.parse(toolingDaemonDetails['uri'] as String);
completer.complete();
} catch (e) {
diff --git a/pkg/dtd_impl/lib/dart_tooling_daemon.dart b/pkg/dtd_impl/lib/dart_tooling_daemon.dart
index 36af61c..9336b94 100644
--- a/pkg/dtd_impl/lib/dart_tooling_daemon.dart
+++ b/pkg/dtd_impl/lib/dart_tooling_daemon.dart
@@ -29,6 +29,11 @@
isFlag: true,
negatable: false,
help: 'Sets output format to JSON for consumption in tools.',
+ ),
+ unrestricted(
+ isFlag: true,
+ negatable: false,
+ help: 'Disables restrictions on services registered by DTD.',
);
const DartToolingDaemonOptions({
@@ -70,13 +75,17 @@
class DartToolingDaemon {
DartToolingDaemon._({
required this.secret,
+ required bool unrestrictedMode,
bool ipv6 = false,
bool shouldLogRequests = false,
}) : _ipv6 = ipv6,
_shouldLogRequests = shouldLogRequests {
streamManager = DTDStreamManager(this);
clientManager = DTDClientManager();
- fileSystemService = FileSystemService(secret: secret);
+ fileSystemService = FileSystemService(
+ secret: secret,
+ unrestrictedMode: unrestrictedMode,
+ );
}
static const _kSseHandlerPath = '\$debugHandler';
@@ -158,9 +167,13 @@
return null;
}
final machineMode = parsedArgs[DartToolingDaemonOptions.machine.name];
+ final unrestrictedMode =
+ parsedArgs[DartToolingDaemonOptions.unrestricted.name];
+
final secret = _generateSecret();
final dtd = DartToolingDaemon._(
secret: secret,
+ unrestrictedMode: unrestrictedMode,
ipv6: ipv6,
shouldLogRequests: shouldLogRequests,
);
@@ -170,7 +183,7 @@
jsonEncode({
'tooling_daemon_details': {
'uri': dtd.uri.toString(),
- 'trusted_client_secret': secret,
+ ...(!unrestrictedMode ? {'trusted_client_secret': secret} : {}),
},
}),
);
@@ -179,7 +192,10 @@
'The Dart Tooling Daemon is listening on '
'${dtd.uri.toString()}',
);
- print('Trusted Client Secret: $secret');
+
+ if (!unrestrictedMode) {
+ print('Trusted Client Secret: $secret');
+ }
}
return dtd;
}
diff --git a/pkg/dtd_impl/lib/src/file_system_service.dart b/pkg/dtd_impl/lib/src/file_system_service.dart
index 68789bc..b71bc99 100644
--- a/pkg/dtd_impl/lib/src/file_system_service.dart
+++ b/pkg/dtd_impl/lib/src/file_system_service.dart
@@ -12,11 +12,10 @@
import 'dtd_client.dart';
class FileSystemService {
- FileSystemService({
- required String secret,
- }) : _secret = secret;
+ FileSystemService({required this.secret, required this.unrestrictedMode});
- final String _secret;
+ final String secret;
+ final bool unrestrictedMode;
final List<Uri> _ideWorkspaceRoots = [];
static const String _serviceName = 'FileSystem';
@@ -51,6 +50,9 @@
}
void _ensureIDEWorkspaceRootsContainUri(Uri uri) {
+ // If in unrestricted mode, no need to do these checks.
+ if (unrestrictedMode) return;
+
for (final root in _ideWorkspaceRoots) {
if (uri.path.startsWith(root.path)) {
return;
@@ -64,7 +66,7 @@
Map<String, Object?> _setIDEWorkspaceRoots(Parameters parameters) {
final incomingSecret = parameters['secret'].asString;
- if (_secret != incomingSecret) {
+ if (!unrestrictedMode && secret != incomingSecret) {
throw RpcErrorCodes.buildRpcException(
RpcErrorCodes.kPermissionDenied,
);
@@ -91,9 +93,7 @@
return IDEWorkspaceRoots(ideWorkspaceRoots: _ideWorkspaceRoots).toJson();
}
- Future<Map<String, Object?>> _readFileAsString(
- Parameters parameters,
- ) async {
+ Future<Map<String, Object?>> _readFileAsString(Parameters parameters) async {
final uri = _extractUri(parameters);
_ensureIDEWorkspaceRootsContainUri(uri);
final file = File.fromUri(uri);
@@ -120,9 +120,7 @@
return uri;
}
- Future<Map<String, Object?>> _writeFileAsString(
- Parameters parameters,
- ) async {
+ Future<Map<String, Object?>> _writeFileAsString(Parameters parameters) async {
final uri = _extractUri(parameters);
final contents = parameters['contents'].asString;
final encoding = Encoding.getByName(