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