| // 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. |
| |
| #include "peridot/lib/module_manifest_source/module_package_source.h" |
| |
| #include <dirent.h> |
| #include <sys/types.h> |
| |
| #include <fs/service.h> |
| #include <lib/async/cpp/task.h> |
| #include <src/lib/fxl/logging.h> |
| #include <src/lib/fxl/memory/weak_ptr.h> |
| #include <src/lib/fxl/strings/split_string.h> |
| #include <src/lib/fxl/strings/string_printf.h> |
| #include "src/lib/files/directory.h" |
| #include "src/lib/files/file.h" |
| |
| #include "peridot/lib/module_manifest_source/json.h" |
| #include "peridot/lib/module_manifest_source/package_util.h" |
| |
| namespace modular { |
| |
| using ::fuchsia::maxwell::internal::ModulePackageIndexer; |
| |
| ModulePackageSource::ModulePackageSource( |
| component::StartupContext* const context) |
| : weak_factory_(this) { |
| context->outgoing().debug_dir()->AddEntry( |
| ModulePackageIndexer::Name_, |
| fbl::AdoptRef(new fs::Service([this](zx::channel channel) { |
| indexer_bindings_.AddBinding( |
| this, |
| fidl::InterfaceRequest<ModulePackageIndexer>(std::move(channel))); |
| return ZX_OK; |
| }))); |
| } |
| |
| ModulePackageSource::~ModulePackageSource() {} |
| |
| void ModulePackageSource::IndexManifest(std::string package_name, |
| std::string module_manifest_path) { |
| FXL_DCHECK(dispatcher_); |
| FXL_DCHECK(new_entry_fn_); |
| |
| std::string data; |
| if (!files::ReadFileToString(module_manifest_path, &data)) { |
| FXL_LOG(ERROR) << "Couldn't read module manifest from: " |
| << module_manifest_path; |
| return; |
| } |
| |
| fuchsia::modular::ModuleManifest entry; |
| if (!ModuleManifestEntryFromJson(data, &entry)) { |
| FXL_LOG(WARNING) << "Couldn't parse module manifest from: " |
| << module_manifest_path; |
| return; |
| } |
| |
| async::PostTask(dispatcher_, |
| [weak_this = weak_factory_.GetWeakPtr(), package_name, |
| entry = std::move(entry)]() mutable { |
| if (!weak_this) { |
| return; |
| } |
| |
| weak_this->new_entry_fn_(entry.binary, std::move(entry)); |
| }); |
| } |
| |
| // TODO(vardhan): Move this into garnet's fxl. |
| void IterateDirectory(fxl::StringView dirname, |
| fit::function<void(fxl::StringView)> callback) { |
| DIR* fd = opendir(dirname.data()); |
| if (fd == nullptr) { |
| perror("Could not open module package index directory: "); |
| return; |
| } |
| struct dirent* dp = nullptr; |
| while ((dp = readdir(fd)) != nullptr) { |
| if (dp->d_name[0] != '.') { |
| callback(dp->d_name); |
| } |
| } |
| closedir(fd); |
| } |
| |
| void ModulePackageSource::Watch(async_dispatcher_t* dispatcher, IdleFn idle_fn, |
| NewEntryFn new_fn, RemovedEntryFn removed_fn) { |
| dispatcher_ = dispatcher; |
| new_entry_fn_ = std::move(new_fn); |
| |
| idle_fn(); |
| } |
| |
| } // namespace modular |