Add FileLoader to DartState

This CL makes it easier to use FileLoader in applications that have more
than one isolate.

Change-Id: I8984f4adaac92cb0ba30f65ce4da32e46c3ac2a5
diff --git a/BUILD.gn b/BUILD.gn
index a9578cb..75561fb 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -12,8 +12,6 @@
     "dart_class_provider.h",
     "dart_library_natives.cc",
     "dart_library_natives.h",
-    "dart_library_provider.cc",
-    "dart_library_provider.h",
     "dart_message_handler.cc",
     "dart_message_handler.h",
     "dart_microtask_queue.cc",
@@ -32,9 +30,10 @@
     "//dart/runtime:libdart",
     "//lib/ftl",
     "//lib/tonic/converter",
+    "//lib/tonic/file_loader",
     "//lib/tonic/logging",
-    "//lib/tonic/typed_data",
     "//lib/tonic/scopes",
+    "//lib/tonic/typed_data",
     "//mojo/public/cpp/system",
   ]
 }
diff --git a/dart_library_provider.cc b/dart_library_provider.cc
deleted file mode 100644
index c855e9d..0000000
--- a/dart_library_provider.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2015 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "lib/tonic/dart_library_provider.h"
-
-namespace tonic {
-
-DartLibraryProvider::~DartLibraryProvider() {}
-
-}  // namespace tonic
diff --git a/dart_library_provider.h b/dart_library_provider.h
deleted file mode 100644
index 1bdff8b..0000000
--- a/dart_library_provider.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef LIB_TONIC_DART_LIBRARY_PROVIDER_H_
-#define LIB_TONIC_DART_LIBRARY_PROVIDER_H_
-
-#include <functional>
-#include <string>
-
-#include "dart/runtime/include/dart_api.h"
-#include "mojo/public/cpp/system/data_pipe.h"
-
-namespace tonic {
-
-typedef std::function<void(mojo::ScopedDataPipeConsumerHandle)>
-    DataPipeConsumerCallback;
-
-class DartLibraryProvider {
- public:
-  virtual void GetLibraryAsStream(const std::string& name,
-                                  DataPipeConsumerCallback callback) = 0;
-
-  virtual Dart_Handle CanonicalizeURL(Dart_Handle library, Dart_Handle url) = 0;
-
-  virtual ~DartLibraryProvider();
-};
-
-}  // namespace tonic
-
-#endif  // LIB_TONIC_DART_LIBRARY_PROVIDER_H_
diff --git a/dart_state.cc b/dart_state.cc
index e8829a7..7ec7c3a 100644
--- a/dart_state.cc
+++ b/dart_state.cc
@@ -4,9 +4,10 @@
 
 #include "lib/tonic/dart_state.h"
 
-#include "lib/tonic/dart_class_library.h"
 #include "lib/tonic/converter/dart_converter.h"
+#include "lib/tonic/dart_class_library.h"
 #include "lib/tonic/dart_message_handler.h"
+#include "lib/tonic/file_loader/file_loader.h"
 
 namespace tonic {
 
@@ -17,9 +18,9 @@
 
 DartState::DartState()
     : isolate_(nullptr),
-      class_library_(std::unique_ptr<DartClassLibrary>(new DartClassLibrary)),
-      message_handler_(
-          std::unique_ptr<DartMessageHandler>(new DartMessageHandler())),
+      class_library_(new DartClassLibrary),
+      message_handler_(new DartMessageHandler()),
+      file_loader_(new FileLoader()),
       weak_factory_(this) {}
 
 DartState::~DartState() {}
@@ -43,7 +44,12 @@
   return weak_factory_.GetWeakPtr();
 }
 
-void DartState::DidSetIsolate() {
+void DartState::DidSetIsolate() {}
+
+Dart_Handle DartState::HandleLibraryTag(Dart_LibraryTag tag,
+                                        Dart_Handle library,
+                                        Dart_Handle url) {
+  return Current()->file_loader().HandleLibraryTag(tag, library, url);
 }
 
 }  // namespace tonic
diff --git a/dart_state.h b/dart_state.h
index e0984a2..8acb4c5 100644
--- a/dart_state.h
+++ b/dart_state.h
@@ -17,6 +17,7 @@
 namespace tonic {
 class DartClassLibrary;
 class DartMessageHandler;
+class FileLoader;
 
 // DartState represents the state associated with a given Dart isolate. The
 // lifetime of this object is controlled by the DartVM. If you want to hold a
@@ -48,13 +49,19 @@
 
   DartClassLibrary& class_library() { return *class_library_; }
   DartMessageHandler& message_handler() { return *message_handler_; }
+  FileLoader& file_loader() { return *file_loader_; }
 
   virtual void DidSetIsolate();
 
+  static Dart_Handle HandleLibraryTag(Dart_LibraryTag tag,
+                                      Dart_Handle library,
+                                      Dart_Handle url);
+
  private:
   Dart_Isolate isolate_;
   std::unique_ptr<DartClassLibrary> class_library_;
   std::unique_ptr<DartMessageHandler> message_handler_;
+  std::unique_ptr<FileLoader> file_loader_;
 
  protected:
   ftl::WeakPtrFactory<DartState> weak_factory_;
diff --git a/file_loader/file_loader.cc b/file_loader/file_loader.cc
index 8b1d53c..1a53cf9 100644
--- a/file_loader/file_loader.cc
+++ b/file_loader/file_loader.cc
@@ -74,6 +74,22 @@
   return true;
 }
 
+Dart_Handle FileLoader::HandleLibraryTag(Dart_LibraryTag tag,
+                                         Dart_Handle library,
+                                         Dart_Handle url) {
+  FTL_DCHECK(Dart_IsLibrary(library));
+  FTL_DCHECK(Dart_IsString(url));
+  if (tag == Dart_kCanonicalizeUrl)
+    return CanonicalizeURL(library, url);
+  if (tag == Dart_kImportTag)
+    return Import(url);
+  if (tag == Dart_kSourceTag)
+    return Source(library, url);
+  if (tag == Dart_kScriptTag)
+    return Script(url);
+  return Dart_NewApiError("Unknown library tag.");
+}
+
 Dart_Handle FileLoader::CanonicalizeURL(Dart_Handle library, Dart_Handle url) {
   std::string string = StdStringFromDart(url);
   if (string.find(kDartScheme) == 0u)
@@ -121,8 +137,15 @@
   return url.substr(kFileURLPrefixLength);
 }
 
-std::string FileLoader::Fetch(const std::string& url) {
+std::string FileLoader::GetFileURLForPath(const std::string& path) {
+  return std::string(kFileURLPrefix) + path;
+}
+
+std::string FileLoader::Fetch(const std::string& url,
+                              std::string* resolved_url) {
   std::string path = GetFilePathForURL(url);
+  if (resolved_url)
+    *resolved_url = GetFileURLForPath(path);
   std::string source;
   if (!files::ReadFileToString(files::GetAbsoluteFilePath(path), &source)) {
     std::cerr << "error: Unable to find Dart library '" << url << "'."
@@ -134,16 +157,32 @@
   return source;
 }
 
-Dart_Handle FileLoader::Import(Dart_Handle url) {
-  Dart_Handle source = StdStringToDart(Fetch(StdStringFromDart(url)));
-  Dart_Handle result = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
+Dart_Handle FileLoader::LoadLibrary(const std::string& url) {
+  std::string resolved_url;
+  Dart_Handle source = ToDart(Fetch(url, &resolved_url));
+  Dart_Handle result =
+      Dart_LoadLibrary(ToDart(url), ToDart(resolved_url), source, 0, 0);
   DART_CHECK_VALID(result);
   return result;
 }
 
+Dart_Handle FileLoader::Import(Dart_Handle url) {
+  return LoadLibrary(StdStringFromDart(url));
+}
+
 Dart_Handle FileLoader::Source(Dart_Handle library, Dart_Handle url) {
-  Dart_Handle source = StdStringToDart(Fetch(StdStringFromDart(url)));
-  Dart_Handle result = Dart_LoadSource(library, url, Dart_Null(), source, 0, 0);
+  std::string resolved_url;
+  Dart_Handle source = ToDart(Fetch(StdStringFromDart(url), &resolved_url));
+  Dart_Handle result =
+      Dart_LoadSource(library, url, ToDart(resolved_url), source, 0, 0);
+  DART_CHECK_VALID(result);
+  return result;
+}
+
+Dart_Handle FileLoader::Script(Dart_Handle url) {
+  std::string resolved_url;
+  Dart_Handle source = ToDart(Fetch(StdStringFromDart(url), &resolved_url));
+  Dart_Handle result = Dart_LoadScript(url, ToDart(resolved_url), source, 0, 0);
   DART_CHECK_VALID(result);
   return result;
 }
diff --git a/file_loader/file_loader.h b/file_loader/file_loader.h
index 685f8c1..786868c 100644
--- a/file_loader/file_loader.h
+++ b/file_loader/file_loader.h
@@ -31,17 +31,28 @@
   const std::set<std::string>& url_dependencies() const {
     return url_dependencies_;
   }
+
+  Dart_Handle HandleLibraryTag(Dart_LibraryTag tag,
+                               Dart_Handle library,
+                               Dart_Handle url);
+
   Dart_Handle CanonicalizeURL(Dart_Handle library, Dart_Handle url);
   Dart_Handle Import(Dart_Handle url);
   Dart_Handle Source(Dart_Handle library, Dart_Handle url);
+  Dart_Handle Script(Dart_Handle url);
 
-  std::string Fetch(const std::string& url);
+  Dart_Handle LoadLibrary(const std::string& url);
+
+  std::string Fetch(const std::string& url,
+                    std::string* resolved_url = nullptr);
 
  private:
   std::string GetFilePathForURL(std::string url);
   std::string GetFilePathForPackageURL(std::string url);
   std::string GetFilePathForFileURL(std::string url);
 
+  std::string GetFileURLForPath(const std::string& path);
+
   std::set<std::string> dependencies_;
   std::set<std::string> url_dependencies_;
   std::string packages_;