| // 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 "src/modular/lib/module_manifest_source/module_package_source.h" |
| |
| #include <dirent.h> |
| #include <lib/async/cpp/task.h> |
| #include <lib/vfs/cpp/service.h> |
| #include <sys/types.h> |
| |
| #include "src/lib/files/directory.h" |
| #include "src/lib/files/file.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/modular/lib/module_manifest_source/json.h" |
| #include "src/modular/lib/module_manifest_source/package_util.h" |
| |
| namespace modular { |
| |
| using ::fuchsia::maxwell::internal::ModulePackageIndexer; |
| |
| ModulePackageSource::ModulePackageSource(sys::ComponentContext* const context) |
| : weak_factory_(this) { |
| context->outgoing()->debug_dir()->AddEntry( |
| ModulePackageIndexer::Name_, |
| std::make_unique<vfs::Service>([this](zx::channel channel, async_dispatcher_t*) { |
| indexer_bindings_.AddBinding( |
| this, fidl::InterfaceRequest<ModulePackageIndexer>(std::move(channel))); |
| })); |
| } |
| |
| 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 |