startup_context.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/fuchsia/startup_context.h"
  5. #include <tuple>
  6. #include <fuchsia/io/cpp/fidl.h>
  7. #include <lib/sys/cpp/outgoing_directory.h>
  8. #include <lib/sys/cpp/service_directory.h>
  9. #include "base/check_op.h"
  10. #include "base/fuchsia/file_utils.h"
  11. #include "base/fuchsia/fuchsia_logging.h"
  12. #include "base/logging.h"
  13. namespace base {
  14. StartupContext::StartupContext(fuchsia::sys::StartupInfo startup_info) {
  15. std::unique_ptr<sys::ServiceDirectory> incoming_services;
  16. // Component manager generates |flat_namespace|, so things are horribly broken
  17. // if |flat_namespace| is malformed.
  18. CHECK_EQ(startup_info.flat_namespace.directories.size(),
  19. startup_info.flat_namespace.paths.size());
  20. // Find the /svc directory and wrap it into a sys::ServiceDirectory.
  21. for (size_t i = 0; i < startup_info.flat_namespace.paths.size(); ++i) {
  22. if (startup_info.flat_namespace.paths[i] == kServiceDirectoryPath) {
  23. incoming_services = std::make_unique<sys::ServiceDirectory>(
  24. std::move(startup_info.flat_namespace.directories[i]));
  25. break;
  26. }
  27. }
  28. // TODO(https://crbug.com/933834): Remove these workarounds when we migrate to
  29. // the new component manager.
  30. if (!incoming_services && startup_info.launch_info.flat_namespace) {
  31. LOG(WARNING) << "Falling back to LaunchInfo namespace";
  32. for (size_t i = 0;
  33. i < startup_info.launch_info.flat_namespace->paths.size(); ++i) {
  34. if (startup_info.launch_info.flat_namespace->paths[i] ==
  35. kServiceDirectoryPath) {
  36. incoming_services = std::make_unique<sys::ServiceDirectory>(
  37. std::move(startup_info.launch_info.flat_namespace->directories[i]));
  38. break;
  39. }
  40. }
  41. }
  42. if (!incoming_services && startup_info.launch_info.additional_services) {
  43. LOG(WARNING) << "Falling back to additional ServiceList services";
  44. // Construct a OutgoingDirectory and publish the additional services into
  45. // it.
  46. additional_services_.Bind(
  47. std::move(startup_info.launch_info.additional_services->provider));
  48. additional_services_directory_ = std::make_unique<sys::OutgoingDirectory>();
  49. for (auto& name : startup_info.launch_info.additional_services->names) {
  50. zx_status_t status = additional_services_directory_->AddPublicService(
  51. std::make_unique<vfs::Service>([this, name](
  52. zx::channel channel,
  53. async_dispatcher_t* dispatcher) {
  54. additional_services_->ConnectToService(name, std::move(channel));
  55. }),
  56. name);
  57. ZX_CHECK(status == ZX_OK, status)
  58. << "AddPublicService(" << name << ") failed";
  59. }
  60. // Publish those services to the caller as |incoming_services|.
  61. fidl::InterfaceHandle<fuchsia::io::Directory> incoming_directory;
  62. additional_services_directory_->GetOrCreateDirectory("svc")->Serve(
  63. fuchsia::io::OpenFlags::RIGHT_READABLE |
  64. fuchsia::io::OpenFlags::RIGHT_WRITABLE,
  65. incoming_directory.NewRequest().TakeChannel());
  66. incoming_services =
  67. std::make_unique<sys::ServiceDirectory>(std::move(incoming_directory));
  68. }
  69. if (!incoming_services) {
  70. LOG(WARNING) << "Component started without a service directory";
  71. // Create a dummy ServiceDirectory with a channel that's not
  72. // connected on the other end.
  73. fidl::InterfaceHandle<fuchsia::io::Directory> dummy_directory;
  74. std::ignore = dummy_directory.NewRequest();
  75. incoming_services =
  76. std::make_unique<sys::ServiceDirectory>(std::move(dummy_directory));
  77. }
  78. component_context_ =
  79. std::make_unique<sys::ComponentContext>(std::move(incoming_services));
  80. outgoing_directory_request_ =
  81. std::move(startup_info.launch_info.directory_request);
  82. }
  83. StartupContext::~StartupContext() = default;
  84. void StartupContext::ServeOutgoingDirectory() {
  85. DCHECK(outgoing_directory_request_);
  86. component_context_->outgoing()->Serve(std::move(outgoing_directory_request_));
  87. }
  88. } // namespace base