diff options
author | Andreas Kling <kling@serenityos.org> | 2023-04-24 10:31:49 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-04-25 14:48:40 +0200 |
commit | c756e021a7d89d02d2dccab20a1f53244d80bb9e (patch) | |
tree | 5ef398c39bc56f8f0a4869d77c103f3ee3149cb4 /Userland/DevTools | |
parent | 203e84c3781aa764379f545d47dd1e7ebe98dd66 (diff) | |
download | serenity-c756e021a7d89d02d2dccab20a1f53244d80bb9e.zip |
Userland: Remove "Inspector" program and related utilities
This program has never lived up to its original idea, and has been
broken for years (property editing, etc). It's also unmaintained and
off-by-default since forever.
At this point, Inspector is more of a maintenance burden than a feature,
so this commit removes it from the system, along with the mechanism in
Core::EventLoop that enables it.
If we decide we want the feature again in the future, it can be
reimplemented better. :^)
Diffstat (limited to 'Userland/DevTools')
-rw-r--r-- | Userland/DevTools/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/DevTools/Inspector/CMakeLists.txt | 16 | ||||
-rw-r--r-- | Userland/DevTools/Inspector/InspectorServerClient.h | 30 | ||||
-rw-r--r-- | Userland/DevTools/Inspector/RemoteObject.cpp | 23 | ||||
-rw-r--r-- | Userland/DevTools/Inspector/RemoteObject.h | 35 | ||||
-rw-r--r-- | Userland/DevTools/Inspector/RemoteObjectGraphModel.cpp | 95 | ||||
-rw-r--r-- | Userland/DevTools/Inspector/RemoteObjectGraphModel.h | 44 | ||||
-rw-r--r-- | Userland/DevTools/Inspector/RemoteObjectPropertyModel.cpp | 216 | ||||
-rw-r--r-- | Userland/DevTools/Inspector/RemoteObjectPropertyModel.h | 50 | ||||
-rw-r--r-- | Userland/DevTools/Inspector/RemoteProcess.cpp | 108 | ||||
-rw-r--r-- | Userland/DevTools/Inspector/RemoteProcess.h | 48 | ||||
-rw-r--r-- | Userland/DevTools/Inspector/main.cpp | 155 |
12 files changed, 0 insertions, 821 deletions
diff --git a/Userland/DevTools/CMakeLists.txt b/Userland/DevTools/CMakeLists.txt index 54a8e343ab..b61e03d54b 100644 --- a/Userland/DevTools/CMakeLists.txt +++ b/Userland/DevTools/CMakeLists.txt @@ -1,5 +1,4 @@ add_subdirectory(GMLPlayground) -add_subdirectory(Inspector) add_subdirectory(Profiler) add_subdirectory(HackStudio) add_subdirectory(SQLStudio) diff --git a/Userland/DevTools/Inspector/CMakeLists.txt b/Userland/DevTools/Inspector/CMakeLists.txt deleted file mode 100644 index 7c3c58c2b4..0000000000 --- a/Userland/DevTools/Inspector/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -serenity_component( - Inspector - RECOMMENDED - TARGETS Inspector -) - -set(SOURCES - main.cpp - RemoteObject.cpp - RemoteObjectGraphModel.cpp - RemoteObjectPropertyModel.cpp - RemoteProcess.cpp -) - -serenity_app(Inspector ICON app-inspector) -target_link_libraries(Inspector PRIVATE LibCore LibDesktop LibGfx LibGUI LibIPC LibMain) diff --git a/Userland/DevTools/Inspector/InspectorServerClient.h b/Userland/DevTools/Inspector/InspectorServerClient.h deleted file mode 100644 index d03ab0a2c2..0000000000 --- a/Userland/DevTools/Inspector/InspectorServerClient.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <InspectorServer/InspectorClientEndpoint.h> -#include <InspectorServer/InspectorServerEndpoint.h> -#include <LibIPC/ConnectionToServer.h> - -namespace Inspector { - -class InspectorServerClient final - : public IPC::ConnectionToServer<InspectorClientEndpoint, InspectorServerEndpoint> - , public InspectorClientEndpoint { - IPC_CLIENT_CONNECTION(InspectorServerClient, "/tmp/session/%sid/portal/inspector"sv) - -public: - virtual ~InspectorServerClient() override = default; - -private: - InspectorServerClient(NonnullOwnPtr<Core::LocalSocket> socket) - : IPC::ConnectionToServer<InspectorClientEndpoint, InspectorServerEndpoint>(*this, move(socket)) - { - } -}; - -} diff --git a/Userland/DevTools/Inspector/RemoteObject.cpp b/Userland/DevTools/Inspector/RemoteObject.cpp deleted file mode 100644 index f4b0449143..0000000000 --- a/Userland/DevTools/Inspector/RemoteObject.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "RemoteObject.h" -#include "RemoteObjectPropertyModel.h" - -namespace Inspector { - -RemoteObject::RemoteObject() - : m_property_model(RemoteObjectPropertyModel::create(*this)) -{ -} - -RemoteObjectPropertyModel& RemoteObject::property_model() -{ - m_property_model->invalidate(); - return *m_property_model; -} - -} diff --git a/Userland/DevTools/Inspector/RemoteObject.h b/Userland/DevTools/Inspector/RemoteObject.h deleted file mode 100644 index a02b99fa80..0000000000 --- a/Userland/DevTools/Inspector/RemoteObject.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <AK/DeprecatedString.h> -#include <AK/JsonObject.h> - -namespace Inspector { - -class RemoteObjectPropertyModel; - -class RemoteObject { -public: - RemoteObject(); - - RemoteObjectPropertyModel& property_model(); - - RemoteObject* parent { nullptr }; - Vector<NonnullOwnPtr<RemoteObject>> children; - - FlatPtr address { 0 }; - FlatPtr parent_address { 0 }; - DeprecatedString class_name; - DeprecatedString name; - - JsonObject json; - - NonnullRefPtr<RemoteObjectPropertyModel> m_property_model; -}; - -} diff --git a/Userland/DevTools/Inspector/RemoteObjectGraphModel.cpp b/Userland/DevTools/Inspector/RemoteObjectGraphModel.cpp deleted file mode 100644 index 97743bf3b9..0000000000 --- a/Userland/DevTools/Inspector/RemoteObjectGraphModel.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * Copyright (c) 2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "RemoteObjectGraphModel.h" -#include "RemoteObject.h" -#include "RemoteProcess.h" -#include <AK/JsonValue.h> -#include <LibGUI/Application.h> -#include <stdio.h> - -namespace Inspector { - -RemoteObjectGraphModel::RemoteObjectGraphModel(RemoteProcess& process) - : m_process(process) -{ - m_object_icon.set_bitmap_for_size(16, Gfx::Bitmap::load_from_file("/res/icons/16x16/inspector-object.png"sv).release_value_but_fixme_should_propagate_errors()); - m_window_icon.set_bitmap_for_size(16, Gfx::Bitmap::load_from_file("/res/icons/16x16/window.png"sv).release_value_but_fixme_should_propagate_errors()); - m_layout_icon.set_bitmap_for_size(16, Gfx::Bitmap::load_from_file("/res/icons/16x16/layout.png"sv).release_value_but_fixme_should_propagate_errors()); - m_timer_icon.set_bitmap_for_size(16, Gfx::Bitmap::load_from_file("/res/icons/16x16/timer.png"sv).release_value_but_fixme_should_propagate_errors()); -} - -GUI::ModelIndex RemoteObjectGraphModel::index(int row, int column, const GUI::ModelIndex& parent) const -{ - if (!parent.is_valid()) { - if (m_process.roots().is_empty()) - return {}; - return create_index(row, column, &m_process.roots().at(row)); - } - auto& remote_parent = *static_cast<RemoteObject*>(parent.internal_data()); - return create_index(row, column, &remote_parent.children.at(row)); -} - -GUI::ModelIndex RemoteObjectGraphModel::parent_index(const GUI::ModelIndex& index) const -{ - if (!index.is_valid()) - return {}; - auto& remote_object = *static_cast<RemoteObject*>(index.internal_data()); - if (!remote_object.parent) - return {}; - - // NOTE: If the parent has no parent, it's a root, so we have to look among the remote roots. - if (!remote_object.parent->parent) { - for (size_t row = 0; row < m_process.roots().size(); ++row) { - if (m_process.roots()[row] == remote_object.parent) - return create_index(row, 0, remote_object.parent); - } - VERIFY_NOT_REACHED(); - return {}; - } - - for (size_t row = 0; row < remote_object.parent->parent->children.size(); ++row) { - if (remote_object.parent->parent->children[row] == remote_object.parent) - return create_index(row, 0, remote_object.parent); - } - - VERIFY_NOT_REACHED(); - return {}; -} - -int RemoteObjectGraphModel::row_count(const GUI::ModelIndex& index) const -{ - if (!index.is_valid()) - return m_process.roots().size(); - auto& remote_object = *static_cast<RemoteObject*>(index.internal_data()); - return remote_object.children.size(); -} - -int RemoteObjectGraphModel::column_count(const GUI::ModelIndex&) const -{ - return 1; -} - -GUI::Variant RemoteObjectGraphModel::data(const GUI::ModelIndex& index, GUI::ModelRole role) const -{ - auto* remote_object = static_cast<RemoteObject*>(index.internal_data()); - if (role == GUI::ModelRole::Icon) { - if (remote_object->class_name == "Window") - return m_window_icon; - if (remote_object->class_name == "Timer") - return m_timer_icon; - if (remote_object->class_name.ends_with("Layout"sv)) - return m_layout_icon; - return m_object_icon; - } - if (role == GUI::ModelRole::Display) - return DeprecatedString::formatted("{}({:p})", remote_object->class_name, remote_object->address); - - return {}; -} - -} diff --git a/Userland/DevTools/Inspector/RemoteObjectGraphModel.h b/Userland/DevTools/Inspector/RemoteObjectGraphModel.h deleted file mode 100644 index 8cbbb745cf..0000000000 --- a/Userland/DevTools/Inspector/RemoteObjectGraphModel.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * Copyright (c) 2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <AK/JsonArray.h> -#include <AK/JsonObject.h> -#include <LibGUI/Model.h> - -namespace Inspector { - -class RemoteProcess; - -class RemoteObjectGraphModel final : public GUI::Model { -public: - static NonnullRefPtr<RemoteObjectGraphModel> create(RemoteProcess& process) - { - return adopt_ref(*new RemoteObjectGraphModel(process)); - } - - virtual ~RemoteObjectGraphModel() override = default; - - virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override; - virtual int column_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override; - virtual GUI::Variant data(const GUI::ModelIndex&, GUI::ModelRole) const override; - virtual GUI::ModelIndex index(int row, int column, const GUI::ModelIndex& parent = GUI::ModelIndex()) const override; - virtual GUI::ModelIndex parent_index(const GUI::ModelIndex&) const override; - -private: - explicit RemoteObjectGraphModel(RemoteProcess&); - - RemoteProcess& m_process; - - GUI::Icon m_object_icon; - GUI::Icon m_window_icon; - GUI::Icon m_layout_icon; - GUI::Icon m_timer_icon; -}; - -} diff --git a/Userland/DevTools/Inspector/RemoteObjectPropertyModel.cpp b/Userland/DevTools/Inspector/RemoteObjectPropertyModel.cpp deleted file mode 100644 index 02d706de36..0000000000 --- a/Userland/DevTools/Inspector/RemoteObjectPropertyModel.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "RemoteObjectPropertyModel.h" -#include "RemoteObject.h" -#include "RemoteProcess.h" - -namespace Inspector { - -RemoteObjectPropertyModel::RemoteObjectPropertyModel(RemoteObject& object) - : m_object(object) -{ -} - -int RemoteObjectPropertyModel::row_count(const GUI::ModelIndex& index) const -{ - Function<int(JsonValue const&)> do_count = [&](JsonValue const& value) { - if (value.is_array()) - return value.as_array().size(); - else if (value.is_object()) - return value.as_object().size(); - return (size_t)0; - }; - - if (index.is_valid()) { - auto* path = static_cast<JsonPath const*>(index.internal_data()); - return do_count(path->resolve(m_object.json)); - } else { - return do_count(m_object.json); - } -} - -DeprecatedString RemoteObjectPropertyModel::column_name(int column) const -{ - switch (column) { - case Column::Name: - return "Name"; - case Column::Value: - return "Value"; - } - VERIFY_NOT_REACHED(); -} - -GUI::Variant RemoteObjectPropertyModel::data(const GUI::ModelIndex& index, GUI::ModelRole role) const -{ - auto* path = static_cast<JsonPath const*>(index.internal_data()); - if (!path) - return {}; - - if (role == GUI::ModelRole::Display) { - switch (index.column()) { - case Column::Name: - return path->last().to_deprecated_string(); - case Column::Value: { - auto data = path->resolve(m_object.json); - if (data.is_array()) - return DeprecatedString::formatted("<Array with {} element{}", data.as_array().size(), data.as_array().size() == 1 ? ">" : "s>"); - if (data.is_object()) - return DeprecatedString::formatted("<Object with {} entr{}", data.as_object().size(), data.as_object().size() == 1 ? "y>" : "ies>"); - return data; - } - } - } - return {}; -} - -void RemoteObjectPropertyModel::set_data(const GUI::ModelIndex& index, const GUI::Variant& new_value) -{ - if (!index.is_valid()) - return; - - auto* path = static_cast<JsonPath const*>(index.internal_data()); - if (path->size() != 1) - return; - - FlatPtr address = m_object.address; - RemoteProcess::the().set_property(address, path->first().to_deprecated_string(), new_value.to_deprecated_string()); - did_update(); -} - -GUI::ModelIndex RemoteObjectPropertyModel::index(int row, int column, const GUI::ModelIndex& parent) const -{ - auto const& parent_path = parent.is_valid() ? *static_cast<JsonPath const*>(parent.internal_data()) : JsonPath {}; - - auto nth_child = [&](int n, JsonValue const& value) -> JsonPath const* { - auto path = make<JsonPath>(); - path->extend(parent_path); - int row_index = n; - if (value.is_object()) { - DeprecatedString property_name; - auto& object = value.as_object(); - object.for_each_member([&](auto& name, auto&) { - if (row_index > 0) { - --row_index; - } else if (row_index == 0) { - property_name = name; - --row_index; - } - }); - if (property_name.is_null()) - return nullptr; - - path->append({ property_name }); - m_paths.append(move(path)); - } else if (value.is_array()) { - path->append(JsonPathElement { (size_t)n }); - m_paths.append(move(path)); - } else { - return nullptr; - } - return m_paths.last(); - }; - - if (!parent.is_valid()) { - if (m_object.json.is_empty()) - return {}; - } - - auto index_path = cached_path_at(row, parent_path); - - if (!index_path) - index_path = nth_child(row, parent_path.resolve(m_object.json)); - - if (!index_path) - return {}; - - return create_index(row, column, index_path); -} - -GUI::ModelIndex RemoteObjectPropertyModel::parent_index(const GUI::ModelIndex& index) const -{ - if (!index.is_valid()) - return index; - - auto path = *static_cast<JsonPath const*>(index.internal_data()); - if (path.is_empty()) - return {}; - - path.take_last(); - if (path.is_empty()) - return {}; - - auto* cpath = find_cached_path(path); - if (cpath) { - int index_in_parent = 0; - if (cpath->last().kind() == JsonPathElement::Kind::Index) - index_in_parent = cpath->last().index(); - else if (cpath->last().kind() == JsonPathElement::Kind::Key) { - auto path_copy = path; - auto last = path_copy.take_last(); - bool found = false; - path_copy.resolve(m_object.json).as_object().for_each_member([&](auto& name, auto&) { - if (!found) { - if (last.key() == name) - found = true; - else - index_in_parent++; - } - }); - } - return create_index(index_in_parent, 0, cpath); - } - - dbgln("No cached path found for path {}", path.to_deprecated_string()); - return {}; -} - -JsonPath const* RemoteObjectPropertyModel::cached_path_at(int n, Vector<JsonPathElement> const& prefix) const -{ - // FIXME: ModelIndex wants a void*, so we have to keep these - // indices alive, but allocating a new path every time - // we're asked for an index is silly, so we have to look for existing ones first. - JsonPath const* index_path = nullptr; - int row_index = n; - for (auto& path : m_paths) { - if (path->size() != prefix.size() + 1) - continue; - - for (size_t i = 0; i < prefix.size(); ++i) { - if ((*path)[i] != prefix[i]) - goto do_continue; - } - - if (row_index == 0) { - index_path = path; - break; - } - --row_index; - do_continue:; - } - - return index_path; -}; - -JsonPath const* RemoteObjectPropertyModel::find_cached_path(Vector<JsonPathElement> const& path) const -{ - for (auto& cpath : m_paths) { - if (cpath->size() != path.size()) - continue; - - for (size_t i = 0; i < cpath->size(); ++i) { - if ((*cpath)[i] != path[i]) - goto do_continue; - } - - return cpath; - do_continue:; - } - - return nullptr; -} - -} diff --git a/Userland/DevTools/Inspector/RemoteObjectPropertyModel.h b/Userland/DevTools/Inspector/RemoteObjectPropertyModel.h deleted file mode 100644 index 15abd14893..0000000000 --- a/Userland/DevTools/Inspector/RemoteObjectPropertyModel.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <AK/JsonPath.h> -#include <AK/JsonValue.h> -#include <LibGUI/Model.h> - -namespace Inspector { - -class RemoteObject; - -class RemoteObjectPropertyModel final : public GUI::Model { -public: - virtual ~RemoteObjectPropertyModel() override { } - static NonnullRefPtr<RemoteObjectPropertyModel> create(RemoteObject& object) - { - return adopt_ref(*new RemoteObjectPropertyModel(object)); - } - - enum Column { - Name, - Value, - __Count, - }; - - virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override; - virtual int column_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override { return Column::__Count; } - virtual DeprecatedString column_name(int) const override; - virtual GUI::Variant data(const GUI::ModelIndex&, GUI::ModelRole) const override; - virtual void set_data(const GUI::ModelIndex&, const GUI::Variant&) override; - virtual bool is_editable(const GUI::ModelIndex& index) const override { return index.column() == Column::Value; } - virtual GUI::ModelIndex index(int row, int column, const GUI::ModelIndex& parent = GUI::ModelIndex()) const override; - virtual GUI::ModelIndex parent_index(const GUI::ModelIndex&) const override; - -private: - explicit RemoteObjectPropertyModel(RemoteObject&); - - JsonPath const* cached_path_at(int n, Vector<JsonPathElement> const& prefix) const; - JsonPath const* find_cached_path(Vector<JsonPathElement> const& path) const; - - RemoteObject& m_object; - mutable Vector<NonnullOwnPtr<JsonPath>> m_paths; -}; - -} diff --git a/Userland/DevTools/Inspector/RemoteProcess.cpp b/Userland/DevTools/Inspector/RemoteProcess.cpp deleted file mode 100644 index 5fb6e6dd08..0000000000 --- a/Userland/DevTools/Inspector/RemoteProcess.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "RemoteProcess.h" -#include "RemoteObject.h" -#include "RemoteObjectGraphModel.h" -#include "RemoteObjectPropertyModel.h" - -namespace Inspector { - -RemoteProcess* s_the; - -RemoteProcess& RemoteProcess::the() -{ - return *s_the; -} - -RemoteProcess::RemoteProcess(pid_t pid) - : m_pid(pid) - , m_object_graph_model(RemoteObjectGraphModel::create(*this)) -{ - s_the = this; - m_client = InspectorServerClient::try_create().release_value_but_fixme_should_propagate_errors(); -} - -void RemoteProcess::handle_identify_response(JsonObject const& response) -{ - int pid = response.get_i32("pid"sv).value_or(0); - VERIFY(pid == m_pid); - - m_process_name = response.get_deprecated_string("process_name"sv).value_or({}); - - if (on_update) - on_update(); -} - -void RemoteProcess::handle_get_all_objects_response(JsonObject const& response) -{ - // FIXME: It would be good if we didn't have to make a local copy of the array value here! - auto& object_array = response.get_array("objects"sv).value(); - - Vector<NonnullOwnPtr<RemoteObject>> remote_objects; - HashMap<FlatPtr, RemoteObject*> objects_by_address; - - for (auto& value : object_array.values()) { - VERIFY(value.is_object()); - auto& object = value.as_object(); - auto remote_object = make<RemoteObject>(); - remote_object->address = object.get_addr("address"sv).value_or(0); - remote_object->parent_address = object.get_addr("parent"sv).value_or(0); - remote_object->name = object.get_deprecated_string("name"sv).value_or({}); - remote_object->class_name = object.get_deprecated_string("class_name"sv).value_or({}); - remote_object->json = object; - objects_by_address.set(remote_object->address, remote_object); - remote_objects.append(move(remote_object)); - } - - for (size_t i = 0; i < remote_objects.size(); ++i) { - auto& remote_object = remote_objects[i]; - auto* parent = objects_by_address.get(remote_object->parent_address).value_or(nullptr); - if (!parent) { - m_roots.append(move(remote_object)); - } else { - remote_object->parent = parent; - parent->children.append(move(remote_object)); - } - } - - m_object_graph_model->invalidate(); - - if (on_update) - on_update(); -} - -void RemoteProcess::set_inspected_object(FlatPtr address) -{ - m_client->async_set_inspected_object(m_pid, address); -} - -void RemoteProcess::set_property(FlatPtr object, StringView name, JsonValue const& value) -{ - m_client->async_set_object_property(m_pid, object, name, value.to_deprecated_string()); -} - -bool RemoteProcess::is_inspectable() -{ - return m_client->is_inspectable(m_pid); -} - -void RemoteProcess::update() -{ - { - auto raw_json = m_client->identify(m_pid); - auto json = JsonValue::from_string(raw_json); - handle_identify_response(json.value().as_object()); - } - - { - auto raw_json = m_client->get_all_objects(m_pid); - auto json = JsonValue::from_string(raw_json); - handle_get_all_objects_response(json.value().as_object()); - } -} - -} diff --git a/Userland/DevTools/Inspector/RemoteProcess.h b/Userland/DevTools/Inspector/RemoteProcess.h deleted file mode 100644 index b25aea6ed7..0000000000 --- a/Userland/DevTools/Inspector/RemoteProcess.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include "InspectorServerClient.h" - -namespace Inspector { - -class RemoteObjectGraphModel; -class RemoteObject; - -class RemoteProcess { -public: - static RemoteProcess& the(); - - explicit RemoteProcess(pid_t); - void update(); - - pid_t pid() const { return m_pid; } - DeprecatedString const& process_name() const { return m_process_name; } - - RemoteObjectGraphModel& object_graph_model() { return *m_object_graph_model; } - Vector<NonnullOwnPtr<RemoteObject>> const& roots() const { return m_roots; } - - void set_inspected_object(FlatPtr); - - void set_property(FlatPtr object, StringView name, JsonValue const& value); - - bool is_inspectable(); - - Function<void()> on_update; - -private: - void handle_get_all_objects_response(JsonObject const&); - void handle_identify_response(JsonObject const&); - - pid_t m_pid { -1 }; - DeprecatedString m_process_name; - NonnullRefPtr<RemoteObjectGraphModel> m_object_graph_model; - Vector<NonnullOwnPtr<RemoteObject>> m_roots; - RefPtr<InspectorServerClient> m_client; -}; - -} diff --git a/Userland/DevTools/Inspector/main.cpp b/Userland/DevTools/Inspector/main.cpp deleted file mode 100644 index ab05551917..0000000000 --- a/Userland/DevTools/Inspector/main.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "RemoteObject.h" -#include "RemoteObjectGraphModel.h" -#include "RemoteObjectPropertyModel.h" -#include "RemoteProcess.h" -#include <AK/URL.h> -#include <LibCore/System.h> -#include <LibDesktop/Launcher.h> -#include <LibGUI/Application.h> -#include <LibGUI/BoxLayout.h> -#include <LibGUI/Clipboard.h> -#include <LibGUI/Menu.h> -#include <LibGUI/Menubar.h> -#include <LibGUI/MessageBox.h> -#include <LibGUI/ModelEditingDelegate.h> -#include <LibGUI/ProcessChooser.h> -#include <LibGUI/Splitter.h> -#include <LibGUI/TreeView.h> -#include <LibGUI/Window.h> -#include <LibMain/Main.h> -#include <stdio.h> -#include <unistd.h> - -using namespace Inspector; - -[[noreturn]] static void print_usage_and_exit() -{ - outln("usage: Inspector <pid>"); - exit(0); -} - -ErrorOr<int> serenity_main(Main::Arguments arguments) -{ - TRY(Core::System::pledge("stdio recvfd sendfd rpath unix")); - TRY(Core::System::unveil("/res", "r")); - TRY(Core::System::unveil("/bin", "r")); - TRY(Core::System::unveil("/tmp", "rwc")); - TRY(Core::System::unveil("/sys/kernel/processes", "r")); - TRY(Core::System::unveil("/etc/passwd", "r")); - TRY(Core::System::unveil(nullptr, nullptr)); - - bool gui_mode = arguments.argc != 2; - pid_t pid; - - auto app = TRY(GUI::Application::try_create(arguments)); - auto app_icon = TRY(GUI::Icon::try_create_default_icon("app-inspector"sv)); - if (gui_mode) { - choose_pid: - auto process_chooser = TRY(GUI::ProcessChooser::try_create("Inspector"sv, "Inspect"_short_string, app_icon.bitmap_for_size(16))); - if (process_chooser->exec() == GUI::Dialog::ExecResult::Cancel) - return 0; - pid = process_chooser->pid(); - } else { - auto pid_opt = DeprecatedString(arguments.strings[1]).to_int(); - if (!pid_opt.has_value()) - print_usage_and_exit(); - pid = pid_opt.value(); - } - - auto window = TRY(GUI::Window::try_create()); - - if (pid == getpid()) { - GUI::MessageBox::show(window, "Cannot inspect Inspector itself!"sv, "Error"sv, GUI::MessageBox::Type::Error); - if (gui_mode) - goto choose_pid; - else - return 1; - } - - RemoteProcess remote_process(pid); - if (!remote_process.is_inspectable()) { - GUI::MessageBox::show(window, DeprecatedString::formatted("Process pid={} is not inspectable", remote_process.pid()), "Error"sv, GUI::MessageBox::Type::Error); - if (gui_mode) { - goto choose_pid; - } else { - return 1; - } - } - - TRY(Desktop::Launcher::add_allowed_handler_with_only_specific_urls("/bin/Help", { URL::create_with_file_scheme("/usr/share/man/man1/Applications/Inspector.md") })); - TRY(Desktop::Launcher::seal_allowlist()); - - window->set_title("Inspector"); - window->resize(685, 500); - window->set_icon(app_icon.bitmap_for_size(16)); - - auto& file_menu = window->add_menu("&File"_short_string); - file_menu.add_action(GUI::CommonActions::make_quit_action([&](auto&) { app->quit(); })); - - auto& help_menu = window->add_menu("&Help"_short_string); - help_menu.add_action(GUI::CommonActions::make_command_palette_action(window)); - help_menu.add_action(GUI::CommonActions::make_help_action([](auto&) { - Desktop::Launcher::open(URL::create_with_file_scheme("/usr/share/man/man1/Applications/Inspector.md"), "/bin/Help"); - })); - help_menu.add_action(GUI::CommonActions::make_about_action("Inspector", app_icon, window)); - - auto widget = TRY(window->set_main_widget<GUI::Widget>()); - widget->set_fill_with_background_color(true); - widget->set_layout<GUI::VerticalBoxLayout>(); - - auto& splitter = widget->add<GUI::HorizontalSplitter>(); - - remote_process.on_update = [&] { - if (!remote_process.process_name().is_null()) - window->set_title(DeprecatedString::formatted("{} ({}) - Inspector", remote_process.process_name(), remote_process.pid())); - }; - - auto& tree_view = splitter.add<GUI::TreeView>(); - tree_view.set_model(remote_process.object_graph_model()); - tree_view.set_activates_on_selection(true); - tree_view.set_preferred_width(286); - - auto& properties_tree_view = splitter.add<GUI::TreeView>(); - properties_tree_view.set_should_fill_selected_rows(true); - properties_tree_view.set_editable(true); - properties_tree_view.aid_create_editing_delegate = [](auto&) { - return make<GUI::StringModelEditingDelegate>(); - }; - - tree_view.on_activation = [&](auto& index) { - auto* remote_object = static_cast<RemoteObject*>(index.internal_data()); - properties_tree_view.set_model(remote_object->property_model()); - remote_process.set_inspected_object(remote_object->address); - }; - - auto properties_tree_view_context_menu = TRY(GUI::Menu::try_create(TRY("Properties Tree View"_string))); - - auto copy_bitmap = Gfx::Bitmap::load_from_file("/res/icons/16x16/edit-copy.png"sv).release_value_but_fixme_should_propagate_errors(); - auto copy_property_name_action = GUI::Action::create("Copy Property Name", copy_bitmap, [&](auto&) { - GUI::Clipboard::the().set_plain_text(properties_tree_view.selection().first().data().to_deprecated_string()); - }); - auto copy_property_value_action = GUI::Action::create("Copy Property Value", copy_bitmap, [&](auto&) { - GUI::Clipboard::the().set_plain_text(properties_tree_view.selection().first().sibling_at_column(1).data().to_deprecated_string()); - }); - - properties_tree_view_context_menu->add_action(copy_property_name_action); - properties_tree_view_context_menu->add_action(copy_property_value_action); - - properties_tree_view.on_context_menu_request = [&](const GUI::ModelIndex& index, const GUI::ContextMenuEvent& event) { - if (index.is_valid()) { - properties_tree_view_context_menu->popup(event.screen_position()); - } - }; - - window->show(); - remote_process.update(); - - TRY(Core::System::pledge("stdio recvfd sendfd rpath")); - return app->exec(); -} |