| // 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 <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/strings/string_piece.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/1275224): 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/1327587): 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, |
| base::StringPiece 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/1255292): 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_ |