1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
fuchsia_web / webinstance_host / web_instance_host.h [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FUCHSIA_WEB_WEBINSTANCE_HOST_WEB_INSTANCE_HOST_H_
#define FUCHSIA_WEB_WEBINSTANCE_HOST_WEB_INSTANCE_HOST_H_
#include <fuchsia/component/cpp/fidl.h>
#include <fuchsia/web/cpp/fidl.h>
#include <lib/fidl/cpp/interface_ptr.h>
#include <lib/fidl/cpp/interface_request.h>
#include <zircon/types.h>
#include <string_view>
#include <utility>
#include "base/command_line.h"
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/sequence_checker.h"
#include "base/uuid.h"
#include "fuchsia_web/webinstance_host/fuchsia_web_debug_proxy.h"
namespace fuchsia::io {
class Directory;
}
namespace sys {
class OutgoingDirectory;
}
// Helper class that allows web_instance Components to be launched based on
// caller-supplied |CreateContextParams|.
// Use one of the concrete subclasses when instantiating.
//
// Note that Components using this class must:
// 1. Include `web_instance_host.shard.cml` in their component manifest.
// 2. Have web_instance's config-data available to the calling Component as
// the `config-data-for-web-instance` directory capability.
//
// To ensure proper product data registration, Components using the class must:
// * Have the same version and channel as WebEngine.
// * Instantiate the class on a thread with an async_dispatcher.
// TODO(crbug.com/42050393): Remove these requirements when platform supports
// it.
class WebInstanceHost {
public:
virtual ~WebInstanceHost();
WebInstanceHost(const WebInstanceHost&) = delete;
WebInstanceHost& operator=(const WebInstanceHost&) = delete;
// Creates a new web_instance Component and connects |services_request| to it.
// Returns ZX_OK if `params` were valid, and the Component was launched.
// `extra_args` are included on the command line when launching the new
// web_instance. Use `base::CommandLine(base::CommandLine::NO_PROGRAM)` for
// empty args.
virtual zx_status_t CreateInstanceForContextWithCopiedArgs(
fuchsia::web::CreateContextParams params,
fidl::InterfaceRequest<fuchsia::io::Directory> services_request,
const base::CommandLine& extra_args) = 0;
// Exposes a fuchsia.web.Debug protocol implementation that can be used
// to receive notifications of DevTools debug ports for new web instances.
fuchsia::web::Debug& debug_api() { return debug_proxy_; }
// The next created WebInstance will have access to the given directory handle
// for temporary directory reading and writing.
// Ownership of the directory is passed to the next created instance.
void set_tmp_dir(fidl::InterfaceHandle<fuchsia::io::Directory> tmp_dir) {
tmp_dir_ = std::move(tmp_dir);
}
protected:
// The host will offer capabilities to child instances via
// `outgoing_directory`. WebInstanceHost owners must serve the directory
// before creating web instances, and must ensure that the directory outlives
// the WebInstanceHost instance.
// TODO(crbug.com/40841277): Remove `outgoing_directory` if and when it is
// possible for tests to serve a test-specific outgoing directory via
// base::TestComponentContextForProcess on a separate thread.
WebInstanceHost(sys::OutgoingDirectory& outgoing_directory,
bool is_web_instance_component_in_same_package);
// Creates a new web_instance Component using `instance_component_url` and
// connects |services_request| to it. Returns ZX_OK if `params` were valid,
// and the Component was launched. `extra_args` are included on the command
// line when launching the new web_instance. Use
// `base::CommandLine(base::CommandLine::NO_PROGRAM)` for empty args.
// `services_to_offer` must be non-empty if and only if
// `params.service_directory` is present
zx_status_t CreateInstanceForContextWithCopiedArgsAndUrl(
fuchsia::web::CreateContextParams params,
fidl::InterfaceRequest<fuchsia::io::Directory> services_request,
base::CommandLine extra_args,
std::string_view instance_component_url,
std::vector<std::string> services_to_offer);
private:
bool is_initialized() const VALID_CONTEXT_REQUIRED(sequence_checker_) {
return realm_.is_bound();
}
// Connects to the fuchsia.component/Realm protocol.
void Initialize();
// Destroys all child instances and associated resources and unbinds from the
// fuchsia.component/Realm protocol.
void Uninitialize();
// Error handler for the channel to RealmBuilder.
void OnRealmError(zx_status_t status);
// Error handler for the channel to an instance's Binder.
void OnComponentBinderClosed(const base::Uuid& id, zx_status_t status);
// The directory via which directory capabilities are dynamically provided to
// child instances.
const raw_ref<sys::OutgoingDirectory> outgoing_directory_
GUARDED_BY_CONTEXT(sequence_checker_);
// The framework-provided protocol used to manage child instances.
fidl::InterfacePtr<fuchsia::component::Realm> realm_
GUARDED_BY_CONTEXT(sequence_checker_);
// A mapping of child instance GUID to the child's Binder interface, by which
// child instance shutdown is observed.
base::flat_map<base::Uuid, fidl::InterfacePtr<fuchsia::component::Binder>>
instances_ GUARDED_BY_CONTEXT(sequence_checker_);
// Implements the fuchsia.web.Debug API across all instances.
FuchsiaWebDebugProxy debug_proxy_;
// If set, then the next created WebInstance will gain ownership of this
// directory.
fidl::InterfaceHandle<fuchsia::io::Directory> tmp_dir_;
// Whether `web_instance.cm` is in the same Package as this host Component.
// TODO(crbug.com/42050363): Determine this based on a static Structured
// Configuration value once Structured Configuration is supported.
const bool is_web_instance_component_in_same_package_;
SEQUENCE_CHECKER(sequence_checker_);
};
// An instantiable WebInstanceHost where services from this Component are
// provided to each `WebInstance`.
class WebInstanceHostWithServicesFromThisComponent : public WebInstanceHost {
public:
WebInstanceHostWithServicesFromThisComponent(
sys::OutgoingDirectory& outgoing_directory,
bool is_web_instance_component_in_same_package);
zx_status_t CreateInstanceForContextWithCopiedArgs(
fuchsia::web::CreateContextParams params,
fidl::InterfaceRequest<fuchsia::io::Directory> services_request,
const base::CommandLine& extra_args) override;
};
// An instantiable WebInstanceHost where services must be provided for each
// `WebInstance` in `params.service_directory` in the call to
// `CreateInstanceForContextWithCopiedArgs()`.
class WebInstanceHostWithoutServices : public WebInstanceHost {
public:
WebInstanceHostWithoutServices(
sys::OutgoingDirectory& outgoing_directory,
bool is_web_instance_component_in_same_package);
zx_status_t CreateInstanceForContextWithCopiedArgs(
fuchsia::web::CreateContextParams params,
fidl::InterfaceRequest<fuchsia::io::Directory> services_request,
const base::CommandLine& extra_args) override;
};
#endif // FUCHSIA_WEB_WEBINSTANCE_HOST_WEB_INSTANCE_HOST_H_