Serenity Operating System
1/*
2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
3 * Copyright (c) 2022, the SerenityOS developers.
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#include <AK/Assertions.h>
9#include <AK/Badge.h>
10#include <AK/JsonObject.h>
11#include <LibCore/Event.h>
12#include <LibCore/EventLoop.h>
13#include <LibCore/Object.h>
14#include <stdio.h>
15
16namespace Core {
17
18IntrusiveList<&Object::m_all_objects_list_node>& Object::all_objects()
19{
20 static IntrusiveList<&Object::m_all_objects_list_node> objects;
21 return objects;
22}
23
24Object::Object(Object* parent)
25 : m_parent(parent)
26{
27 all_objects().append(*this);
28 if (m_parent)
29 m_parent->add_child(*this);
30
31 REGISTER_READONLY_STRING_PROPERTY("class_name", class_name);
32 REGISTER_STRING_PROPERTY("name", name, set_name);
33
34 register_property(
35 "address", [this] { return FlatPtr(this); },
36 [](auto&) { return false; });
37
38 register_property(
39 "parent", [this] { return FlatPtr(this->parent()); },
40 [](auto&) { return false; });
41}
42
43Object::~Object()
44{
45 // NOTE: We move our children out to a stack vector to prevent other
46 // code from trying to iterate over them.
47 auto children = move(m_children);
48 // NOTE: We also unparent the children, so that they won't try to unparent
49 // themselves in their own destructors.
50 for (auto& child : children)
51 child->m_parent = nullptr;
52
53 all_objects().remove(*this);
54 stop_timer();
55 if (m_parent)
56 m_parent->remove_child(*this);
57}
58
59void Object::event(Core::Event& event)
60{
61 switch (event.type()) {
62 case Core::Event::Timer:
63 return timer_event(static_cast<TimerEvent&>(event));
64 case Core::Event::ChildAdded:
65 case Core::Event::ChildRemoved:
66 return child_event(static_cast<ChildEvent&>(event));
67 case Core::Event::Invalid:
68 VERIFY_NOT_REACHED();
69 break;
70 case Core::Event::Custom:
71 return custom_event(static_cast<CustomEvent&>(event));
72 default:
73 break;
74 }
75}
76
77ErrorOr<void> Object::try_add_child(Object& object)
78{
79 // FIXME: Should we support reparenting objects?
80 VERIFY(!object.parent() || object.parent() == this);
81 TRY(m_children.try_append(object));
82 object.m_parent = this;
83 Core::ChildEvent child_event(Core::Event::ChildAdded, object);
84 event(child_event);
85 return {};
86}
87
88void Object::add_child(Object& object)
89{
90 MUST(try_add_child(object));
91}
92
93void Object::insert_child_before(Object& new_child, Object& before_child)
94{
95 // FIXME: Should we support reparenting objects?
96 VERIFY(!new_child.parent() || new_child.parent() == this);
97 new_child.m_parent = this;
98 m_children.insert_before_matching(new_child, [&](auto& existing_child) { return existing_child.ptr() == &before_child; });
99 Core::ChildEvent child_event(Core::Event::ChildAdded, new_child, &before_child);
100 event(child_event);
101}
102
103void Object::remove_child(Object& object)
104{
105 for (size_t i = 0; i < m_children.size(); ++i) {
106 if (m_children[i] == &object) {
107 // NOTE: We protect the child so it survives the handling of ChildRemoved.
108 NonnullRefPtr<Object> protector = object;
109 object.m_parent = nullptr;
110 m_children.remove(i);
111 Core::ChildEvent child_event(Core::Event::ChildRemoved, object);
112 event(child_event);
113 return;
114 }
115 }
116 VERIFY_NOT_REACHED();
117}
118
119void Object::remove_all_children()
120{
121 while (!m_children.is_empty())
122 m_children.first()->remove_from_parent();
123}
124
125void Object::timer_event(Core::TimerEvent&)
126{
127}
128
129void Object::child_event(Core::ChildEvent&)
130{
131}
132
133void Object::custom_event(CustomEvent&)
134{
135}
136
137void Object::start_timer(int ms, TimerShouldFireWhenNotVisible fire_when_not_visible)
138{
139 if (m_timer_id) {
140 dbgln("{} {:p} already has a timer!", class_name(), this);
141 VERIFY_NOT_REACHED();
142 }
143
144 m_timer_id = Core::EventLoop::register_timer(*this, ms, true, fire_when_not_visible);
145}
146
147void Object::stop_timer()
148{
149 if (!m_timer_id)
150 return;
151 bool success = Core::EventLoop::unregister_timer(m_timer_id);
152 VERIFY(success);
153 m_timer_id = 0;
154}
155
156void Object::dump_tree(int indent)
157{
158 for (int i = 0; i < indent; ++i) {
159 out(" ");
160 }
161 out("{}{{{:p}}}", class_name(), this);
162 if (!name().is_null())
163 out(" {}", name());
164 outln();
165
166 for_each_child([&](auto& child) {
167 child.dump_tree(indent + 2);
168 return IterationDecision::Continue;
169 });
170}
171
172void Object::deferred_invoke(Function<void()> invokee)
173{
174 Core::deferred_invoke([invokee = move(invokee), strong_this = NonnullRefPtr(*this)] { invokee(); });
175}
176
177void Object::save_to(JsonObject& json)
178{
179 for (auto& it : m_properties) {
180 auto& property = it.value;
181 json.set(property->name(), property->get());
182 }
183}
184
185JsonValue Object::property(DeprecatedString const& name) const
186{
187 auto it = m_properties.find(name);
188 if (it == m_properties.end())
189 return JsonValue();
190 return it->value->get();
191}
192
193bool Object::set_property(DeprecatedString const& name, JsonValue const& value)
194{
195 auto it = m_properties.find(name);
196 if (it == m_properties.end())
197 return false;
198 return it->value->set(value);
199}
200
201bool Object::is_ancestor_of(Object const& other) const
202{
203 if (&other == this)
204 return false;
205 for (auto* ancestor = other.parent(); ancestor; ancestor = ancestor->parent()) {
206 if (ancestor == this)
207 return true;
208 }
209 return false;
210}
211
212void Object::dispatch_event(Core::Event& e, Object* stay_within)
213{
214 VERIFY(!stay_within || stay_within == this || stay_within->is_ancestor_of(*this));
215 auto* target = this;
216 do {
217 // If there's an event filter on this target, ask if it wants to swallow this event.
218 if (target->m_event_filter && !target->m_event_filter(e))
219 return;
220 target->event(e);
221 target = target->parent();
222 if (target == stay_within) {
223 // Prevent the event from bubbling any further.
224 return;
225 }
226 } while (target && !e.is_accepted());
227}
228
229bool Object::is_visible_for_timer_purposes() const
230{
231 if (parent())
232 return parent()->is_visible_for_timer_purposes();
233 return true;
234}
235
236void Object::increment_inspector_count(Badge<InspectorServerConnection>)
237{
238 ++m_inspector_count;
239 if (m_inspector_count == 1)
240 did_begin_inspection();
241}
242
243void Object::decrement_inspector_count(Badge<InspectorServerConnection>)
244{
245 --m_inspector_count;
246 if (!m_inspector_count)
247 did_end_inspection();
248}
249
250void Object::register_property(DeprecatedString const& name, Function<JsonValue()> getter, Function<bool(JsonValue const&)> setter)
251{
252 m_properties.set(name, make<Property>(name, move(getter), move(setter)));
253}
254
255void Object::set_event_filter(Function<bool(Core::Event&)> filter)
256{
257 m_event_filter = move(filter);
258}
259
260static HashMap<StringView, ObjectClassRegistration*>& object_classes()
261{
262 static HashMap<StringView, ObjectClassRegistration*> s_map;
263 return s_map;
264}
265
266ObjectClassRegistration::ObjectClassRegistration(StringView class_name, Function<ErrorOr<NonnullRefPtr<Object>>()> factory, ObjectClassRegistration* parent_class)
267 : m_class_name(class_name)
268 , m_factory(move(factory))
269 , m_parent_class(parent_class)
270{
271 object_classes().set(class_name, this);
272}
273
274bool ObjectClassRegistration::is_derived_from(ObjectClassRegistration const& base_class) const
275{
276 if (&base_class == this)
277 return true;
278 if (!m_parent_class)
279 return false;
280 return m_parent_class->is_derived_from(base_class);
281}
282
283void ObjectClassRegistration::for_each(Function<void(ObjectClassRegistration const&)> callback)
284{
285 for (auto& it : object_classes()) {
286 callback(*it.value);
287 }
288}
289
290ObjectClassRegistration const* ObjectClassRegistration::find(StringView class_name)
291{
292 return object_classes().get(class_name).value_or(nullptr);
293}
294}