blob: a4d9e12f0774c43322a2f49e1b4059f0d5b1d85d [file] [log] [blame]
// Copyright 2018 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 GARNET_BIN_APPMGR_SERVICE_PROVIDER_DIR_IMPL_H_
#define GARNET_BIN_APPMGR_SERVICE_PROVIDER_DIR_IMPL_H_
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include <fs/pseudo-dir.h>
#include <fs/service.h>
#include <fs/synchronous-vfs.h>
#include <fuchsia/sys/cpp/fidl.h>
#include "lib/fidl/cpp/binding_set.h"
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/macros.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace component {
// A directory-like object which dynamically creates Service vnodes
// for any file lookup. It also exposes service provider interface.
//
// It supports enumeration for only first level of services.
class ServiceProviderDirImpl : public fuchsia::sys::ServiceProvider,
public fs::Vnode {
public:
explicit ServiceProviderDirImpl(
const std::vector<std::string>* services = nullptr);
~ServiceProviderDirImpl() override;
// Sets the parent of this. Parent should be fully initialized.
void set_parent(fbl::RefPtr<ServiceProviderDirImpl> parent);
void set_component_url(const std::string& url) { component_url_ = url; }
void AddService(const std::string& service_name,
fbl::RefPtr<fs::Service> service);
void AddBinding(
fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> request);
//
// Overridden from |fs::Vnode|:
//
zx_status_t Lookup(fbl::RefPtr<fs::Vnode>* out, fbl::StringPiece name) final;
zx_status_t Getattr(vnattr_t* a) final;
zx_status_t Readdir(fs::vdircookie_t* cookie, void* dirents, size_t len,
size_t* out_actual) final;
zx_status_t GetNodeInfo(uint32_t flags, fuchsia_io_NodeInfo* info) final;
//
// Overridden from |fuchsia::sys::ServiceProvider|:
//
void ConnectToService(std::string service_name, zx::channel channel) override;
bool IsDirectory() const final;
private:
bool IsServiceWhitelisted(const std::string& service_name) {
return (!has_services_whitelist_ ||
services_whitelist_.count(service_name) > 0);
}
fidl::BindingSet<fuchsia::sys::ServiceProvider> bindings_;
fs::SynchronousVfs vfs_;
// |root_| has all services offered by this provider (including those
// inherited from the parent, if any).
fbl::RefPtr<fs::PseudoDir> root_;
fbl::RefPtr<ServiceProviderDirImpl> parent_;
fxl::WeakPtrFactory<ServiceProviderDirImpl> weak_factory_;
// TODO(CP-25): Remove has_services_whitelist_ when empty services is
// equivalent to no services.
bool has_services_whitelist_ = false;
std::unordered_set<std::string> services_whitelist_;
// Secondary storage for services under |root_| in a format that can easily
// be consumed by children. Stored as vector to preserve order.
typedef std::pair<std::string, fbl::RefPtr<fs::Service>> ServiceHandle;
std::vector<ServiceHandle> service_handles_;
std::unordered_set<std::string> all_service_names_;
std::string component_url_ = "NO_COMPONENT";
FXL_DISALLOW_COPY_AND_ASSIGN(ServiceProviderDirImpl);
};
} // namespace component
#endif // GARNET_BIN_APPMGR_SERVICE_PROVIDER_DIR_IMPL_H_