1 /*
2  * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/base/inspector.h"
17 
18 #include <unistd.h>
19 #include <unordered_set>
20 
21 #include "base/memory/ace_type.h"
22 #include "base/utils/utils.h"
23 #include "core/common/ace_application_info.h"
24 #include "core/common/recorder/event_recorder.h"
25 #include "core/components_ng/base/inspector_filter.h"
26 #include "core/components_ng/base/ui_node.h"
27 #include "core/components_ng/pattern/custom/custom_node.h"
28 #include "core/components_ng/pattern/stage/page_info.h"
29 #include "core/components_ng/pattern/stage/page_pattern.h"
30 #include "core/components_ng/pattern/text/span_node.h"
31 #include "core/components_ng/render/render_context.h"
32 #include "core/components_v2/inspector/inspector_constants.h"
33 #include "core/event/touch_event.h"
34 #include "core/pipeline_ng/pipeline_context.h"
35 #include "frameworks/base/memory/type_info_base.h"
36 #include "foundation/arkui/ace_engine/frameworks/base/utils/utf.h"
37 
38 namespace OHOS::Ace::NG {
39 namespace {
40 const char INSPECTOR_TYPE[] = "$type";
41 const char INSPECTOR_ID[] = "$ID";
42 const char INSPECTOR_RECT[] = "$rect";
43 const char INSPECTOR_ATTRS[] = "$attrs";
44 const char INSPECTOR_ROOT[] = "root";
45 const char INSPECTOR_PAGE_URL[] = "pageUrl";
46 const char INSPECTOR_NAV_DST_NAME[] = "navDstName";
47 const char INSPECTOR_WIDTH[] = "width";
48 const char INSPECTOR_HEIGHT[] = "height";
49 const char INSPECTOR_RESOLUTION[] = "$resolution";
50 const char INSPECTOR_CHILDREN[] = "$children";
51 const char INSPECTOR_DEBUGLINE[] = "$debugLine";
52 #ifdef PREVIEW
53 const char INSPECTOR_VIEW_ID[] = "$viewID";
54 #else
55 const char INSPECTOR_CUSTOM_VIEW_TAG[] = "viewTag";
56 const char INSPECTOR_COMPONENT_TYPE[] = "type";
57 const char INSPECTOR_STATE_VAR[] = "state";
58 #endif
59 const char INSPECTOR_ATTR_ID[] = "id";
60 const char INSPECTOR_LABEL[] = "label";
61 const char INSPECTOR_CONTENT[] = "content";
62 const char INSPECTOR_ENABLED[] = "enabled";
63 const char INSPECTOR_OPACITY[] = "opacity";
64 const char INSPECTOR_ZINDEX[] = "zindex";
65 const char INSPECTOR_VISIBILITY[] = "visibility";
66 
67 
68 const uint32_t LONG_PRESS_DELAY = 1000;
69 RectF deviceRect;
70 
GetInspectorByKey(const RefPtr<FrameNode> & root,const std::string & key,bool notDetach=false)71 RefPtr<UINode> GetInspectorByKey(const RefPtr<FrameNode>& root, const std::string& key, bool notDetach = false)
72 {
73     std::queue<RefPtr<UINode>> elements;
74     elements.push(root);
75     RefPtr<UINode> inspectorElement;
76     while (!elements.empty()) {
77         auto current = elements.front();
78         elements.pop();
79         if (key == current->GetInspectorId().value_or("")) {
80             return current;
81         }
82 
83         const auto& children = current->GetChildren(notDetach);
84         for (const auto& child : children) {
85             elements.push(child);
86         }
87     }
88     return nullptr;
89 }
90 
DumpElementTree(int32_t depth,const RefPtr<UINode> & element,std::map<int32_t,std::list<RefPtr<UINode>>> & depthElementMap)91 void DumpElementTree(
92     int32_t depth, const RefPtr<UINode>& element, std::map<int32_t, std::list<RefPtr<UINode>>>& depthElementMap)
93 {
94     if (element->GetChildren().empty()) {
95         return;
96     }
97     const auto& children = element->GetChildren();
98     depthElementMap[depth].insert(depthElementMap[depth].end(), children.begin(), children.end());
99     for (const auto& depthElement : children) {
100         DumpElementTree(depth + 1, depthElement, depthElementMap);
101     }
102 }
103 
GetUpPoint(const TouchEvent & downPoint)104 TouchEvent GetUpPoint(const TouchEvent& downPoint)
105 {
106     return TouchEvent {}
107         .SetX(downPoint.x)
108         .SetY(downPoint.y)
109         .SetType(TouchType::UP)
110         .SetTime(std::chrono::high_resolution_clock::now())
111         .SetSourceType(SourceType::TOUCH);
112 }
113 #ifdef PREVIEW
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<RefPtr<NG::UINode>> & children,int32_t pageId,bool isLayoutInspector=false)114 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::vector<RefPtr<NG::UINode>>& children, int32_t pageId,
115     bool isLayoutInspector = false)
116 {
117     // Set ViewId for the fast preview.
118     auto parent = uiNode->GetParent();
119     if (parent && parent->GetTag() == "JsView") {
120         uiNode->SetViewId(std::to_string(parent->GetId()));
121     } else {
122         uiNode->SetViewId(parent->GetViewId());
123     }
124     if (uiNode->GetTag() == "stage") {
125     } else if (uiNode->GetTag() == "page") {
126         if (uiNode->GetPageId() != pageId) {
127             return;
128         }
129     } else {
130         if (!uiNode->GetDebugLine().empty()) {
131             children.emplace_back(uiNode);
132             return;
133         }
134     }
135 
136     for (const auto& frameChild : uiNode->GetChildren()) {
137         GetFrameNodeChildren(frameChild, children, pageId);
138     }
139 }
140 
GetSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId)141 void GetSpanInspector(
142     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId)
143 {
144     // span rect follows parent text size
145     auto spanParentNode = parent->GetParent();
146     while (spanParentNode != nullptr) {
147         if (AceType::InstanceOf<NG::FrameNode>(spanParentNode)) {
148             break;
149         }
150         spanParentNode = spanParentNode->GetParent();
151     }
152     CHECK_NULL_VOID(spanParentNode);
153     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
154     auto jsonNode = JsonUtil::Create(true);
155     auto jsonObject = JsonUtil::Create(true);
156 
157     InspectorFilter filter;
158     parent->ToJsonValue(jsonObject, filter);
159     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
160     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
161     jsonNode->Put(INSPECTOR_ID, parent->GetId());
162     RectF rect = node->GetTransformRectRelativeToWindow();
163     rect = rect.Constrain(deviceRect);
164     if (rect.IsEmpty()) {
165         rect.SetRect(0, 0, 0, 0);
166     }
167     auto strRec = std::to_string(rect.Left())
168                       .append(",")
169                       .append(std::to_string(rect.Top()))
170                       .append(",")
171                       .append(std::to_string(rect.Width()))
172                       .append(",")
173                       .append(std::to_string(rect.Height()));
174     jsonNode->Put(INSPECTOR_RECT, strRec.c_str());
175     jsonNode->Put(INSPECTOR_DEBUGLINE, parent->GetDebugLine().c_str());
176     jsonNode->Put(INSPECTOR_VIEW_ID, parent->GetViewId().c_str());
177     jsonNodeArray->PutRef(std::move(jsonNode));
178 }
179 
GetInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId,bool isActive,const InspectorFilter & filter=InspectorFilter (),uint32_t depth=UINT32_MAX,bool isLayoutInspector=false)180 void GetInspectorChildren(const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray,
181     int pageId, bool isActive, const InspectorFilter& filter = InspectorFilter(), uint32_t depth = UINT32_MAX,
182     bool isLayoutInspector = false)
183 {
184     // Span is a special case in Inspector since span inherits from UINode
185     if (AceType::InstanceOf<SpanNode>(parent)) {
186         GetSpanInspector(parent, jsonNodeArray, pageId);
187         return;
188     }
189     auto jsonNode = JsonUtil::Create(true);
190     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
191     jsonNode->Put(INSPECTOR_ID, parent->GetId());
192     auto node = AceType::DynamicCast<FrameNode>(parent);
193     if (node) {
194         RectF rect;
195         isActive = isActive && node->IsActive();
196         if (isActive) {
197             rect = node->GetTransformRectRelativeToWindow();
198         }
199         rect = rect.Constrain(deviceRect);
200         if (rect.IsEmpty()) {
201             rect.SetRect(0, 0, 0, 0);
202         }
203         auto strRec = std::to_string(rect.Left()).append(",")
204                           .append(std::to_string(rect.Top())).append(",")
205                           .append(std::to_string(rect.Width())).append(",")
206                           .append(std::to_string(rect.Height()));
207         jsonNode->Put(INSPECTOR_RECT, strRec.c_str());
208         jsonNode->Put(INSPECTOR_DEBUGLINE, node->GetDebugLine().c_str());
209         jsonNode->Put(INSPECTOR_VIEW_ID, node->GetViewId().c_str());
210         auto jsonObject = JsonUtil::Create(true);
211 
212         InspectorFilter filter;
213         parent->ToJsonValue(jsonObject, filter);
214         jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
215     }
216 
217     std::vector<RefPtr<NG::UINode>> children;
218     for (const auto& item : parent->GetChildren()) {
219         GetFrameNodeChildren(item, children, pageId);
220     }
221     if (node != nullptr) {
222         auto overlayNode = node->GetOverlayNode();
223         if (overlayNode != nullptr) {
224             GetFrameNodeChildren(overlayNode, children, pageId);
225         }
226     }
227     if (depth) {
228         auto jsonChildrenArray = JsonUtil::CreateArray(true);
229         for (auto uiNode : children) {
230             GetInspectorChildren(uiNode, jsonChildrenArray, pageId, isActive, filter, depth - 1);
231         }
232         if (jsonChildrenArray->GetArraySize()) {
233             jsonNode->PutRef(INSPECTOR_CHILDREN, std::move(jsonChildrenArray));
234         }
235     }
236     jsonNodeArray->PutRef(std::move(jsonNode));
237 }
238 
239 #else
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<RefPtr<NG::UINode>> & children,int32_t pageId,bool isLayoutInspector=false)240 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::vector<RefPtr<NG::UINode>>& children,
241     int32_t pageId, bool isLayoutInspector = false)
242 {
243     if (AceType::InstanceOf<NG::FrameNode>(uiNode) || AceType::InstanceOf<SpanNode>(uiNode) ||
244         AceType::InstanceOf<CustomNode>(uiNode)) {
245         if (uiNode->GetTag() == "stage") {
246         } else if (uiNode->GetTag() == "page") {
247             if (uiNode->GetPageId() != pageId) {
248                 return;
249             }
250         } else {
251             auto custom = AceType::DynamicCast<NG::CustomNode>(uiNode);
252             auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
253             auto spanNode = AceType::DynamicCast<NG::SpanNode>(uiNode);
254             if ((frameNode && !frameNode->IsInternal()) || spanNode || (custom && isLayoutInspector)) {
255                 children.emplace_back(uiNode);
256                 return;
257             }
258         }
259     }
260     for (const auto& frameChild : uiNode->GetChildren()) {
261         GetFrameNodeChildren(frameChild, children, pageId, isLayoutInspector);
262     }
263 }
264 
GetSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId)265 void GetSpanInspector(
266     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId)
267 {
268     // span rect follows parent text size
269     auto spanParentNode = parent->GetParent();
270     while (spanParentNode != nullptr) {
271         if (AceType::InstanceOf<NG::FrameNode>(spanParentNode)) {
272             break;
273         }
274         spanParentNode = spanParentNode->GetParent();
275     }
276     CHECK_NULL_VOID(spanParentNode);
277     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
278     auto jsonNode = JsonUtil::Create(true);
279     auto jsonObject = JsonUtil::Create(true);
280 
281     InspectorFilter filter;
282     parent->ToJsonValue(jsonObject, filter);
283     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
284     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
285     jsonNode->Put(INSPECTOR_ID, parent->GetId());
286     jsonNode->Put(INSPECTOR_DEBUGLINE, parent->GetDebugLine().c_str());
287     RectF rect = node->GetTransformRectRelativeToWindow();
288     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
289     jsonNodeArray->PutRef(std::move(jsonNode));
290 }
291 
GetCustomNodeInfo(const RefPtr<NG::UINode> & customNode,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNode)292 void GetCustomNodeInfo(const RefPtr<NG::UINode> &customNode, std::unique_ptr<OHOS::Ace::JsonValue> &jsonNode)
293 {
294     // custom node rect follows parent size
295     auto hostNode = customNode->GetParent();
296     while (hostNode != nullptr) {
297         if (AceType::InstanceOf<NG::FrameNode>(hostNode)) {
298             break;
299         }
300         hostNode = hostNode->GetParent();
301     }
302     CHECK_NULL_VOID(hostNode);
303     jsonNode->Put(INSPECTOR_COMPONENT_TYPE, "custom");
304     auto node = AceType::DynamicCast<CustomNode>(customNode);
305     CHECK_NULL_VOID(node);
306     auto parentNode = AceType::DynamicCast<FrameNode>(hostNode);
307     jsonNode->Put(INSPECTOR_STATE_VAR, node->GetStateInspectorInfo());
308     RectF rect = parentNode->GetTransformRectRelativeToWindow();
309     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
310     jsonNode->Put(INSPECTOR_DEBUGLINE, customNode->GetDebugLine().c_str());
311     jsonNode->Put(INSPECTOR_CUSTOM_VIEW_TAG, node->GetCustomTag().c_str());
312 }
313 
GetInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId,bool isActive,const InspectorFilter & filter=InspectorFilter (),uint32_t depth=UINT32_MAX,bool isLayoutInspector=false)314 void GetInspectorChildren(const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray,
315     int pageId, bool isActive, const InspectorFilter& filter = InspectorFilter(), uint32_t depth = UINT32_MAX,
316     bool isLayoutInspector = false)
317 {
318     // Span is a special case in Inspector since span inherits from UINode
319     if (AceType::InstanceOf<SpanNode>(parent)) {
320         GetSpanInspector(parent, jsonNodeArray, pageId);
321         return;
322     }
323     if (AceType::InstanceOf<CustomNode>(parent) && !isLayoutInspector) {
324         return;
325     }
326     auto jsonNode = JsonUtil::Create(true);
327     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
328     jsonNode->Put(INSPECTOR_ID, parent->GetId());
329     if (parent->GetTag() == V2::JS_VIEW_ETS_TAG) {
330         GetCustomNodeInfo(parent, jsonNode);
331     } else {
332         jsonNode->Put(INSPECTOR_COMPONENT_TYPE, "build-in");
333     }
334     auto node = AceType::DynamicCast<FrameNode>(parent);
335     if (node) {
336         RectF rect;
337         isActive = isActive && node->IsActive();
338         if (isActive) {
339             rect = node->GetTransformRectRelativeToWindow();
340         }
341         jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
342         jsonNode->Put(INSPECTOR_DEBUGLINE, node->GetDebugLine().c_str());
343     }
344     auto jsonObject = JsonUtil::Create(true);
345     parent->ToJsonValue(jsonObject, filter);
346     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
347     std::string jsonNodeStr = jsonNode->ToString();
348     ConvertIllegalStr(jsonNodeStr);
349     auto jsonNodeNew = JsonUtil::ParseJsonString(jsonNodeStr);
350     std::vector<RefPtr<NG::UINode>> children;
351     for (const auto& item : parent->GetChildren()) {
352         GetFrameNodeChildren(item, children, pageId, isLayoutInspector);
353     }
354     if (node) {
355         auto overlayNode = node->GetOverlayNode();
356         if (overlayNode != nullptr) {
357             GetFrameNodeChildren(overlayNode, children, pageId, isLayoutInspector);
358         }
359     }
360     if (depth) {
361         auto jsonChildrenArray = JsonUtil::CreateArray(true);
362         for (auto uiNode : children) {
363             GetInspectorChildren(uiNode, jsonChildrenArray, pageId, isActive, filter, depth - 1, isLayoutInspector);
364         }
365         if (jsonChildrenArray->GetArraySize()) {
366             jsonNodeNew->PutRef(INSPECTOR_CHILDREN, std::move(jsonChildrenArray));
367         }
368     }
369     jsonNodeArray->PutRef(std::move(jsonNodeNew));
370 }
371 #endif
372 
GetOverlayNode(const RefPtr<NG::UINode> & pageNode)373 RefPtr<NG::UINode> GetOverlayNode(const RefPtr<NG::UINode>& pageNode)
374 {
375     CHECK_NULL_RETURN(pageNode, nullptr);
376     auto stageNode = pageNode->GetParent();
377     CHECK_NULL_RETURN(stageNode, nullptr);
378     auto stageParent = stageNode->GetParent();
379     CHECK_NULL_RETURN(stageParent, nullptr);
380     auto overlayNode = stageParent->GetChildren().back();
381     if (overlayNode->GetTag() == "stage") {
382         return nullptr;
383     }
384     return overlayNode;
385 }
386 
GetContextInfo(const RefPtr<PipelineContext> & context,std::unique_ptr<JsonValue> & jsonRoot)387 void GetContextInfo(const RefPtr<PipelineContext>& context, std::unique_ptr<JsonValue>& jsonRoot)
388 {
389     auto scale = context->GetViewScale();
390     auto rootHeight = context->GetRootHeight();
391     auto rootWidth = context->GetRootWidth();
392     deviceRect.SetRect(0, 0, rootWidth * scale, rootHeight * scale);
393     jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
394     jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
395     jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(PipelineBase::GetCurrentDensity()).c_str());
396 }
397 
GetInspectorInfo(std::vector<RefPtr<NG::UINode>> children,int32_t pageId,std::unique_ptr<JsonValue> jsonRoot,bool isLayoutInspector,const InspectorFilter & filter=InspectorFilter ())398 std::string GetInspectorInfo(std::vector<RefPtr<NG::UINode>> children, int32_t pageId,
399     std::unique_ptr<JsonValue> jsonRoot, bool isLayoutInspector, const InspectorFilter& filter = InspectorFilter())
400 {
401     auto jsonNodeArray = JsonUtil::CreateArray(true);
402     auto depth = filter.GetFilterDepth();
403     for (auto& uiNode : children) {
404         GetInspectorChildren(uiNode, jsonNodeArray, pageId, true, filter, depth - 1, isLayoutInspector);
405     }
406     if (jsonNodeArray->GetArraySize()) {
407         jsonRoot->PutRef(INSPECTOR_CHILDREN, std::move(jsonNodeArray));
408     }
409 
410     if (isLayoutInspector) {
411         auto jsonTree = JsonUtil::Create(true);
412         jsonTree->Put("type", "root");
413         jsonTree->PutRef("content", std::move(jsonRoot));
414         auto pipeline = PipelineContext::GetCurrentContextSafely();
415         if (pipeline) {
416             jsonTree->Put("VsyncID", (int32_t)pipeline->GetFrameCount());
417             jsonTree->Put("ProcessID", getpid());
418             jsonTree->Put("WindowID", (int32_t)pipeline->GetWindowId());
419         }
420         return jsonTree->ToString();
421     }
422 
423     return jsonRoot->ToString();
424 }
425 } // namespace
426 
427 std::set<RefPtr<FrameNode>> Inspector::offscreenNodes;
428 
GetFrameNodeByKey(const std::string & key,bool notDetach)429 RefPtr<FrameNode> Inspector::GetFrameNodeByKey(const std::string& key, bool notDetach)
430 {
431     if (!offscreenNodes.empty()) {
432         for (auto node : offscreenNodes) {
433             auto frameNode = AceType::DynamicCast<FrameNode>(GetInspectorByKey(node, key, notDetach));
434             if (frameNode) {
435                 return frameNode;
436             }
437         }
438     }
439     auto context = NG::PipelineContext::GetCurrentContext();
440     if (!context) {
441         LOGW("Internal error! Context is null. key: %{public}s", key.c_str());
442         return nullptr;
443     }
444     auto rootNode = context->GetRootElement();
445     if (!rootNode) {
446         LOGW("Internal error! RootNode is null. key: %{public}s", key.c_str());
447         return nullptr;
448     }
449 
450     return AceType::DynamicCast<FrameNode>(GetInspectorByKey(rootNode, key, notDetach));
451 }
452 
GetInspectorNodeByKey(const std::string & key,const InspectorFilter & filter)453 std::string Inspector::GetInspectorNodeByKey(const std::string& key, const InspectorFilter& filter)
454 {
455     auto context = NG::PipelineContext::GetCurrentContext();
456     CHECK_NULL_RETURN(context, "");
457     auto rootNode = context->GetRootElement();
458     CHECK_NULL_RETURN(rootNode, "");
459 
460     auto inspectorElement = GetInspectorByKey(rootNode, key);
461     CHECK_NULL_RETURN(inspectorElement, "");
462 
463     auto jsonNode = JsonUtil::Create(true);
464     jsonNode->Put(INSPECTOR_TYPE, inspectorElement->GetTag().c_str());
465     jsonNode->Put(INSPECTOR_ID, inspectorElement->GetId());
466     auto frameNode = AceType::DynamicCast<FrameNode>(inspectorElement);
467     if (frameNode) {
468         auto rect = frameNode->GetTransformRectRelativeToWindow();
469         jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
470     }
471     auto jsonAttrs = JsonUtil::Create(true);
472     std::string debugLine = inspectorElement->GetDebugLine();
473     jsonNode->Put(INSPECTOR_DEBUGLINE, debugLine.c_str());
474 
475     inspectorElement->ToJsonValue(jsonAttrs, filter);
476     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonAttrs));
477     return jsonNode->ToString();
478 }
479 
GetRectangleById(const std::string & key,Rectangle & rectangle)480 void Inspector::GetRectangleById(const std::string& key, Rectangle& rectangle)
481 {
482     auto frameNode = Inspector::GetFrameNodeByKey(key, true);
483     if (!frameNode) {
484         LOGW("Can't find component:%{public}s, check your parameters", key.c_str());
485         return;
486     }
487     rectangle.size = frameNode->GetGeometryNode()->GetFrameSize();
488     auto context = frameNode->GetRenderContext();
489     if (!context) {
490         LOGW("Internal error! Component(id=%{public}s) is null", key.c_str());
491         return;
492     }
493     rectangle.localOffset = context->GetPaintRectWithTransform().GetOffset();
494     rectangle.windowOffset = frameNode->GetOffsetRelativeToWindow();
495     auto pipeline = frameNode->GetContext();
496     CHECK_NULL_VOID(pipeline);
497     rectangle.screenRect = pipeline->GetCurrentWindowRect();
498     ACE_SCOPED_TRACE("Inspector::GetRectangleById_Id=%d_Tag=%s_Key=%s",
499         frameNode->GetId(), frameNode->GetTag().c_str(), key.c_str());
500     LOGI("GetRectangleById Id:%{public}d key:%{public}s tag:%{public}s localOffset:%{public}s"
501          " windowOffset:%{public}s screenRect:%{public}s",
502         frameNode->GetId(), key.c_str(), frameNode->GetTag().c_str(), rectangle.localOffset.ToString().c_str(),
503         rectangle.windowOffset.ToString().c_str(), rectangle.screenRect.ToString().c_str());
504     auto renderContext = frameNode->GetRenderContext();
505     CHECK_NULL_VOID(renderContext);
506     Matrix4 defMatrix4 = Matrix4::CreateIdentity();
507     Matrix4 matrix4 = renderContext->GetTransformMatrixValue(defMatrix4);
508     rectangle.matrix4 = matrix4;
509     auto rect = renderContext->GetPaintRectWithoutTransform();
510     const double halfDimension = 50.0;
511     auto center = renderContext->GetTransformCenter().value_or(DimensionOffset(
512         Dimension(halfDimension, DimensionUnit::PERCENT), Dimension(halfDimension, DimensionUnit::PERCENT)));
513     double centerX = 0.0;
514     double centerY = 0.0;
515     if (center.GetX().Unit() == DimensionUnit::PERCENT || center.GetY().Unit() == DimensionUnit::PERCENT) {
516         if (rect.IsValid()) {
517             centerX = Dimension(center.GetX().ConvertToPxWithSize(rect.Width()), DimensionUnit::PX).ConvertToVp();
518             centerY = Dimension(center.GetY().ConvertToPxWithSize(rect.Height()), DimensionUnit::PX).ConvertToVp();
519         }
520     } else {
521         centerX = center.GetX().ConvertToVp();
522         centerY = center.GetY().ConvertToVp();
523     }
524     VectorF defScale = VectorF(1.0, 1.0);
525     VectorF scale = renderContext->GetTransformScaleValue(defScale);
526     rectangle.scale.x = scale.x;
527     rectangle.scale.y = scale.y;
528     rectangle.scale.z = 1.0;
529     rectangle.scale.centerX = centerX;
530     rectangle.scale.centerY = centerY;
531     Vector5F defRotate = Vector5F(0.0, 0.0, 0.0, 0.0, 0.0);
532     Vector5F rotate = renderContext->GetTransformRotateValue(defRotate);
533     rectangle.rotate.x = rotate.x;
534     rectangle.rotate.y = rotate.y;
535     rectangle.rotate.z = rotate.z;
536     rectangle.rotate.angle = rotate.w;
537     rectangle.rotate.centerX = centerX;
538     rectangle.rotate.centerY = centerY;
539     TranslateOptions defTranslate = TranslateOptions(0.0, 0.0, 0.0);
540     TranslateOptions translate = renderContext->GetTransformTranslateValue(defTranslate);
541     if ((translate.x.Unit() == DimensionUnit::PERCENT) && rect.IsValid()) {
542         rectangle.translate.x =
543             Dimension(translate.x.ConvertToPxWithSize(rect.Width()), DimensionUnit::PX).ConvertToVp();
544     } else {
545         rectangle.translate.x = translate.x.ConvertToVp();
546     }
547     if ((translate.y.Unit() == DimensionUnit::PERCENT) && rect.IsValid()) {
548         rectangle.translate.y =
549             Dimension(translate.y.ConvertToPxWithSize(rect.Height()), DimensionUnit::PX).ConvertToVp();
550     } else {
551         rectangle.translate.y = translate.y.ConvertToVp();
552     }
553     rectangle.translate.z = translate.z.ConvertToVp();
554 }
555 
GetInspector(bool isLayoutInspector)556 std::string Inspector::GetInspector(bool isLayoutInspector)
557 {
558     InspectorFilter filter;
559     bool needThrow = false;
560     return GetInspector(isLayoutInspector, filter, needThrow);
561 }
562 
GetInspector(bool isLayoutInspector,const InspectorFilter & filter,bool & needThrow)563 std::string Inspector::GetInspector(bool isLayoutInspector, const InspectorFilter& filter, bool& needThrow)
564 {
565     auto jsonRoot = JsonUtil::Create(true);
566     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
567     needThrow = false;
568     auto context = NG::PipelineContext::GetCurrentContext();
569     if (context == nullptr) {
570         needThrow = true;
571         return jsonRoot->ToString();
572     }
573     GetContextInfo(context, jsonRoot);
574 
575     RefPtr<UINode> pageRootNode;
576     const std::string key = filter.GetFilterID();
577     if (key.empty()) {
578         pageRootNode = context->GetStageManager()->GetLastPage();
579     } else {
580         auto rootNode = context->GetStageManager()->GetLastPage();
581         if (rootNode == nullptr) {
582             needThrow = true;
583             return jsonRoot->ToString();
584         }
585         pageRootNode = GetInspectorByKey(rootNode, key);
586     }
587     if (pageRootNode == nullptr) {
588         needThrow = true;
589         return jsonRoot->ToString();
590     }
591     auto pageId = context->GetStageManager()->GetLastPage()->GetPageId();
592     std::vector<RefPtr<NG::UINode>> children;
593     if (key.empty()) {
594         for (const auto& item : pageRootNode->GetChildren()) {
595             GetFrameNodeChildren(item, children, pageId, isLayoutInspector);
596         }
597         auto overlayNode = GetOverlayNode(pageRootNode);
598         if (overlayNode) {
599             GetFrameNodeChildren(overlayNode, children, pageId, isLayoutInspector);
600         }
601     } else {
602         children.emplace_back(pageRootNode);
603     }
604     return GetInspectorInfo(children, pageId, std::move(jsonRoot), isLayoutInspector, filter);
605 }
606 
GetInspectorOfNode(RefPtr<NG::UINode> node)607 std::string Inspector::GetInspectorOfNode(RefPtr<NG::UINode> node)
608 {
609     auto jsonRoot = JsonUtil::Create(true);
610 
611     auto context = NG::PipelineContext::GetCurrentContext();
612     CHECK_NULL_RETURN(context, jsonRoot->ToString());
613     GetContextInfo(context, jsonRoot);
614     CHECK_NULL_RETURN(node, jsonRoot->ToString());
615     auto pageId = context->GetStageManager()->GetLastPage()->GetPageId();
616     auto jsonNodeArray = JsonUtil::CreateArray(true);
617     GetInspectorChildren(node, jsonNodeArray, pageId, true, InspectorFilter(), 0);
618     if (jsonNodeArray->GetArraySize()) {
619         jsonRoot = jsonNodeArray->GetArrayItem(0);
620         GetContextInfo(context, jsonRoot);
621     }
622 
623     return jsonRoot->ToString();
624 }
625 
GetSubWindowInspector(bool isLayoutInspector)626 std::string Inspector::GetSubWindowInspector(bool isLayoutInspector)
627 {
628     auto jsonRoot = JsonUtil::Create(true);
629     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
630 
631     auto context = NG::PipelineContext::GetCurrentContext();
632     CHECK_NULL_RETURN(context, jsonRoot->ToString());
633     GetContextInfo(context, jsonRoot);
634     auto overlayNode = context->GetOverlayManager()->GetRootNode().Upgrade();
635     CHECK_NULL_RETURN(overlayNode, jsonRoot->ToString());
636     auto pageId = 0;
637     std::vector<RefPtr<NG::UINode>> children;
638     GetFrameNodeChildren(overlayNode, children, pageId, isLayoutInspector);
639 
640     return GetInspectorInfo(children, 0, std::move(jsonRoot), isLayoutInspector);
641 }
642 
FillSimplifiedInspectorAttrs(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNode)643 void FillSimplifiedInspectorAttrs(const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNode)
644 {
645     auto tmpJson = JsonUtil::Create(true);
646 
647     InspectorFilter filter;
648     parent->ToJsonValue(tmpJson, filter);
649     jsonNode->Put(INSPECTOR_ATTR_ID, tmpJson->GetString(INSPECTOR_ATTR_ID).c_str());
650 
651     auto jsonObject = JsonUtil::Create(true);
652     if (tmpJson->Contains(INSPECTOR_LABEL)) {
653         jsonObject->Put(INSPECTOR_LABEL, tmpJson->GetString(INSPECTOR_LABEL).c_str());
654     }
655     if (tmpJson->Contains(INSPECTOR_CONTENT)) {
656         jsonObject->Put(INSPECTOR_CONTENT, tmpJson->GetString(INSPECTOR_CONTENT).c_str());
657     }
658     jsonObject->Put(INSPECTOR_ENABLED, tmpJson->GetBool(INSPECTOR_ENABLED));
659     jsonObject->Put(INSPECTOR_OPACITY, tmpJson->GetDouble(INSPECTOR_OPACITY));
660     jsonObject->Put(INSPECTOR_ZINDEX, tmpJson->GetInt(INSPECTOR_ZINDEX));
661     jsonObject->Put(INSPECTOR_VISIBILITY, tmpJson->GetString(INSPECTOR_VISIBILITY).c_str());
662     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
663 }
664 
GetSimplifiedSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId)665 void GetSimplifiedSpanInspector(
666     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId)
667 {
668     // span rect follows parent text size
669     auto spanParentNode = parent->GetParent();
670     CHECK_NULL_VOID(spanParentNode);
671     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
672     CHECK_NULL_VOID(node);
673     auto jsonNode = JsonUtil::Create(true);
674 
675     FillSimplifiedInspectorAttrs(parent, jsonNode);
676 
677     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
678     RectF rect = node->GetTransformRectRelativeToWindow();
679     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
680     jsonNodeArray->PutRef(std::move(jsonNode));
681 }
682 
GetSimplifiedInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId,bool isActive)683 void GetSimplifiedInspectorChildren(
684     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId, bool isActive)
685 {
686     // Span is a special case in Inspector since span inherits from UINode
687     if (AceType::InstanceOf<SpanNode>(parent)) {
688         GetSimplifiedSpanInspector(parent, jsonNodeArray, pageId);
689         return;
690     }
691     auto jsonNode = JsonUtil::Create(true);
692     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
693     auto node = AceType::DynamicCast<FrameNode>(parent);
694 
695     RectF rect;
696     isActive = isActive && node->IsActive();
697     if (isActive) {
698         rect = node->GetTransformRectRelativeToWindow();
699     }
700 
701     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
702 
703     FillSimplifiedInspectorAttrs(parent, jsonNode);
704 
705     std::vector<RefPtr<NG::UINode>> children;
706     for (const auto& item : parent->GetChildren()) {
707         GetFrameNodeChildren(item, children, pageId);
708     }
709     auto jsonChildrenArray = JsonUtil::CreateArray(true);
710     for (auto uiNode : children) {
711         GetSimplifiedInspectorChildren(uiNode, jsonChildrenArray, pageId, isActive);
712     }
713     if (jsonChildrenArray->GetArraySize()) {
714         jsonNode->PutRef(INSPECTOR_CHILDREN, std::move(jsonChildrenArray));
715     }
716     jsonNodeArray->PutRef(std::move(jsonNode));
717 }
718 
GetSimplifiedInspector(int32_t containerId)719 std::string Inspector::GetSimplifiedInspector(int32_t containerId)
720 {
721     TAG_LOGI(AceLogTag::ACE_UIEVENT, "GetSimplifiedInspector start: container %{public}d", containerId);
722     auto jsonRoot = JsonUtil::Create(true);
723     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
724 
725     auto context = NG::PipelineContext::GetContextByContainerId(containerId);
726     CHECK_NULL_RETURN(context, jsonRoot->ToString());
727     auto scale = context->GetViewScale();
728     auto rootHeight = context->GetRootHeight();
729     auto rootWidth = context->GetRootWidth();
730     deviceRect.SetRect(0, 0, rootWidth * scale, rootHeight * scale);
731     jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
732     jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
733     jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(SystemProperties::GetResolution()).c_str());
734 
735     auto pageRootNode = context->GetStageManager()->GetLastPage();
736     CHECK_NULL_RETURN(pageRootNode, jsonRoot->ToString());
737 
738     auto pagePattern = pageRootNode->GetPattern<PagePattern>();
739     CHECK_NULL_RETURN(pagePattern, jsonRoot->ToString());
740     auto pageInfo = pagePattern->GetPageInfo();
741     CHECK_NULL_RETURN(pageInfo, jsonRoot->ToString());
742     jsonRoot->Put(INSPECTOR_PAGE_URL, pageInfo->GetPageUrl().c_str());
743     jsonRoot->Put(INSPECTOR_NAV_DST_NAME, Recorder::EventRecorder::Get().GetNavDstName().c_str());
744 
745     auto pageId = context->GetStageManager()->GetLastPage()->GetPageId();
746     std::vector<RefPtr<NG::UINode>> children;
747     for (const auto& item : pageRootNode->GetChildren()) {
748         GetFrameNodeChildren(item, children, pageId);
749     }
750     auto overlayNode = GetOverlayNode(pageRootNode);
751     if (overlayNode) {
752         GetFrameNodeChildren(overlayNode, children, pageId);
753     }
754     auto jsonNodeArray = JsonUtil::CreateArray(true);
755     for (auto& uiNode : children) {
756         GetSimplifiedInspectorChildren(uiNode, jsonNodeArray, pageId, true);
757     }
758     if (jsonNodeArray->GetArraySize()) {
759         jsonRoot->PutRef(INSPECTOR_CHILDREN, std::move(jsonNodeArray));
760     }
761 
762     return jsonRoot->ToString();
763 }
764 
SendEventByKey(const std::string & key,int action,const std::string & params)765 bool Inspector::SendEventByKey(const std::string& key, int action, const std::string& params)
766 {
767     auto context = NG::PipelineContext::GetCurrentContext();
768     CHECK_NULL_RETURN(context, false);
769     auto rootNode = context->GetRootElement();
770     CHECK_NULL_RETURN(rootNode, false);
771 
772     auto inspectorElement = AceType::DynamicCast<FrameNode>(GetInspectorByKey(rootNode, key));
773     CHECK_NULL_RETURN(inspectorElement, false);
774 
775     auto size = inspectorElement->GetGeometryNode()->GetFrameSize();
776     auto offset = inspectorElement->GetTransformRelativeOffset();
777     Rect rect { offset.GetX(), offset.GetY(), size.Width(), size.Height() };
778     context->GetTaskExecutor()->PostTask(
779         [weak = AceType::WeakClaim(AceType::RawPtr(context)), rect, action, params]() {
780             auto context = weak.Upgrade();
781             if (!context) {
782                 return;
783             }
784             TouchEvent point;
785             point.SetX(static_cast<float>(rect.Left() + rect.Width() / 2))
786                 .SetY(static_cast<float>(rect.Top() + rect.Height() / 2))
787                 .SetType(TouchType::DOWN)
788                 .SetTime(std::chrono::high_resolution_clock::now())
789                 .SetSourceType(SourceType::TOUCH);
790             context->OnTouchEvent(point.UpdatePointers());
791 
792             switch (action) {
793                 case static_cast<int>(AceAction::ACTION_CLICK): {
794                     context->OnTouchEvent(GetUpPoint(point).UpdatePointers());
795                     break;
796                 }
797                 case static_cast<int>(AceAction::ACTION_LONG_CLICK): {
798                     CancelableCallback<void()> inspectorTimer;
799                     auto&& callback = [weak, point]() {
800                         auto refPtr = weak.Upgrade();
801                         if (refPtr) {
802                             refPtr->OnTouchEvent(GetUpPoint(point).UpdatePointers());
803                         }
804                     };
805                     inspectorTimer.Reset(callback);
806                     auto taskExecutor =
807                         SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
808                     taskExecutor.PostDelayedTask(inspectorTimer, LONG_PRESS_DELAY, "ArkUIInspectorLongPressTouchEvent");
809                     break;
810                 }
811                 default:
812                     break;
813             }
814         },
815         TaskExecutor::TaskType::UI, "ArkUIInspectorSendEventByKey");
816 
817     return true;
818 }
819 
HideAllMenus()820 void Inspector::HideAllMenus()
821 {
822     auto context = NG::PipelineContext::GetCurrentContext();
823     CHECK_NULL_VOID(context);
824     auto overlayManager = context->GetOverlayManager();
825     CHECK_NULL_VOID(overlayManager);
826     overlayManager->HideAllMenus();
827 }
828 
AddOffscreenNode(RefPtr<FrameNode> node)829 void Inspector::AddOffscreenNode(RefPtr<FrameNode> node)
830 {
831     CHECK_NULL_VOID(node);
832     offscreenNodes.insert(node);
833 }
834 
RemoveOffscreenNode(RefPtr<FrameNode> node)835 void Inspector::RemoveOffscreenNode(RefPtr<FrameNode> node)
836 {
837     CHECK_NULL_VOID(node);
838     offscreenNodes.erase(node);
839 }
840 
GetInspectorTree(InspectorTreeMap & treesInfo)841 void Inspector::GetInspectorTree(InspectorTreeMap& treesInfo)
842 {
843     treesInfo.clear();
844     auto context = NG::PipelineContext::GetCurrentContext();
845     CHECK_NULL_VOID(context);
846     auto stageManager = context->GetStageManager();
847     CHECK_NULL_VOID(stageManager);
848     RefPtr<UINode> pageRootNode = stageManager->GetLastPage();
849     CHECK_NULL_VOID(pageRootNode);
850     auto rootNode = AddInspectorTreeNode(pageRootNode, treesInfo);
851     CHECK_NULL_VOID(rootNode);
852     auto pageId = pageRootNode->GetPageId();
853     std::vector<RefPtr<NG::UINode>> children;
854     for (const auto& item : pageRootNode->GetChildren()) {
855         GetFrameNodeChildren(item, children, pageId, false);
856     }
857     auto overlayNode = GetOverlayNode(pageRootNode);
858     if (overlayNode) {
859         GetFrameNodeChildren(overlayNode, children, pageId, false);
860     }
861     return GetInspectorTreeInfo(children, pageId, treesInfo);
862 }
863 
RecordOnePageNodes(const RefPtr<NG::UINode> & pageNode,InspectorTreeMap & treesInfo)864 void Inspector::RecordOnePageNodes(const RefPtr<NG::UINode>& pageNode, InspectorTreeMap& treesInfo)
865 {
866     CHECK_NULL_VOID(pageNode);
867     std::vector<RefPtr<NG::UINode>> children;
868     auto pageId = pageNode->GetPageId();
869     auto rootNode = AddInspectorTreeNode(pageNode, treesInfo);
870     CHECK_NULL_VOID(rootNode);
871     for (const auto& item : pageNode->GetChildren()) {
872         GetFrameNodeChildren(item, children, pageId, false);
873     }
874     auto overlayNode = GetOverlayNode(pageNode);
875     if (overlayNode) {
876         GetFrameNodeChildren(overlayNode, children, pageId, false);
877     }
878     GetInspectorTreeInfo(children, pageId, treesInfo);
879 }
880 
GetRecordAllPagesNodes(InspectorTreeMap & treesInfo)881 void Inspector::GetRecordAllPagesNodes(InspectorTreeMap& treesInfo)
882 {
883     treesInfo.clear();
884     auto context = NG::PipelineContext::GetCurrentContext();
885     CHECK_NULL_VOID(context);
886     auto stageManager = context->GetStageManager();
887     CHECK_NULL_VOID(stageManager);
888     auto stageNode = stageManager->GetStageNode();
889     CHECK_NULL_VOID(stageNode);
890     for (const auto& item : stageNode->GetChildren()) {
891         auto frameNode = AceType::DynamicCast<FrameNode>(item);
892         if (frameNode == nullptr) {
893             continue;
894         }
895         auto pagePattern = frameNode->GetPattern<PagePattern>();
896         if (pagePattern == nullptr) {
897             continue;
898         }
899         RecordOnePageNodes(item, treesInfo);
900     }
901 }
902 
AddInspectorTreeNode(const RefPtr<NG::UINode> & uiNode,InspectorTreeMap & recNodes)903 RefPtr<RecNode> Inspector::AddInspectorTreeNode(const RefPtr<NG::UINode>& uiNode, InspectorTreeMap& recNodes)
904 {
905     CHECK_NULL_RETURN(uiNode, nullptr);
906     RefPtr<RecNode> recNode = AceType::MakeRefPtr<RecNode>();
907     CHECK_NULL_RETURN(recNode, nullptr);
908     recNode->SetNodeId(uiNode->GetId());
909     std::string strTag = uiNode->GetTag();
910     ConvertIllegalStr(strTag);
911     recNode->SetName(strTag);
912     std::string strDebugLine = uiNode->GetDebugLine();
913     ConvertIllegalStr(strDebugLine);
914     recNode->SetDebugLine(strDebugLine);
915     auto frameNode = AceType::DynamicCast<FrameNode>(uiNode);
916     CHECK_NULL_RETURN(frameNode, nullptr);
917     auto renderContext = frameNode->GetRenderContext();
918     CHECK_NULL_RETURN(renderContext, nullptr);
919     recNode->SetSelfId(renderContext->GetNodeId());
920     recNodes.emplace(uiNode->GetId(), recNode);
921     return recNode;
922 }
923 
GetInspectorTreeInfo(std::vector<RefPtr<NG::UINode>> children,int32_t pageId,InspectorTreeMap & recNodes)924 void Inspector::GetInspectorTreeInfo(
925     std::vector<RefPtr<NG::UINode>> children, int32_t pageId, InspectorTreeMap& recNodes)
926 {
927     for (auto& uiNode : children) {
928         auto addedItem = AddInspectorTreeNode(uiNode, recNodes);
929         if (addedItem == nullptr) {
930             continue;
931         }
932         GetInspectorChildrenInfo(uiNode, recNodes, pageId);
933     }
934 }
935 
GetInspectorChildrenInfo(const RefPtr<NG::UINode> & parent,InspectorTreeMap & recNodes,int32_t pageId,uint32_t depth)936 void Inspector::GetInspectorChildrenInfo(
937     const RefPtr<NG::UINode>& parent, InspectorTreeMap& recNodes, int32_t pageId, uint32_t depth)
938 {
939     // Span is a special case in Inspector since span inherits from UINode
940     if (AceType::InstanceOf<SpanNode>(parent)) {
941         return;
942     }
943     if (AceType::InstanceOf<CustomNode>(parent)) {
944         return;
945     }
946     std::vector<RefPtr<NG::UINode>> children;
947     for (const auto& item : parent->GetChildren()) {
948         GetFrameNodeChildren(item, children, pageId, false);
949     }
950     auto node = AceType::DynamicCast<FrameNode>(parent);
951     if (node != nullptr) {
952         auto overlayNode = node->GetOverlayNode();
953         if (overlayNode != nullptr) {
954             GetFrameNodeChildren(overlayNode, children, pageId, false);
955         }
956     }
957     if (depth) {
958         for (auto uiNode : children) {
959             auto addedNode = AddInspectorTreeNode(uiNode, recNodes);
960             if (addedNode == nullptr) {
961                 continue;
962             }
963             GetInspectorChildrenInfo(uiNode, recNodes, pageId, depth - 1);
964         }
965     }
966 }
967 
GetOffScreenTreeNodes(InspectorTreeMap & nodes)968 void Inspector::GetOffScreenTreeNodes(InspectorTreeMap& nodes)
969 {
970     for (const auto& item : offscreenNodes) {
971         AddInspectorTreeNode(item, nodes);
972     }
973 }
974 } // namespace OHOS::Ace::NG
975