blob: 6c03786b9e748a9f5ec1dc7ce0c235fddb3d6315 [file] [log] [blame]
// Copyright 2022 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/developer/debug/debug_agent/component_manager.h"
#include "src/developer/debug/debug_agent/process_handle.h"
#include "src/developer/debug/debug_agent/system_interface.h"
#include "src/developer/debug/ipc/records.h"
namespace debug_agent {
namespace {
// Returns a function that can be used to compare other |debug_ipc::ComponentInfo| objects to the
// supplied |needle|. The |needle| controls what is compared by setting only the desired fields to
// be compared. Setting all fields is equivalent to directly comparing the two ComponentInfo
// objects. This is intended to be shared between all subclasses that provide an implementation for
// |FindComponentInfo| with a debug_ipc::ComponentInfo argument without being opinionated about how
// the derived classes keep track of the actual component information being looked up.
auto MakeComponentInfoComparator(const debug_ipc::ComponentInfo& needle) {
// We check either or both strings depending on what's populated from the caller.
bool check_moniker = !needle.moniker.empty();
bool check_url = !needle.url.empty();
return [=, &needle](const debug_ipc::ComponentInfo& info) -> bool {
// We can check all fields of the component info in this manner: if any check is enabled, then
// it must pass. If more than one check is enabled, then they must all pass, effectively
// performing a logical "and" over all enabled checks as provided by the input needle. Any
// checks that are not enabled are ignored.
if (check_moniker && needle.moniker != info.moniker) {
return false;
}
if (check_url && needle.url != info.url) {
return false;
}
// All checks passed, this is a match.
return true;
};
}
} // namespace
std::vector<debug_ipc::ComponentInfo> ComponentManager::FindComponentInfo(
const ProcessHandle& process) const {
zx_koid_t job_koid = process.GetJobKoid();
while (job_koid) {
auto components = FindComponentInfo(job_koid);
if (!components.empty())
return components;
job_koid = system_interface_->GetParentJobKoid(job_koid);
}
return {};
}
std::vector<debug_ipc::ComponentInfo> ComponentManager::FindComponentInfo(
const debug_ipc::ComponentInfo& needle) const {
if (needle.moniker.empty() && needle.url.empty()) {
return {};
}
return FindComponentInfoWithComparator(MakeComponentInfoComparator(needle));
}
std::optional<debug_ipc::ComponentInfo> ComponentManager::FindComponentInfoByMoniker(
const std::string& moniker) const {
debug_ipc::ComponentInfo info;
info.moniker = moniker;
auto result = FindComponentInfo(info);
if (result.empty()) {
return std::nullopt;
}
FX_DCHECK(result.size() == 1);
return result[0];
}
std::vector<debug_ipc::ComponentInfo> ComponentManager::FindComponentInfoByUrl(
const std::string& url) const {
debug_ipc::ComponentInfo info;
info.url = url;
return FindComponentInfo(info);
}
} // namespace debug_agent