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