[vm] Support http and https schemes in dart imports.

Bug: https://github.com/dart-lang/sdk/issues/33388
Change-Id: I2bc6d45a3a953c56a68954def11bcc3cf237b6a6
Reviewed-on: https://dart-review.googlesource.com/64960
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Zach Anderson <zra@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 84825db..90dd842 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -38,7 +38,8 @@
 import 'package:kernel/kernel.dart' show Component, Procedure;
 import 'package:kernel/target/targets.dart' show TargetFlags;
 import 'package:kernel/target/vm.dart' show VmTarget;
-import 'package:vm/incremental_compiler.dart';
+import '../lib/incremental_compiler.dart';
+import '../lib/http_filesystem.dart';
 
 final bool verbose = new bool.fromEnvironment('DFE_VERBOSE');
 const String platformKernelFile = 'virtual_platform_kernel.dill';
@@ -514,11 +515,9 @@
 /// frontend.
 FileSystem _buildFileSystem(List sourceFiles, List<int> platformKernel,
     String multirootFilepaths, String multirootScheme) {
-  FileSystem fileSystem;
+  FileSystem fileSystem = new HttpAwareFileSystem(StandardFileSystem.instance);
 
-  if (sourceFiles.isEmpty && platformKernel == null) {
-    fileSystem = StandardFileSystem.instance;
-  } else {
+  if (!sourceFiles.isEmpty || platformKernel != null) {
     MemoryFileSystem memoryFileSystem =
         new MemoryFileSystem(Uri.parse('file:///'));
     if (sourceFiles != null) {
@@ -533,7 +532,7 @@
           .entityForUri(Uri.parse(platformKernelFile))
           .writeAsBytesSync(platformKernel);
     }
-    fileSystem = new HybridFileSystem(memoryFileSystem);
+    fileSystem = new HybridFileSystem(memoryFileSystem, fileSystem);
   }
 
   if (multirootFilepaths != null) {
diff --git a/pkg/vm/lib/http_filesystem.dart b/pkg/vm/lib/http_filesystem.dart
new file mode 100644
index 0000000..ed036cd
--- /dev/null
+++ b/pkg/vm/lib/http_filesystem.dart
@@ -0,0 +1,67 @@
+import 'dart:async';
+import 'dart:io' as io;
+
+import 'package:front_end/src/api_unstable/build_integration.dart';
+
+class HttpAwareFileSystem implements FileSystem {
+  FileSystem original;
+
+  HttpAwareFileSystem(this.original);
+
+  @override
+  FileSystemEntity entityForUri(Uri uri) {
+    if (uri.scheme == 'http' || uri.scheme == 'https') {
+      return new HttpFileSystemEntity(this, uri);
+    } else {
+      return original.entityForUri(uri);
+    }
+  }
+}
+
+class HttpFileSystemEntity implements FileSystemEntity {
+  HttpAwareFileSystem fileSystem;
+  Uri uri;
+
+  HttpFileSystemEntity(this.fileSystem, this.uri);
+
+  @override
+  Future<bool> exists() async {
+    return connectAndRun((io.HttpClient httpClient) async {
+      io.HttpClientRequest request = await httpClient.headUrl(uri);
+      io.HttpClientResponse response = await request.close();
+      return response.statusCode == io.HttpStatus.ok;
+    });
+  }
+
+  @override
+  Future<List<int>> readAsBytes() async {
+    return connectAndRun((io.HttpClient httpClient) async {
+      io.HttpClientRequest request = await httpClient.getUrl(uri);
+      io.HttpClientResponse response = await request.close();
+      if (response.statusCode != io.HttpStatus.ok) {
+        throw new FileSystemException(uri, response.toString());
+      }
+      List<List<int>> list = await response.toList();
+      return list.expand((list) => list).toList();
+    });
+  }
+
+  @override
+  Future<String> readAsString() async {
+    return String.fromCharCodes(await readAsBytes());
+  }
+
+  T connectAndRun<T>(T body(io.HttpClient httpClient)) {
+    io.HttpClient httpClient;
+    try {
+      httpClient = new io.HttpClient();
+      // Set timeout to be shorter than anticipated OS default
+      httpClient.connectionTimeout = const Duration(seconds: 5);
+      return body(httpClient);
+    } on Exception catch (e) {
+      throw new FileSystemException(uri, e.toString());
+    } finally {
+      httpClient?.close(force: true);
+    }
+  }
+}
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index ef393a7..a4ff9b6 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -6853,7 +6853,7 @@
       "foo1:///main.dart",
       /* multiroot_filepaths= */ "/bar,/baz",
       /* multiroot_scheme= */ "foo");
-  EXPECT_ERROR(lib, "Compilation failed foo1");
+  EXPECT_ERROR(lib, "Compilation failed FileSystemException(uri=foo1:");
 }
 
 void NewNativePort_send123(Dart_Port dest_port_id, Dart_CObject* message) {
diff --git a/tests/standalone_2/standalone_2.status b/tests/standalone_2/standalone_2.status
index 20dc2b5..965c602 100644
--- a/tests/standalone_2/standalone_2.status
+++ b/tests/standalone_2/standalone_2.status
@@ -94,12 +94,6 @@
 [ $runtime == none && !$strong ]
 io/process_exit_negative_test: Fail, OK # Must be run to exit with non-zero exit code.
 
-# These tests spawn a process that imports using a http URL, since
-# spawned processes now run in Dart2 mode the tests fail as http URL imports
-# is not supported by the front end.
-[ $runtime == vm && ($compiler == app_jit || $compiler == none) ]
-http_launch_test: RuntimeError # Issue 33388
-
 [ $system == linux && ($runtime == flutter || $runtime == vm) ]
 io/http_basic_test: Pass, Slow, Timeout # Issue 28046, These tests might be slow on an opt counter threshold bot. They also time out on the bot occasionally => flaky test issue 28046
 io/http_launch_test: Pass, Slow, Timeout # Issue 28046, These tests might be slow on an opt counter threshold bot. They also time out on the bot occasionally => flaky test issue 28046
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 0804201..201fe64 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -11,7 +11,6 @@
 # to add them.
 
 [ $compiler == app_jitk ]
-http_launch_test: RuntimeError # Issue 33388
 io/directory_test: RuntimeError
 io/file_error_test: RuntimeError
 io/file_test: RuntimeError
@@ -69,7 +68,6 @@
 io/web_socket_ping_test: Crash, Pass
 
 [ $compiler == dartk && $runtime == vm && $strong ]
-http_launch_test: RuntimeError # Issue 33388
 io/http_client_request_test: Pass, Timeout
 io/http_compression_test: RuntimeError
 io/platform_resolved_executable_test/03: Pass, RuntimeError