[flutter_runner] Use a custom wrapper (RunnerContext) for startup handles

In the singleton app case, this is a prerequisite to Dart code
exposing stuff under out/.

Change-Id: Id581f1280abe9ef808584e0d14ff7d18f290d212
diff --git a/runtime/flutter_runner/BUILD.gn b/runtime/flutter_runner/BUILD.gn
index 9626c76..0efd427 100644
--- a/runtime/flutter_runner/BUILD.gn
+++ b/runtime/flutter_runner/BUILD.gn
@@ -86,6 +86,8 @@
       "platform_view.h",
       "runner.cc",
       "runner.h",
+      "runner_context.cc",
+      "runner_context.h",
       "service_provider_dir.cc",
       "service_provider_dir.h",
       "session_connection.cc",
@@ -139,8 +141,8 @@
              "//sdk/fidl/fuchsia.ui.input",
              "//sdk/fidl/fuchsia.ui.scenic",
              "//sdk/fidl/fuchsia.ui.views",
-             "//sdk/lib/ui/scenic/cpp",
              "//sdk/lib/sys/cpp",
+             "//sdk/lib/ui/scenic/cpp",
              "//sdk/lib/vfs/cpp",
              "//third_party/dart/runtime/bin:libdart_builtin${product_suffix}",
              "//third_party/icu",
@@ -150,8 +152,8 @@
              "//third_party/zlib:minizip",
              "//topaz/public/dart-pkg/fuchsia",
              "//topaz/runtime/dart/utils",
-             "//topaz/runtime/dart/utils:inlines",
              "//topaz/runtime/dart/utils:files",
+             "//topaz/runtime/dart/utils:inlines",
              "//topaz/runtime/dart/utils:vmo",
              "//zircon/public/fidl/fuchsia-io",
              "//zircon/public/lib/async-cpp",
diff --git a/runtime/flutter_runner/runner.cc b/runtime/flutter_runner/runner.cc
index ee2810c..c2e829c 100644
--- a/runtime/flutter_runner/runner.cc
+++ b/runtime/flutter_runner/runner.cc
@@ -89,12 +89,13 @@
 }
 
 Runner::Runner(async::Loop* loop)
-    : loop_(loop), host_context_(sys::ComponentContext::Create()) {
+    : loop_(loop),
+      runner_context_(RunnerContext::CreateFromStartupInfo()) {
 #if !defined(DART_PRODUCT)
   // The VM service isolate uses the process-wide namespace. It writes the
   // vm service protocol port under /tmp. The VMServiceObject exposes that
   // port number to The Hub.
-  host_context_->outgoing()->debug_dir()->AddEntry(
+  runner_context_->debug_dir()->AddEntry(
       dart_utils::VMServiceObject::kPortDirName,
       std::make_unique<dart_utils::VMServiceObject>());
 
@@ -109,12 +110,12 @@
 
   SetThreadName("io.flutter.runner.main");
 
-  host_context_->outgoing()->AddPublicService<fuchsia::sys::Runner>(
+  runner_context_->AddPublicService<fuchsia::sys::Runner>(
       std::bind(&Runner::RegisterApplication, this, std::placeholders::_1));
 }
 
 Runner::~Runner() {
-  host_context_->outgoing()->RemovePublicService<fuchsia::sys::Runner>();
+  runner_context_->RemovePublicService<fuchsia::sys::Runner>();
 
 #if !defined(DART_PRODUCT)
   trace_observer_->Stop();
@@ -150,7 +151,7 @@
       std::move(termination_callback),  // termination callback
       std::move(package),               // application pacakge
       std::move(startup_info),          // startup info
-      host_context_->svc(),             // runner incoming services
+      runner_context_->svc(),           // runner incoming services
       std::move(controller)             // controller request
   );
 
diff --git a/runtime/flutter_runner/runner.h b/runtime/flutter_runner/runner.h
index 5176873..3ebf90a 100644
--- a/runtime/flutter_runner/runner.h
+++ b/runtime/flutter_runner/runner.h
@@ -17,6 +17,7 @@
 #include "component.h"
 #include "flutter/fml/macros.h"
 #include "lib/fidl/cpp/binding_set.h"
+#include "runner_context.h"
 #include "thread.h"
 #include "topaz/runtime/dart/utils/vmservice_object.h"
 
@@ -45,7 +46,7 @@
     ActiveApplication() = default;
   };
 
-  std::unique_ptr<sys::ComponentContext> host_context_;
+  std::unique_ptr<RunnerContext> runner_context_;
   fidl::BindingSet<fuchsia::sys::Runner> active_applications_bindings_;
   std::unordered_map<const Application*, ActiveApplication>
       active_applications_;
diff --git a/runtime/flutter_runner/runner_context.cc b/runtime/flutter_runner/runner_context.cc
new file mode 100644
index 0000000..dd697e0
--- /dev/null
+++ b/runtime/flutter_runner/runner_context.cc
@@ -0,0 +1,39 @@
+// Copyright 2019 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 "runner_context.h"
+
+namespace flutter_runner {
+
+RunnerContext::RunnerContext(std::shared_ptr<sys::ServiceDirectory> svc,
+                             zx::channel directory_request)
+    : svc_(std::move(svc)),
+      root_dir_(std::make_shared<vfs::PseudoDir>()),
+      public_dir_(std::make_shared<vfs::PseudoDir>()),
+      debug_dir_(std::make_shared<vfs::PseudoDir>()),
+      ctrl_dir_(std::make_shared<vfs::PseudoDir>()) {
+  root_dir_->AddSharedEntry("public", public_dir_);
+  root_dir_->AddSharedEntry("debug", debug_dir_);
+  root_dir_->AddSharedEntry("ctrl", ctrl_dir_);
+
+  root_dir_->Serve(
+      fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE,
+      std::move(directory_request));
+}
+
+RunnerContext::~RunnerContext() = default;
+
+std::unique_ptr<RunnerContext> RunnerContext::CreateFromStartupInfo() {
+  zx_handle_t directory_request = zx_take_startup_handle(PA_DIRECTORY_REQUEST);
+  return std::make_unique<RunnerContext>(
+      sys::ServiceDirectory::CreateFromNamespace(),
+      zx::channel(directory_request));
+}
+
+zx_status_t RunnerContext::AddPublicService(
+    std::unique_ptr<vfs::Service> service, std::string service_name) const {
+  return public_dir_->AddEntry(std::move(service_name), std::move(service));
+}
+
+}  // namespace flutter_runner
diff --git a/runtime/flutter_runner/runner_context.h b/runtime/flutter_runner/runner_context.h
new file mode 100644
index 0000000..6875f12
--- /dev/null
+++ b/runtime/flutter_runner/runner_context.h
@@ -0,0 +1,66 @@
+// Copyright 2019 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 TOPAZ_RUNTIME_FLUTTER_RUNNER_RUNNER_CONTEXT_H_
+#define TOPAZ_RUNTIME_FLUTTER_RUNNER_RUNNER_CONTEXT_H_
+
+#include <memory>
+#include <unordered_map>
+
+#include <fuchsia/sys/cpp/fidl.h>
+#include <lib/async-loop/cpp/loop.h>
+#include <lib/sys/cpp/component_context.h>
+#include <lib/vfs/cpp/pseudo_dir.h>
+#include <lib/vfs/cpp/service.h>
+#include <zircon/process.h>
+#include <zircon/processargs.h>
+
+#include "flutter/fml/macros.h"
+
+namespace flutter_runner {
+
+class RunnerContext {
+ public:
+  RunnerContext(std::shared_ptr<sys::ServiceDirectory> svc,
+                zx::channel directory_request);
+  ~RunnerContext();
+
+  static std::unique_ptr<RunnerContext> CreateFromStartupInfo();
+
+  const std::shared_ptr<sys::ServiceDirectory>& svc() const { return svc_; }
+  const std::shared_ptr<vfs::PseudoDir>& root_dir() const { return root_dir_; }
+  const std::shared_ptr<vfs::PseudoDir>& public_dir() const { return public_dir_; }
+  const std::shared_ptr<vfs::PseudoDir>& debug_dir() const { return debug_dir_; }
+  const std::shared_ptr<vfs::PseudoDir>& ctrl_dir() const { return ctrl_dir_; }
+
+  template <typename Interface>
+  zx_status_t AddPublicService(
+      fidl::InterfaceRequestHandler<Interface> handler,
+      std::string service_name = Interface::Name_) const {
+    return AddPublicService(std::make_unique<vfs::Service>(std::move(handler)),
+                            std::move(service_name));
+  }
+
+  zx_status_t AddPublicService(std::unique_ptr<vfs::Service> service,
+                               std::string service_name) const;
+
+  template <typename Interface>
+  zx_status_t RemovePublicService(
+      const std::string& name = Interface::Name_) const {
+    return public_dir_->RemoveEntry(name);
+  }
+
+ private:
+  std::shared_ptr<sys::ServiceDirectory> svc_;
+  std::shared_ptr<vfs::PseudoDir> root_dir_;
+  std::shared_ptr<vfs::PseudoDir> public_dir_;
+  std::shared_ptr<vfs::PseudoDir> debug_dir_;
+  std::shared_ptr<vfs::PseudoDir> ctrl_dir_;
+
+  FML_DISALLOW_COPY_AND_ASSIGN(RunnerContext);
+};
+
+}  // namespace flutter_runner
+
+#endif  // TOPAZ_RUNTIME_FLUTTER_RUNNER_RUNNER_CONTEXT_H_