xref: /aosp_15_r20/external/cronet/base/fuchsia/test_component_context_for_process.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/fuchsia/test_component_context_for_process.h"
6 
7 #include <fidl/fuchsia.io/cpp/hlcpp_conversion.h>
8 #include <fuchsia/io/cpp/fidl.h>
9 #include <lib/fdio/directory.h>
10 #include <lib/fidl/cpp/interface_handle.h>
11 #include <lib/sys/cpp/component_context.h>
12 
13 #include <string_view>
14 
15 #include "base/files/file_enumerator.h"
16 #include "base/fuchsia/filtered_service_directory.h"
17 #include "base/fuchsia/fuchsia_logging.h"
18 #include "base/fuchsia/process_context.h"
19 #include "base/run_loop.h"
20 
21 namespace base {
22 
TestComponentContextForProcess(InitialState initial_state)23 TestComponentContextForProcess::TestComponentContextForProcess(
24     InitialState initial_state) {
25   // TODO(https://crbug.com/1038786): Migrate to sys::ComponentContextProvider
26   // once it provides access to an sys::OutgoingDirectory or PseudoDir through
27   // which to publish additional_services().
28 
29   // Set up |incoming_services_| to use the ServiceDirectory from the current
30   // default ComponentContext to fetch services from.
31   context_services_ = std::make_unique<FilteredServiceDirectory>(
32       base::ComponentContextForProcess()->svc());
33 
34   // Push all services from /svc to the test context if requested.
35   if (initial_state == InitialState::kCloneAll) {
36     // Calling stat() in /svc is problematic; see https://fxbug.dev/100207. Tell
37     // the enumerator not to recurse, to return both files and directories, and
38     // to report only the names of entries.
39     base::FileEnumerator file_enum(base::FilePath("/svc"), /*recursive=*/false,
40                                    base::FileEnumerator::NAMES_ONLY);
41     for (auto file = file_enum.Next(); !file.empty(); file = file_enum.Next()) {
42       AddService(file.BaseName().value());
43     }
44   }
45 
46   // Create a ServiceDirectory backed by the contents of |incoming_directory|.
47   fidl::InterfaceHandle<::fuchsia::io::Directory> incoming_directory;
48   zx_status_t status =
49       context_services_->ConnectClient(incoming_directory.NewRequest());
50   ZX_CHECK(status == ZX_OK, status) << "ConnectClient failed";
51   auto incoming_services =
52       std::make_shared<sys::ServiceDirectory>(std::move(incoming_directory));
53 
54   // Create the ComponentContext with the incoming directory connected to the
55   // directory of |context_services_| published by the test, and with a request
56   // for the process' root outgoing directory.
57   fidl::InterfaceHandle<::fuchsia::io::Directory> published_root_directory;
58   old_context_ = ReplaceComponentContextForProcessForTest(
59       std::make_unique<sys::ComponentContext>(
60           std::move(incoming_services), published_root_directory.NewRequest()));
61 
62   // Connect to the "/svc" directory of the |published_root_directory| and wrap
63   // that into a ServiceDirectory.
64   fidl::InterfaceHandle<::fuchsia::io::Directory> published_services;
65   status = fdio_service_connect_at(
66       published_root_directory.channel().get(), "svc",
67       published_services.NewRequest().TakeChannel().release());
68   ZX_CHECK(status == ZX_OK, status) << "fdio_service_connect_at() to /svc";
69   published_services_ =
70       std::make_shared<sys::ServiceDirectory>(std::move(published_services));
71   published_services_natural_ =
72       fidl::HLCPPToNatural(published_services_->CloneChannel());
73 }
74 
~TestComponentContextForProcess()75 TestComponentContextForProcess::~TestComponentContextForProcess() {
76   ReplaceComponentContextForProcessForTest(std::move(old_context_));
77 }
78 
additional_services()79 sys::OutgoingDirectory* TestComponentContextForProcess::additional_services() {
80   return context_services_->outgoing_directory();
81 }
82 
AddService(const std::string_view service)83 void TestComponentContextForProcess::AddService(
84     const std::string_view service) {
85   zx_status_t status = context_services_->AddService(service);
86   ZX_CHECK(status == ZX_OK, status) << "AddService(" << service << ") failed";
87 }
88 
AddServices(base::span<const std::string_view> services)89 void TestComponentContextForProcess::AddServices(
90     base::span<const std::string_view> services) {
91   for (auto service : services)
92     AddService(service);
93 }
94 
95 fidl::UnownedClientEnd<fuchsia_io::Directory>
published_services_natural()96 TestComponentContextForProcess::published_services_natural() {
97   return published_services_natural_.borrow();
98 }
99 
100 }  // namespace base
101