• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 #if !defined(PREVIEW) && !defined(ACE_UNITTEST)
21 #if !defined(CROSS_PLATFORM) && defined(WEB_SUPPORTED)
22 #include "core/components_ng/pattern/web/web_pattern.h"
23 #endif
24 #include "core/common/recorder/inspector_tree_collector.h"
25 #include "core/components_v2/inspector/inspector_constants.h"
26 #include "interfaces/inner_api/ace/ui_event_observer.h"
27 #endif
28 
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 "foundation/arkui/ace_engine/frameworks/base/utils/utf.h"
33 
34 namespace OHOS::Ace::NG {
35 namespace {
36 const char INSPECTOR_TYPE[] = "$type";
37 const char INSPECTOR_ID[] = "$ID";
38 const char INSPECTOR_RECT[] = "$rect";
39 const char INSPECTOR_ATTRS[] = "$attrs";
40 const char INSPECTOR_ROOT[] = "root";
41 const char INSPECTOR_WIDTH[] = "width";
42 const char INSPECTOR_HEIGHT[] = "height";
43 const char INSPECTOR_RESOLUTION[] = "$resolution";
44 const char INSPECTOR_CHILDREN[] = "$children";
45 const char INSPECTOR_DEBUGLINE[] = "$debugLine";
46 #ifdef PREVIEW
47 const char INSPECTOR_VIEW_ID[] = "$viewID";
48 #else
49 const char INSPECTOR_CUSTOM_VIEW_TAG[] = "viewTag";
50 const char INSPECTOR_COMPONENT_TYPE[] = "type";
51 const char INSPECTOR_STATE_VAR[] = "state";
52 #endif
53 #if !defined(PREVIEW) && !defined(ACE_UNITTEST)
54 const char INSPECTOR_PAGE_URL[] = "pageUrl";
55 const char INSPECTOR_NAV_DST_NAME[] = "navDstName";
56 const char INSPECTOR_ATTR_ID[] = "id";
57 const char INSPECTOR_LABEL[] = "label";
58 const char INSPECTOR_CONTENT[] = "content";
59 const char INSPECTOR_ENABLED[] = "enabled";
60 const char INSPECTOR_OPACITY[] = "opacity";
61 const char INSPECTOR_ZINDEX[] = "zindex";
62 const char INSPECTOR_VISIBILITY[] = "visibility";
63 const char INSPECTOR_CHILDREN_COUNT[] = "$childrenCount";
64 #endif
65 
66 
67 const uint32_t LONG_PRESS_DELAY = 1000;
68 RectF deviceRect;
69 
GetUpPoint(const TouchEvent & downPoint)70 TouchEvent GetUpPoint(const TouchEvent& downPoint)
71 {
72     return TouchEvent {}
73         .SetX(downPoint.x)
74         .SetY(downPoint.y)
75         .SetType(TouchType::UP)
76         .SetTime(std::chrono::high_resolution_clock::now())
77         .SetSourceType(SourceType::TOUCH);
78 }
79 #ifdef PREVIEW
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<RefPtr<NG::UINode>> & children,int32_t pageId,bool isLayoutInspector=false)80 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::vector<RefPtr<NG::UINode>>& children, int32_t pageId,
81     bool isLayoutInspector = false)
82 {
83     // Set ViewId for the fast preview.
84     auto parent = uiNode->GetParent();
85     if (parent) {
86         if (parent->GetTag() == "JsView") {
87             uiNode->SetViewId(std::to_string(parent->GetId()));
88         } else {
89             uiNode->SetViewId(parent->GetViewId());
90         }
91     }
92     if (uiNode->GetTag() == "stage") {
93     } else if (uiNode->GetTag() == "page") {
94         if (uiNode->GetPageId() != pageId) {
95             return;
96         }
97     } else {
98         if (!uiNode->GetDebugLine().empty()) {
99             children.emplace_back(uiNode);
100             return;
101         }
102     }
103 
104     for (const auto& frameChild : uiNode->GetChildren()) {
105         GetFrameNodeChildren(frameChild, children, pageId);
106     }
107 }
108 
GetSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId)109 void GetSpanInspector(
110     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId)
111 {
112     // span rect follows parent text size
113     auto spanParentNode = parent->GetParent();
114     while (spanParentNode != nullptr) {
115         if (AceType::InstanceOf<NG::FrameNode>(spanParentNode)) {
116             break;
117         }
118         spanParentNode = spanParentNode->GetParent();
119     }
120     CHECK_NULL_VOID(spanParentNode);
121     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
122     auto jsonNode = JsonUtil::Create(true);
123     auto jsonObject = JsonUtil::Create(true);
124 
125     InspectorFilter filter;
126     parent->ToJsonValue(jsonObject, filter);
127     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
128     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
129     jsonNode->Put(INSPECTOR_ID, parent->GetId());
130     RectF rect = node->GetTransformRectRelativeToWindow();
131     rect = rect.Constrain(deviceRect);
132     if (rect.IsEmpty()) {
133         rect.SetRect(0, 0, 0, 0);
134     }
135     auto strRec = std::to_string(rect.Left())
136                       .append(",")
137                       .append(std::to_string(rect.Top()))
138                       .append(",")
139                       .append(std::to_string(rect.Width()))
140                       .append(",")
141                       .append(std::to_string(rect.Height()));
142     jsonNode->Put(INSPECTOR_RECT, strRec.c_str());
143     jsonNode->Put(INSPECTOR_DEBUGLINE, parent->GetDebugLine().c_str());
144     jsonNode->Put(INSPECTOR_VIEW_ID, parent->GetViewId().c_str());
145     jsonNodeArray->PutRef(std::move(jsonNode));
146 }
147 
PutNodeInfoToJsonNode(RefPtr<OHOS::Ace::NG::FrameNode> & node,bool & isActive,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNode,const RefPtr<NG::UINode> & parent)148 void PutNodeInfoToJsonNode(RefPtr<OHOS::Ace::NG::FrameNode>& node,
149     bool& isActive, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNode, const RefPtr<NG::UINode>& parent)
150 {
151     if (node) {
152         RectF rect;
153         isActive = isActive && node->IsActive();
154         if (isActive) {
155             rect = node->GetTransformRectRelativeToWindow();
156         }
157         rect = rect.Constrain(deviceRect);
158         if (rect.IsEmpty()) {
159             rect.SetRect(0, 0, 0, 0);
160         }
161         auto strRec = std::to_string(rect.Left()).append(",")
162                           .append(std::to_string(rect.Top())).append(",")
163                           .append(std::to_string(rect.Width())).append(",")
164                           .append(std::to_string(rect.Height()));
165         jsonNode->Put(INSPECTOR_RECT, strRec.c_str());
166         jsonNode->Put(INSPECTOR_DEBUGLINE, node->GetDebugLine().c_str());
167         jsonNode->Put(INSPECTOR_VIEW_ID, node->GetViewId().c_str());
168         auto jsonObject = JsonUtil::Create(true);
169 
170         InspectorFilter filter;
171         parent->ToJsonValue(jsonObject, filter);
172         jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
173     }
174 }
175 
GetInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,InspectorChildrenParameters inspectorParameters,const InspectorFilter & filter=InspectorFilter (),uint32_t depth=UINT32_MAX)176 void GetInspectorChildren(const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray,
177     InspectorChildrenParameters inspectorParameters, const InspectorFilter& filter = InspectorFilter(),
178     uint32_t depth = UINT32_MAX)
179 {
180     // Span is a special case in Inspector since span inherits from UINode
181     if (AceType::InstanceOf<SpanNode>(parent)) {
182         GetSpanInspector(parent, jsonNodeArray, inspectorParameters.pageId);
183         return;
184     }
185     auto jsonNode = JsonUtil::Create(true);
186     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
187     jsonNode->Put(INSPECTOR_ID, parent->GetId());
188     auto node = AceType::DynamicCast<FrameNode>(parent);
189     PutNodeInfoToJsonNode(node, inspectorParameters.isActive, jsonNode, parent);
190 
191     std::vector<RefPtr<NG::UINode>> children;
192     for (const auto& item : parent->GetChildren()) {
193         GetFrameNodeChildren(item, children, inspectorParameters.pageId);
194     }
195     if (node != nullptr) {
196         auto overlayNode = node->GetOverlayNode();
197         if (overlayNode != nullptr) {
198             GetFrameNodeChildren(overlayNode, children, inspectorParameters.pageId);
199         }
200     }
201     if (depth) {
202         auto jsonChildrenArray = JsonUtil::CreateArray(true);
203         for (auto uiNode : children) {
204             GetInspectorChildren(uiNode, jsonChildrenArray, inspectorParameters, filter, depth - 1);
205         }
206         if (jsonChildrenArray->GetArraySize()) {
207             jsonNode->PutRef(INSPECTOR_CHILDREN, std::move(jsonChildrenArray));
208         }
209     }
210     jsonNodeArray->PutRef(std::move(jsonNode));
211 }
212 
213 #else
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::vector<RefPtr<NG::UINode>> & children,int32_t pageId,bool isLayoutInspector=false)214 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::vector<RefPtr<NG::UINode>>& children,
215     int32_t pageId, bool isLayoutInspector = false)
216 {
217     if (AceType::InstanceOf<NG::FrameNode>(uiNode) || AceType::InstanceOf<SpanNode>(uiNode) ||
218         AceType::InstanceOf<CustomNode>(uiNode)) {
219         if (uiNode->GetTag() == "stage") {
220         } else if (uiNode->GetTag() == "page") {
221             if (uiNode->GetPageId() != pageId) {
222                 return;
223             }
224         } else {
225             auto custom = AceType::DynamicCast<NG::CustomNode>(uiNode);
226             auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
227             auto spanNode = AceType::DynamicCast<NG::SpanNode>(uiNode);
228             if ((frameNode && !frameNode->IsInternal()) || spanNode || (custom && isLayoutInspector)) {
229                 children.emplace_back(uiNode);
230                 return;
231             }
232         }
233     }
234     for (const auto& frameChild : uiNode->GetChildren()) {
235         GetFrameNodeChildren(frameChild, children, pageId, isLayoutInspector);
236     }
237 }
238 
GetSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,int pageId)239 void GetSpanInspector(
240     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, int pageId)
241 {
242     // span rect follows parent text size
243     auto spanParentNode = parent->GetParent();
244     while (spanParentNode != nullptr) {
245         if (AceType::InstanceOf<NG::FrameNode>(spanParentNode)) {
246             break;
247         }
248         spanParentNode = spanParentNode->GetParent();
249     }
250     CHECK_NULL_VOID(spanParentNode);
251     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
252     auto jsonNode = JsonUtil::Create(true);
253     auto jsonObject = JsonUtil::Create(true);
254 
255     InspectorFilter filter;
256     parent->ToJsonValue(jsonObject, filter);
257     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
258     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
259     jsonNode->Put(INSPECTOR_ID, parent->GetId());
260     jsonNode->Put(INSPECTOR_DEBUGLINE, parent->GetDebugLine().c_str());
261     RectF rect = node->GetTransformRectRelativeToWindow();
262     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
263     jsonNodeArray->PutRef(std::move(jsonNode));
264 }
265 
GetCustomNodeInfo(const RefPtr<NG::UINode> & customNode,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNode)266 void GetCustomNodeInfo(const RefPtr<NG::UINode> &customNode, std::unique_ptr<OHOS::Ace::JsonValue> &jsonNode)
267 {
268     // custom node rect follows parent size
269     auto hostNode = customNode->GetParent();
270     while (hostNode != nullptr) {
271         if (AceType::InstanceOf<NG::FrameNode>(hostNode)) {
272             break;
273         }
274         hostNode = hostNode->GetParent();
275     }
276     CHECK_NULL_VOID(hostNode);
277     jsonNode->Put(INSPECTOR_COMPONENT_TYPE, "custom");
278     auto node = AceType::DynamicCast<CustomNode>(customNode);
279     CHECK_NULL_VOID(node);
280     auto parentNode = AceType::DynamicCast<FrameNode>(hostNode);
281     jsonNode->Put(INSPECTOR_STATE_VAR, node->GetStateInspectorInfo());
282     RectF rect = parentNode->GetTransformRectRelativeToWindow();
283     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
284     jsonNode->Put(INSPECTOR_DEBUGLINE, customNode->GetDebugLine().c_str());
285     jsonNode->Put(INSPECTOR_CUSTOM_VIEW_TAG, node->GetCustomTag().c_str());
286 }
287 
PutNodeInfoToJsonNode(RefPtr<OHOS::Ace::NG::FrameNode> & node,bool & isActive,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNode)288 void PutNodeInfoToJsonNode(RefPtr<OHOS::Ace::NG::FrameNode>& node,
289     bool& isActive, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNode)
290 {
291     if (node) {
292         RectF rect;
293         isActive = isActive && node->IsActive();
294         if (isActive) {
295             rect = node->GetTransformRectRelativeToWindow();
296         }
297         jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
298         jsonNode->Put(INSPECTOR_DEBUGLINE, node->GetDebugLine().c_str());
299     }
300 }
301 
GetInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,InspectorChildrenParameters inspectorParameters,const InspectorFilter & filter=InspectorFilter (),uint32_t depth=UINT32_MAX)302 void GetInspectorChildren(const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray,
303     InspectorChildrenParameters inspectorParameters, const InspectorFilter& filter = InspectorFilter(),
304     uint32_t depth = UINT32_MAX)
305 {
306     // Span is a special case in Inspector since span inherits from UINode
307     if (AceType::InstanceOf<SpanNode>(parent)) {
308         GetSpanInspector(parent, jsonNodeArray, inspectorParameters.pageId);
309         return;
310     }
311     if (AceType::InstanceOf<CustomNode>(parent) && !inspectorParameters.isLayoutInspector) {
312         return;
313     }
314     auto jsonNode = JsonUtil::Create(true);
315     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
316     jsonNode->Put(INSPECTOR_ID, parent->GetId());
317     if (parent->GetTag() == V2::JS_VIEW_ETS_TAG) {
318         GetCustomNodeInfo(parent, jsonNode);
319     } else {
320         jsonNode->Put(INSPECTOR_COMPONENT_TYPE, "build-in");
321     }
322     auto node = AceType::DynamicCast<FrameNode>(parent);
323     PutNodeInfoToJsonNode(node, inspectorParameters.isActive, jsonNode);
324     auto jsonObject = JsonUtil::Create(true);
325     parent->ToJsonValue(jsonObject, filter);
326     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
327     std::string jsonNodeStr = jsonNode->ToString();
328     ConvertIllegalStr(jsonNodeStr);
329     auto jsonNodeNew = JsonUtil::ParseJsonString(jsonNodeStr);
330     if (jsonNodeNew == nullptr || !jsonNodeNew->IsValid()) {
331         LOGW("inspector info of %{public}s-%{public}d is illegal", parent->GetTag().c_str(), parent->GetId());
332         return;
333     }
334     std::vector<RefPtr<NG::UINode>> children;
335     for (const auto& item : parent->GetChildren()) {
336         GetFrameNodeChildren(item, children, inspectorParameters.pageId, inspectorParameters.isLayoutInspector);
337     }
338     if (node) {
339         auto overlayNode = node->GetOverlayNode();
340         if (overlayNode != nullptr) {
341             GetFrameNodeChildren(overlayNode, children, inspectorParameters.pageId,
342                 inspectorParameters.isLayoutInspector);
343         }
344     }
345     if (depth) {
346         auto jsonChildrenArray = JsonUtil::CreateArray(true);
347         for (auto uiNode : children) {
348             GetInspectorChildren(uiNode, jsonChildrenArray, inspectorParameters, filter, depth - 1);
349         }
350         if (jsonChildrenArray->GetArraySize()) {
351             jsonNodeNew->PutRef(INSPECTOR_CHILDREN, std::move(jsonChildrenArray));
352         }
353     }
354     jsonNodeArray->PutRef(std::move(jsonNodeNew));
355 }
356 #endif
357 
GenerateParameters(InspectorChildrenParameters & inspectorParameters,int32_t & pageId,bool isActive,bool isLayoutInspector=false)358 void GenerateParameters(InspectorChildrenParameters& inspectorParameters,
359     int32_t& pageId, bool isActive, bool isLayoutInspector = false)
360 {
361     inspectorParameters.pageId = pageId;
362     inspectorParameters.isActive = isActive;
363     inspectorParameters.isLayoutInspector = isLayoutInspector;
364 }
365 
GetOverlayNode(const RefPtr<NG::UINode> & pageNode)366 RefPtr<NG::UINode> GetOverlayNode(const RefPtr<NG::UINode>& pageNode)
367 {
368     CHECK_NULL_RETURN(pageNode, nullptr);
369     auto stageNode = pageNode->GetParent();
370     CHECK_NULL_RETURN(stageNode, nullptr);
371     auto stageParent = stageNode->GetParent();
372     CHECK_NULL_RETURN(stageParent, nullptr);
373     auto overlayNode = stageParent->GetChildren().back();
374     if (overlayNode->GetTag() == "stage") {
375         return nullptr;
376     }
377     return overlayNode;
378 }
379 
GetContextInfo(const RefPtr<PipelineContext> & context,std::unique_ptr<JsonValue> & jsonRoot)380 void GetContextInfo(const RefPtr<PipelineContext>& context, std::unique_ptr<JsonValue>& jsonRoot)
381 {
382     auto scale = context->GetViewScale();
383     auto rootHeight = context->GetRootHeight();
384     auto rootWidth = context->GetRootWidth();
385     deviceRect.SetRect(0, 0, rootWidth * scale, rootHeight * scale);
386     jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
387     jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
388     jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(PipelineBase::GetCurrentDensity()).c_str());
389 }
390 
GetInspectorInfo(std::vector<RefPtr<NG::UINode>> children,int32_t pageId,std::unique_ptr<JsonValue> jsonRoot,bool isLayoutInspector,const InspectorFilter & filter=InspectorFilter ())391 std::string GetInspectorInfo(std::vector<RefPtr<NG::UINode>> children, int32_t pageId,
392     std::unique_ptr<JsonValue> jsonRoot, bool isLayoutInspector, const InspectorFilter& filter = InspectorFilter())
393 {
394     auto jsonNodeArray = JsonUtil::CreateArray(true);
395     auto depth = filter.GetFilterDepth();
396     InspectorChildrenParameters inspectorParameters;
397     GenerateParameters(inspectorParameters, pageId, true, isLayoutInspector);
398     for (auto& uiNode : children) {
399         GetInspectorChildren(uiNode, jsonNodeArray, inspectorParameters, filter, depth - 1);
400     }
401     if (jsonNodeArray->GetArraySize()) {
402         jsonRoot->PutRef(INSPECTOR_CHILDREN, std::move(jsonNodeArray));
403     }
404 
405     if (isLayoutInspector) {
406         auto jsonTree = JsonUtil::Create(true);
407         jsonTree->Put("type", "root");
408         jsonTree->PutRef("content", std::move(jsonRoot));
409         auto pipeline = PipelineContext::GetCurrentContextSafely();
410         if (pipeline) {
411             jsonTree->Put("VsyncID", (int32_t)pipeline->GetFrameCount());
412             jsonTree->Put("ProcessID", getpid());
413             jsonTree->Put("WindowID", (int32_t)pipeline->GetWindowId());
414         }
415         return jsonTree->ToString();
416     }
417 
418     return jsonRoot->ToString();
419 }
420 } // namespace
421 
422 std::set<RefPtr<FrameNode>> Inspector::offscreenNodes;
423 
GetFrameNodeByKey(const std::string & key,bool notDetach,bool skipoffscreenNodes)424 RefPtr<FrameNode> Inspector::GetFrameNodeByKey(const std::string& key, bool notDetach, bool skipoffscreenNodes)
425 {
426     // 如果查找的目标节点确定是已经挂树的节点,可以跳过offscreenNodes的遍历,避免offscreenNodes过多的情况消耗性能。
427     if (!offscreenNodes.empty() && !skipoffscreenNodes) {
428         for (auto node : offscreenNodes) {
429             auto frameNode = AceType::DynamicCast<FrameNode>(GetInspectorByKey(node, key, notDetach));
430             if (frameNode) {
431                 return frameNode;
432             }
433         }
434     }
435     auto context = NG::PipelineContext::GetCurrentContextSafely();
436     if (!context) {
437         LOGW("Internal error! Context is null.");
438         return nullptr;
439     }
440     auto rootNode = context->GetRootElement();
441     if (!rootNode) {
442         LOGW("Internal error! RootNode is null.");
443         return nullptr;
444     }
445 
446     return AceType::DynamicCast<FrameNode>(GetInspectorByKey(rootNode, key, notDetach));
447 }
448 
GetInspectorNodeByKey(const std::string & key,const InspectorFilter & filter)449 std::string Inspector::GetInspectorNodeByKey(const std::string& key, const InspectorFilter& filter)
450 {
451     auto context = NG::PipelineContext::GetCurrentContext();
452     CHECK_NULL_RETURN(context, "");
453     auto rootNode = context->GetRootElement();
454     CHECK_NULL_RETURN(rootNode, "");
455 
456     auto inspectorElement = GetInspectorByKey(rootNode, key);
457     CHECK_NULL_RETURN(inspectorElement, "");
458 
459     auto jsonNode = JsonUtil::Create(true);
460     jsonNode->Put(INSPECTOR_TYPE, inspectorElement->GetTag().c_str());
461     jsonNode->Put(INSPECTOR_ID, inspectorElement->GetId());
462     auto frameNode = AceType::DynamicCast<FrameNode>(inspectorElement);
463     if (frameNode) {
464         auto rect = frameNode->GetTransformRectRelativeToWindow();
465         jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
466     }
467     auto jsonAttrs = JsonUtil::Create(true);
468     std::string debugLine = inspectorElement->GetDebugLine();
469     jsonNode->Put(INSPECTOR_DEBUGLINE, debugLine.c_str());
470 
471     inspectorElement->ToJsonValue(jsonAttrs, filter);
472     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonAttrs));
473     return jsonNode->ToString();
474 }
475 
GetRectangleById(const std::string & key,Rectangle & rectangle)476 void Inspector::GetRectangleById(const std::string& key, Rectangle& rectangle)
477 {
478     auto frameNode = Inspector::GetFrameNodeByKey(key, true);
479     if (!frameNode) {
480         LOGW("Can't find component, check your parameters");
481         return;
482     }
483     rectangle.size = frameNode->GetGeometryNode()->GetFrameSize();
484     auto context = frameNode->GetRenderContext();
485     if (!context) {
486         LOGW("Internal error! Component(tag=%{public}s) is null", frameNode->GetTag().c_str());
487         return;
488     }
489     rectangle.localOffset = context->GetPaintRectWithTransform().GetOffset();
490     rectangle.windowOffset = frameNode->GetOffsetRelativeToWindow();
491     auto pipeline = frameNode->GetContext();
492     CHECK_NULL_VOID(pipeline);
493     auto container = Container::Current();
494     if (container && container->IsDynamicRender() &&
495         container->GetUIContentType() == UIContentType::DYNAMIC_COMPONENT) {
496         rectangle.windowOffset = rectangle.windowOffset + OffsetF(pipeline->GetHostParentOffsetToWindow().GetX(),
497             pipeline->GetHostParentOffsetToWindow().GetY());
498     }
499     rectangle.screenRect = pipeline->GetCurrentWindowRect();
500     ACE_SCOPED_TRACE("Inspector::GetRectangleById_Id=%d_Tag=%s_Key=%s",
501         frameNode->GetId(), frameNode->GetTag().c_str(), key.c_str());
502     TAG_LOGD(AceLogTag::ACE_LAYOUT_INSPECTOR, "GetRectangleById Id:%{public}d key:%{public}s localOffset:%{public}s"
503          "screenRect:%{public}s",
504         frameNode->GetId(), key.c_str(), rectangle.localOffset.ToString().c_str(),
505         rectangle.screenRect.ToString().c_str());
506     auto renderContext = frameNode->GetRenderContext();
507     CHECK_NULL_VOID(renderContext);
508     Matrix4 defMatrix4 = Matrix4::CreateIdentity();
509     Matrix4 matrix4 = renderContext->GetTransformMatrixValue(defMatrix4);
510     rectangle.matrix4 = matrix4;
511     auto rect = renderContext->GetPaintRectWithoutTransform();
512     const double halfDimension = 50.0;
513     auto center = renderContext->GetTransformCenter().value_or(DimensionOffset(
514         Dimension(halfDimension, DimensionUnit::PERCENT), Dimension(halfDimension, DimensionUnit::PERCENT)));
515     double centerX = 0.0;
516     double centerY = 0.0;
517     if (center.GetX().Unit() == DimensionUnit::PERCENT || center.GetY().Unit() == DimensionUnit::PERCENT) {
518         if (rect.IsValid()) {
519             centerX = Dimension(center.GetX().ConvertToPxWithSize(rect.Width()), DimensionUnit::PX).ConvertToVp();
520             centerY = Dimension(center.GetY().ConvertToPxWithSize(rect.Height()), DimensionUnit::PX).ConvertToVp();
521         }
522     } else {
523         centerX = center.GetX().ConvertToVp();
524         centerY = center.GetY().ConvertToVp();
525     }
526     VectorF defScale = VectorF(1.0, 1.0);
527     VectorF scale = renderContext->GetTransformScaleValue(defScale);
528     rectangle.scale.x = scale.x;
529     rectangle.scale.y = scale.y;
530     rectangle.scale.z = 1.0;
531     rectangle.scale.centerX = centerX;
532     rectangle.scale.centerY = centerY;
533     Vector5F defRotate = Vector5F(0.0, 0.0, 0.0, 0.0, 0.0);
534     Vector5F rotate = renderContext->GetTransformRotateValue(defRotate);
535     rectangle.rotate.x = rotate.x;
536     rectangle.rotate.y = rotate.y;
537     rectangle.rotate.z = rotate.z;
538     rectangle.rotate.angle = rotate.w;
539     rectangle.rotate.centerX = centerX;
540     rectangle.rotate.centerY = centerY;
541     TranslateOptions defTranslate = TranslateOptions(0.0, 0.0, 0.0);
542     TranslateOptions translate = renderContext->GetTransformTranslateValue(defTranslate);
543     if ((translate.x.Unit() == DimensionUnit::PERCENT) && rect.IsValid()) {
544         rectangle.translate.x =
545             Dimension(translate.x.ConvertToPxWithSize(rect.Width()), DimensionUnit::PX).ConvertToVp();
546     } else {
547         rectangle.translate.x = translate.x.ConvertToVp();
548     }
549     if ((translate.y.Unit() == DimensionUnit::PERCENT) && rect.IsValid()) {
550         rectangle.translate.y =
551             Dimension(translate.y.ConvertToPxWithSize(rect.Height()), DimensionUnit::PX).ConvertToVp();
552     } else {
553         rectangle.translate.y = translate.y.ConvertToVp();
554     }
555     rectangle.translate.z = translate.z.ConvertToVp();
556 }
557 
GetInspector(bool isLayoutInspector)558 std::string Inspector::GetInspector(bool isLayoutInspector)
559 {
560     InspectorFilter filter;
561     bool needThrow = false;
562     return GetInspector(isLayoutInspector, filter, needThrow);
563 }
564 
GetInspector(bool isLayoutInspector,const InspectorFilter & filter,bool & needThrow)565 std::string Inspector::GetInspector(bool isLayoutInspector, const InspectorFilter& filter, bool& needThrow)
566 {
567     auto jsonRoot = JsonUtil::Create(true);
568     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
569     needThrow = false;
570     auto context = NG::PipelineContext::GetCurrentContext();
571     if (context == nullptr) {
572         needThrow = true;
573         return jsonRoot->ToString();
574     }
575     GetContextInfo(context, jsonRoot);
576 
577     RefPtr<UINode> pageRootNode;
578     const std::string key = filter.GetFilterID();
579     if (key.empty()) {
580         pageRootNode = context->GetStageManager()->GetLastPage();
581     } else {
582         auto rootNode = context->GetStageManager()->GetLastPage();
583         if (rootNode == nullptr) {
584             needThrow = true;
585             return jsonRoot->ToString();
586         }
587         pageRootNode = GetInspectorByKey(rootNode, key);
588     }
589     if (pageRootNode == nullptr) {
590         needThrow = true;
591         return jsonRoot->ToString();
592     }
593     auto pageId = context->GetStageManager()->GetLastPage()->GetPageId();
594     std::vector<RefPtr<NG::UINode>> children;
595     if (key.empty()) {
596         for (const auto& item : pageRootNode->GetChildren()) {
597             GetFrameNodeChildren(item, children, pageId, isLayoutInspector);
598         }
599         auto overlayNode = GetOverlayNode(pageRootNode);
600         if (overlayNode) {
601             GetFrameNodeChildren(overlayNode, children, pageId, isLayoutInspector);
602         }
603     } else {
604         children.emplace_back(pageRootNode);
605     }
606     return GetInspectorInfo(children, pageId, std::move(jsonRoot), isLayoutInspector, filter);
607 }
608 
GetInspectorOfNode(RefPtr<NG::UINode> node)609 std::string Inspector::GetInspectorOfNode(RefPtr<NG::UINode> node)
610 {
611     auto jsonRoot = JsonUtil::Create(true);
612 
613     auto context = NG::PipelineContext::GetCurrentContext();
614     CHECK_NULL_RETURN(context, jsonRoot->ToString());
615     GetContextInfo(context, jsonRoot);
616     CHECK_NULL_RETURN(node, jsonRoot->ToString());
617     auto pageId = context->GetStageManager()->GetLastPage()->GetPageId();
618     auto jsonNodeArray = JsonUtil::CreateArray(true);
619     InspectorChildrenParameters inspectorParameters;
620     GenerateParameters(inspectorParameters, pageId, true);
621     GetInspectorChildren(node, jsonNodeArray, inspectorParameters, InspectorFilter(), 0);
622     if (jsonNodeArray->GetArraySize()) {
623         jsonRoot = jsonNodeArray->GetArrayItem(0);
624         GetContextInfo(context, jsonRoot);
625     }
626 
627     return jsonRoot->ToString();
628 }
629 
GetInspectorByKey(const RefPtr<FrameNode> & root,const std::string & key,bool notDetach)630 RefPtr<UINode> Inspector::GetInspectorByKey(const RefPtr<FrameNode>& root, const std::string& key, bool notDetach)
631 {
632     std::queue<RefPtr<UINode>> elements;
633     elements.push(root);
634     RefPtr<UINode> inspectorElement;
635     while (!elements.empty()) {
636         auto current = elements.front();
637         elements.pop();
638         if (key == current->GetInspectorId().value_or("")) {
639             return current;
640         }
641 
642         const auto& children = current->GetChildren(notDetach);
643         for (const auto& child : children) {
644             elements.push(child);
645         }
646     }
647     return nullptr;
648 }
649 
GetSubWindowInspector(bool isLayoutInspector)650 std::string Inspector::GetSubWindowInspector(bool isLayoutInspector)
651 {
652     auto jsonRoot = JsonUtil::Create(true);
653     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
654 
655     auto context = NG::PipelineContext::GetCurrentContext();
656     CHECK_NULL_RETURN(context, jsonRoot->ToString());
657     GetContextInfo(context, jsonRoot);
658     auto overlayNode = context->GetOverlayManager()->GetRootNode().Upgrade();
659     CHECK_NULL_RETURN(overlayNode, jsonRoot->ToString());
660     auto pageId = 0;
661     std::vector<RefPtr<NG::UINode>> children;
662     GetFrameNodeChildren(overlayNode, children, pageId, isLayoutInspector);
663 
664     return GetInspectorInfo(children, 0, std::move(jsonRoot), isLayoutInspector);
665 }
666 
667 #if !defined(PREVIEW) && !defined(ACE_UNITTEST)
668 struct InspectorTreeParams {
669     int pageId;
670     bool isActive;
671     TreeParams params;
672     InspectorConfig inspectorCfg;
673     size_t size;
674     bool isAsync = false;
675     std::shared_ptr<Recorder::InspectorTreeCollector> collector;
676 };
677 
FillSimplifiedInspectorAttrs(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNode,const TreeParams & params,const InspectorConfig & inspectorCfg)678 void FillSimplifiedInspectorAttrs(const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNode,
679     const TreeParams& params, const InspectorConfig& inspectorCfg)
680 {
681     if (params.isNewVersion) {
682         auto tmpJson = JsonUtil::Create(true);
683         parent->ToTreeJson(tmpJson, inspectorCfg);
684         jsonNode->PutRef(INSPECTOR_ATTRS, std::move(tmpJson));
685         return;
686     }
687     auto tmpJson = JsonUtil::Create(true);
688     InspectorFilter filter;
689     parent->ToJsonValue(tmpJson, filter);
690     if (params.enableFullAttrs) {
691         jsonNode->PutRef(INSPECTOR_ATTRS, std::move(tmpJson));
692         return;
693     }
694     jsonNode->Put(INSPECTOR_ATTR_ID, tmpJson->GetString(INSPECTOR_ATTR_ID).c_str());
695 
696     auto jsonObject = JsonUtil::Create(true);
697     if (tmpJson->Contains(INSPECTOR_LABEL)) {
698         jsonObject->Put(INSPECTOR_LABEL, tmpJson->GetString(INSPECTOR_LABEL).c_str());
699     }
700     if (tmpJson->Contains(INSPECTOR_CONTENT)) {
701         jsonObject->Put(INSPECTOR_CONTENT, tmpJson->GetString(INSPECTOR_CONTENT).c_str());
702     }
703     jsonObject->Put(INSPECTOR_ENABLED, tmpJson->GetBool(INSPECTOR_ENABLED));
704     jsonObject->Put(INSPECTOR_OPACITY, tmpJson->GetDouble(INSPECTOR_OPACITY));
705     jsonObject->Put(INSPECTOR_ZINDEX, tmpJson->GetInt(INSPECTOR_ZINDEX));
706     jsonObject->Put(INSPECTOR_VISIBILITY, tmpJson->GetString(INSPECTOR_VISIBILITY).c_str());
707     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
708 }
709 
GetSimplifiedSpanInspector(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,InspectorTreeParams & funcParams)710 void GetSimplifiedSpanInspector(const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray,
711     InspectorTreeParams& funcParams)
712 {
713     // span rect follows parent text size
714     auto spanParentNode = parent->GetParent();
715     CHECK_NULL_VOID(spanParentNode);
716     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
717     CHECK_NULL_VOID(node);
718     auto jsonNode = JsonUtil::Create(true);
719 
720     FillSimplifiedInspectorAttrs(parent, jsonNode, funcParams.params, funcParams.inspectorCfg);
721 
722     jsonNode->Put(INSPECTOR_ID, parent->GetId());
723     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
724     RectF rect = node->GetTransformRectRelativeToWindow();
725     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
726     jsonNodeArray->PutRef(std::move(jsonNode));
727 }
728 
GetFrameNodeChildren(const RefPtr<NG::UINode> & uiNode,std::list<RefPtr<NG::UINode>> & children,int32_t pageId)729 void GetFrameNodeChildren(const RefPtr<NG::UINode>& uiNode, std::list<RefPtr<NG::UINode>>& children, int32_t pageId)
730 {
731     if (AceType::InstanceOf<NG::FrameNode>(uiNode) || AceType::InstanceOf<SpanNode>(uiNode) ||
732         AceType::InstanceOf<CustomNode>(uiNode)) {
733         if (uiNode->GetTag() == "page") {
734             if (uiNode->GetPageId() != pageId) {
735                 return;
736             }
737         } else if (uiNode->GetTag() != "stage") {
738             auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
739             auto spanNode = AceType::DynamicCast<NG::SpanNode>(uiNode);
740             if ((frameNode && !frameNode->IsInternal()) || spanNode) {
741                 children.emplace_back(uiNode);
742                 return;
743             }
744         }
745     }
746     for (const auto& frameChild : uiNode->GetChildren()) {
747         GetFrameNodeChildren(frameChild, children, pageId);
748     }
749 }
750 
CheckNodeRect(const RefPtr<FrameNode> & node,RectF & rect,bool isVisibleOnly)751 bool CheckNodeRect(const RefPtr<FrameNode>& node, RectF& rect, bool isVisibleOnly)
752 {
753     auto renderContext = node->GetRenderContext();
754     CHECK_NULL_RETURN(renderContext, false);
755     auto paintRect = renderContext->GetPaintRectWithoutTransform();
756     if (paintRect.IsEmpty()) {
757         return false;
758     }
759     rect = node->GetTransformRectRelativeToWindow();
760     if (isVisibleOnly && !deviceRect.IsIntersectWith(rect)) {
761         return false;
762     }
763     return true;
764 }
765 
GetWebContentIfNeed(const RefPtr<FrameNode> & node,const InspectorTreeParams & funcParams)766 void GetWebContentIfNeed(const RefPtr<FrameNode>& node, const InspectorTreeParams& funcParams)
767 {
768     if (!funcParams.isAsync || !funcParams.collector) {
769         return;
770     }
771 #if !defined(CROSS_PLATFORM) && defined(WEB_SUPPORTED)
772     if (node->GetTag() == V2::WEB_ETS_TAG && funcParams.params.enableWeb && !funcParams.params.webContentJs.empty()) {
773         auto pattern = node->GetPattern<WebPattern>();
774         CHECK_NULL_VOID(pattern);
775         if (!pattern->GetActiveStatus()) {
776             return;
777         }
778         auto lambda = [webId = node->GetId(), collector = funcParams.collector](const std::string& result) {
779             std::string key = "Web_" + std::to_string(webId);
780             collector->GetJson()->Put(key.c_str(), result.c_str());
781             collector->DecreaseTaskNum();
782         };
783         funcParams.collector->IncreaseTaskNum();
784         if (!pattern->RunJavascriptAsync(funcParams.params.webContentJs, std::move(lambda))) {
785             funcParams.collector->DecreaseTaskNum();
786         }
787     }
788 #endif
789 }
790 
GetSimplifiedInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,InspectorTreeParams & funcParams)791 void GetSimplifiedInspectorChildren(const RefPtr<NG::UINode>& parent,
792     std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, InspectorTreeParams& funcParams)
793 {
794     // Span is a special case in Inspector since span inherits from UINode
795     if (AceType::InstanceOf<SpanNode>(parent)) {
796         funcParams.size += 1;
797         GetSimplifiedSpanInspector(parent, jsonNodeArray, funcParams);
798         return;
799     }
800     auto jsonNode = JsonUtil::Create(true);
801     auto node = AceType::DynamicCast<FrameNode>(parent);
802     auto isActive = funcParams.isActive && node->IsActive();
803     if (!isActive && !funcParams.params.enableAllNodes) {
804         return;
805     }
806     auto lp = node->GetLayoutProperty();
807     CHECK_NULL_VOID(lp);
808     bool isVisible = lp->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE;
809     if (!isVisible && !funcParams.params.enableAllNodes) {
810         return;
811     }
812     jsonNode->Put(INSPECTOR_ID, node->GetId());
813     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
814     RectF rect;
815     if (!CheckNodeRect(node, rect, funcParams.params.isVisibleOnly)) {
816         return;
817     }
818     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
819     funcParams.size += 1;
820     GetWebContentIfNeed(node, funcParams);
821     FillSimplifiedInspectorAttrs(parent, jsonNode, funcParams.params, funcParams.inspectorCfg);
822     std::vector<RefPtr<NG::UINode>> children;
823     for (const auto& item : parent->GetChildren()) {
824         GetFrameNodeChildren(item, children, funcParams.pageId);
825     }
826     auto jsonChildrenArray = JsonUtil::CreateArray(true);
827     for (auto uiNode : children) {
828         funcParams.isActive = isActive;
829         GetSimplifiedInspectorChildren(uiNode, jsonChildrenArray, funcParams);
830     }
831     if (jsonChildrenArray->GetArraySize()) {
832         jsonNode->PutRef(INSPECTOR_CHILDREN, std::move(jsonChildrenArray));
833     }
834     jsonNodeArray->PutRef(std::move(jsonNode));
835 }
836 
GetSimplifiedInspectorStep1(const std::unique_ptr<JsonValue> & jsonRoot,int32_t containerId,RefPtr<PipelineContext> & context,RefPtr<FrameNode> & pageRootNode)837 bool GetSimplifiedInspectorStep1(const std::unique_ptr<JsonValue>& jsonRoot, int32_t containerId,
838     RefPtr<PipelineContext>& context, RefPtr<FrameNode>& pageRootNode)
839 {
840     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
841     context = NG::PipelineContext::GetContextByContainerId(containerId);
842     CHECK_NULL_RETURN(context, false);
843     auto scale = context->GetViewScale();
844     auto rootHeight = context->GetRootHeight();
845     auto rootWidth = context->GetRootWidth();
846     deviceRect.SetRect(0, 0, rootWidth * scale, rootHeight * scale);
847     jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
848     jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
849     jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(SystemProperties::GetResolution()).c_str());
850 
851     pageRootNode = context->GetStageManager()->GetLastPage();
852     return pageRootNode != nullptr;
853 }
854 
GetSimplifiedInspectorStep2(const std::unique_ptr<JsonValue> & jsonRoot,const RefPtr<FrameNode> & pageRootNode,InspectorTreeParams & funcParams)855 bool GetSimplifiedInspectorStep2(
856     const std::unique_ptr<JsonValue>& jsonRoot, const RefPtr<FrameNode>& pageRootNode, InspectorTreeParams& funcParams)
857 {
858     auto pagePattern = pageRootNode->GetPattern<PagePattern>();
859     CHECK_NULL_RETURN(pagePattern, false);
860     auto pageInfo = pagePattern->GetPageInfo();
861     CHECK_NULL_RETURN(pageInfo, false);
862     jsonRoot->Put(INSPECTOR_PAGE_URL, pageInfo->GetPageUrl().c_str());
863     jsonRoot->Put(INSPECTOR_NAV_DST_NAME, Recorder::EventRecorder::Get().GetNavDstName().c_str());
864 
865     auto pageId = pageRootNode->GetPageId();
866     std::list<RefPtr<NG::UINode>> children;
867     for (const auto& item : pageRootNode->GetChildren()) {
868         GetFrameNodeChildren(item, children, pageId);
869     }
870     auto overlayNode = GetOverlayNode(pageRootNode);
871     if (overlayNode) {
872         GetFrameNodeChildren(overlayNode, children, pageId);
873     }
874     auto jsonNodeArray = JsonUtil::CreateArray(true);
875 
876     funcParams.pageId = pageId;
877     funcParams.isActive = true;
878     funcParams.size = children.size();
879     funcParams.inspectorCfg = { funcParams.params.isContentOnly };
880     for (auto& uiNode : children) {
881         GetSimplifiedInspectorChildren(uiNode, jsonNodeArray, funcParams);
882     }
883     if (jsonNodeArray->GetArraySize()) {
884         jsonRoot->PutRef(INSPECTOR_CHILDREN, std::move(jsonNodeArray));
885     }
886     jsonRoot->Put(INSPECTOR_CHILDREN_COUNT, funcParams.size);
887     return true;
888 }
889 #endif
890 
GetSimplifiedInspector(int32_t containerId,const TreeParams & params)891 std::string Inspector::GetSimplifiedInspector(int32_t containerId, const TreeParams& params)
892 {
893 #if !defined(PREVIEW) && !defined(ACE_UNITTEST)
894     TAG_LOGI(AceLogTag::ACE_UIEVENT, "Inspector tree a: container %{public}d", containerId);
895     auto jsonRoot = JsonUtil::Create(true);
896     RefPtr<PipelineContext> context;
897     RefPtr<FrameNode> pageRootNode;
898     auto success = GetSimplifiedInspectorStep1(jsonRoot, containerId, context, pageRootNode);
899     if (!success) {
900         return jsonRoot->ToString();
901     }
902     InspectorTreeParams inspectorTreeParams;
903     inspectorTreeParams.params = params;
904     inspectorTreeParams.isAsync = false;
905     GetSimplifiedInspectorStep2(jsonRoot, pageRootNode, inspectorTreeParams);
906     return jsonRoot->ToString();
907 #else
908     return "{}";
909 #endif
910 }
911 
GetSimplifiedInspectorAsync(int32_t containerId,const TreeParams & params,const std::shared_ptr<Recorder::InspectorTreeCollector> & collector)912 void Inspector::GetSimplifiedInspectorAsync(
913     int32_t containerId, const TreeParams& params, const std::shared_ptr<Recorder::InspectorTreeCollector>& collector)
914 {
915 #if !defined(PREVIEW) && !defined(ACE_UNITTEST)
916     TAG_LOGI(AceLogTag::ACE_UIEVENT, "Inspector tree a: container %{public}d", containerId);
917     collector->IncreaseTaskNum();
918     auto& jsonRoot = collector->GetJson();
919     RefPtr<PipelineContext> context;
920     RefPtr<FrameNode> pageRootNode;
921     auto success = GetSimplifiedInspectorStep1(jsonRoot, containerId, context, pageRootNode);
922     if (!success) {
923         collector->DecreaseTaskNum();
924         return;
925     }
926     InspectorTreeParams inspectorTreeParams;
927     inspectorTreeParams.params = params;
928     inspectorTreeParams.isAsync = true;
929     inspectorTreeParams.collector = collector;
930     GetSimplifiedInspectorStep2(jsonRoot, pageRootNode, inspectorTreeParams);
931     collector->DecreaseTaskNum();
932 #endif
933 }
934 
SendEventByKey(const std::string & key,int action,const std::string & params)935 bool Inspector::SendEventByKey(const std::string& key, int action, const std::string& params)
936 {
937     auto context = NG::PipelineContext::GetCurrentContext();
938     CHECK_NULL_RETURN(context, false);
939     auto rootNode = context->GetRootElement();
940     CHECK_NULL_RETURN(rootNode, false);
941 
942     auto inspectorElement = AceType::DynamicCast<FrameNode>(GetInspectorByKey(rootNode, key));
943     CHECK_NULL_RETURN(inspectorElement, false);
944 
945     auto size = inspectorElement->GetGeometryNode()->GetFrameSize();
946     auto offset = inspectorElement->GetTransformRelativeOffset();
947     Rect rect { offset.GetX(), offset.GetY(), size.Width(), size.Height() };
948     context->GetTaskExecutor()->PostTask(
949         [weak = AceType::WeakClaim(AceType::RawPtr(context)), rect, action, params]() {
950             auto context = weak.Upgrade();
951             if (!context) {
952                 return;
953             }
954             TouchEvent point;
955             point.SetX(static_cast<float>(rect.Left() + rect.Width() / 2))
956                 .SetY(static_cast<float>(rect.Top() + rect.Height() / 2))
957                 .SetType(TouchType::DOWN)
958                 .SetTime(std::chrono::high_resolution_clock::now())
959                 .SetSourceType(SourceType::TOUCH);
960             context->OnTouchEvent(point.UpdatePointers());
961 
962             switch (action) {
963                 case static_cast<int>(AceAction::ACTION_CLICK): {
964                     context->OnTouchEvent(GetUpPoint(point).UpdatePointers());
965                     break;
966                 }
967                 case static_cast<int>(AceAction::ACTION_LONG_CLICK): {
968                     CancelableCallback<void()> inspectorTimer;
969                     auto&& callback = [weak, point]() {
970                         auto refPtr = weak.Upgrade();
971                         if (refPtr) {
972                             refPtr->OnTouchEvent(GetUpPoint(point).UpdatePointers());
973                         }
974                     };
975                     inspectorTimer.Reset(callback);
976                     auto taskExecutor =
977                         SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
978                     taskExecutor.PostDelayedTask(inspectorTimer, LONG_PRESS_DELAY, "ArkUIInspectorLongPressTouchEvent");
979                     break;
980                 }
981                 default:
982                     break;
983             }
984         },
985         TaskExecutor::TaskType::UI, "ArkUIInspectorSendEventByKey");
986 
987     return true;
988 }
989 
HideAllMenus()990 void Inspector::HideAllMenus()
991 {
992     auto context = NG::PipelineContext::GetCurrentContext();
993     CHECK_NULL_VOID(context);
994     auto overlayManager = context->GetOverlayManager();
995     CHECK_NULL_VOID(overlayManager);
996     overlayManager->HideAllMenus();
997 }
998 
AddOffscreenNode(RefPtr<FrameNode> node)999 void Inspector::AddOffscreenNode(RefPtr<FrameNode> node)
1000 {
1001     CHECK_NULL_VOID(node);
1002     offscreenNodes.insert(node);
1003 }
1004 
RemoveOffscreenNode(RefPtr<FrameNode> node)1005 void Inspector::RemoveOffscreenNode(RefPtr<FrameNode> node)
1006 {
1007     CHECK_NULL_VOID(node);
1008     offscreenNodes.erase(node);
1009 }
1010 
GetInspectorTree(InspectorTreeMap & treesInfo)1011 void Inspector::GetInspectorTree(InspectorTreeMap& treesInfo)
1012 {
1013     treesInfo.clear();
1014     auto context = NG::PipelineContext::GetCurrentContext();
1015     CHECK_NULL_VOID(context);
1016     auto stageManager = context->GetStageManager();
1017     CHECK_NULL_VOID(stageManager);
1018     RefPtr<UINode> pageRootNode = stageManager->GetLastPage();
1019     CHECK_NULL_VOID(pageRootNode);
1020     auto rootNode = AddInspectorTreeNode(pageRootNode, treesInfo);
1021     CHECK_NULL_VOID(rootNode);
1022     auto pageId = pageRootNode->GetPageId();
1023     std::vector<RefPtr<NG::UINode>> children;
1024     for (const auto& item : pageRootNode->GetChildren()) {
1025         GetFrameNodeChildren(item, children, pageId, false);
1026     }
1027     auto overlayNode = GetOverlayNode(pageRootNode);
1028     if (overlayNode) {
1029         GetFrameNodeChildren(overlayNode, children, pageId, false);
1030     }
1031     return GetInspectorTreeInfo(children, pageId, treesInfo);
1032 }
1033 
RecordOnePageNodes(const RefPtr<NG::UINode> & pageNode,InspectorTreeMap & treesInfo)1034 void Inspector::RecordOnePageNodes(const RefPtr<NG::UINode>& pageNode, InspectorTreeMap& treesInfo)
1035 {
1036     CHECK_NULL_VOID(pageNode);
1037     std::vector<RefPtr<NG::UINode>> children;
1038     auto pageId = pageNode->GetPageId();
1039     auto rootNode = AddInspectorTreeNode(pageNode, treesInfo);
1040     CHECK_NULL_VOID(rootNode);
1041     for (const auto& item : pageNode->GetChildren()) {
1042         GetFrameNodeChildren(item, children, pageId, false);
1043     }
1044     auto overlayNode = GetOverlayNode(pageNode);
1045     if (overlayNode) {
1046         GetFrameNodeChildren(overlayNode, children, pageId, false);
1047     }
1048     GetInspectorTreeInfo(children, pageId, treesInfo);
1049 }
1050 
GetRecordAllPagesNodes(InspectorTreeMap & treesInfo)1051 void Inspector::GetRecordAllPagesNodes(InspectorTreeMap& treesInfo)
1052 {
1053     treesInfo.clear();
1054     auto context = NG::PipelineContext::GetCurrentContext();
1055     CHECK_NULL_VOID(context);
1056     auto stageManager = context->GetStageManager();
1057     CHECK_NULL_VOID(stageManager);
1058     auto stageNode = stageManager->GetStageNode();
1059     CHECK_NULL_VOID(stageNode);
1060     for (const auto& item : stageNode->GetChildren()) {
1061         auto frameNode = AceType::DynamicCast<FrameNode>(item);
1062         if (frameNode == nullptr) {
1063             continue;
1064         }
1065         auto pagePattern = frameNode->GetPattern<PagePattern>();
1066         if (pagePattern == nullptr) {
1067             continue;
1068         }
1069         RecordOnePageNodes(item, treesInfo);
1070     }
1071 }
1072 
AddInspectorTreeNode(const RefPtr<NG::UINode> & uiNode,InspectorTreeMap & recNodes)1073 RefPtr<RecNode> Inspector::AddInspectorTreeNode(const RefPtr<NG::UINode>& uiNode, InspectorTreeMap& recNodes)
1074 {
1075     CHECK_NULL_RETURN(uiNode, nullptr);
1076     RefPtr<RecNode> recNode = AceType::MakeRefPtr<RecNode>();
1077     CHECK_NULL_RETURN(recNode, nullptr);
1078     recNode->SetNodeId(uiNode->GetId());
1079     std::string strTag = uiNode->GetTag();
1080     ConvertIllegalStr(strTag);
1081     recNode->SetName(strTag);
1082     std::string strDebugLine = uiNode->GetDebugLine();
1083     ConvertIllegalStr(strDebugLine);
1084     recNode->SetDebugLine(strDebugLine);
1085     auto frameNode = AceType::DynamicCast<FrameNode>(uiNode);
1086     CHECK_NULL_RETURN(frameNode, nullptr);
1087     auto renderContext = frameNode->GetRenderContext();
1088     CHECK_NULL_RETURN(renderContext, nullptr);
1089     recNode->SetSelfId(renderContext->GetNodeId());
1090     recNodes.emplace(uiNode->GetId(), recNode);
1091     return recNode;
1092 }
1093 
GetInspectorTreeInfo(std::vector<RefPtr<NG::UINode>> children,int32_t pageId,InspectorTreeMap & recNodes)1094 void Inspector::GetInspectorTreeInfo(
1095     std::vector<RefPtr<NG::UINode>> children, int32_t pageId, InspectorTreeMap& recNodes)
1096 {
1097     for (auto& uiNode : children) {
1098         auto addedItem = AddInspectorTreeNode(uiNode, recNodes);
1099         if (addedItem == nullptr) {
1100             continue;
1101         }
1102         GetInspectorChildrenInfo(uiNode, recNodes, pageId);
1103     }
1104 }
1105 
GetInspectorChildrenInfo(const RefPtr<NG::UINode> & parent,InspectorTreeMap & recNodes,int32_t pageId,uint32_t depth)1106 void Inspector::GetInspectorChildrenInfo(
1107     const RefPtr<NG::UINode>& parent, InspectorTreeMap& recNodes, int32_t pageId, uint32_t depth)
1108 {
1109     // Span is a special case in Inspector since span inherits from UINode
1110     if (AceType::InstanceOf<SpanNode>(parent)) {
1111         return;
1112     }
1113     if (AceType::InstanceOf<CustomNode>(parent)) {
1114         return;
1115     }
1116     std::vector<RefPtr<NG::UINode>> children;
1117     for (const auto& item : parent->GetChildren()) {
1118         GetFrameNodeChildren(item, children, pageId, false);
1119     }
1120     auto node = AceType::DynamicCast<FrameNode>(parent);
1121     if (node != nullptr) {
1122         auto overlayNode = node->GetOverlayNode();
1123         if (overlayNode != nullptr) {
1124             GetFrameNodeChildren(overlayNode, children, pageId, false);
1125         }
1126     }
1127     if (depth) {
1128         for (auto uiNode : children) {
1129             auto addedNode = AddInspectorTreeNode(uiNode, recNodes);
1130             if (addedNode == nullptr) {
1131                 continue;
1132             }
1133             GetInspectorChildrenInfo(uiNode, recNodes, pageId, depth - 1);
1134         }
1135     }
1136 }
1137 
GetOffScreenTreeNodes(InspectorTreeMap & nodes)1138 void Inspector::GetOffScreenTreeNodes(InspectorTreeMap& nodes)
1139 {
1140     for (const auto& item : offscreenNodes) {
1141         AddInspectorTreeNode(item, nodes);
1142     }
1143 }
1144 
ParseWindowIdFromMsg(const std::string & message)1145 uint32_t Inspector::ParseWindowIdFromMsg(const std::string& message)
1146 {
1147     TAG_LOGD(AceLogTag::ACE_LAYOUT_INSPECTOR, "start process inspector get window msg");
1148     uint32_t windowId = INVALID_WINDOW_ID;
1149     auto json = JsonUtil::ParseJsonString(message);
1150     if (json == nullptr || !json->IsValid() || !json->IsObject()) {
1151         TAG_LOGE(AceLogTag::ACE_LAYOUT_INSPECTOR, "input message is invalid");
1152         return windowId;
1153     }
1154     auto methodVal = json->GetString(KEY_METHOD);
1155     if (methodVal != SUPPORT_METHOD) {
1156         TAG_LOGE(AceLogTag::ACE_LAYOUT_INSPECTOR, "method is not supported");
1157         return windowId;
1158     }
1159     auto paramObj = json->GetObject(KEY_PARAMS);
1160     if (paramObj == nullptr || !paramObj->IsValid() || !paramObj->IsObject()) {
1161         TAG_LOGE(AceLogTag::ACE_LAYOUT_INSPECTOR, "input message params is invalid");
1162         return windowId;
1163     }
1164     windowId = StringUtils::StringToUint(paramObj->GetString("windowId"));
1165     return windowId;
1166 }
1167 } // namespace OHOS::Ace::NG
1168