• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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/simplified_inspector.h"
17 
18 #include <memory>
19 
20 #include "core/components/scroll/scroll_controller_base.h"
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_ng/pattern/scrollable/scrollable_pattern.h"
26 #include "core/components_ng/pattern/stage/page_pattern.h"
27 #include "core/components_ng/pattern/text/span_node.h"
28 #include "core/components_v2/inspector/inspector_constants.h"
29 #include "interfaces/inner_api/ace/ui_event_observer.h"
30 
31 namespace OHOS::Ace::NG {
32 namespace {
33 const char INSPECTOR_TYPE[] = "$type";
34 const char INSPECTOR_ID[] = "$ID";
35 const char INSPECTOR_RECT[] = "$rect";
36 const char INSPECTOR_ATTRS[] = "$attrs";
37 const char INSPECTOR_ROOT[] = "root";
38 const char INSPECTOR_WIDTH[] = "width";
39 const char INSPECTOR_HEIGHT[] = "height";
40 const char INSPECTOR_RESOLUTION[] = "$resolution";
41 const char INSPECTOR_CHILDREN[] = "$children";
42 const char INSPECTOR_BUNDLE[] = "bundleName";
43 const char INSPECTOR_ABILITY[] = "ability";
44 const char INSPECTOR_PAGE_URL[] = "pageUrl";
45 const char INSPECTOR_NAV_DST_NAME[] = "navDstName";
46 const char INSPECTOR_ATTR_ID[] = "id";
47 const char INSPECTOR_LABEL[] = "label";
48 const char INSPECTOR_CONTENT[] = "content";
49 const char INSPECTOR_ENABLED[] = "enabled";
50 const char INSPECTOR_OPACITY[] = "opacity";
51 const char INSPECTOR_ZINDEX[] = "zindex";
52 const char INSPECTOR_VISIBILITY[] = "visibility";
53 const char INSPECTOR_CHILDREN_COUNT[] = "$childrenCount";
54 
55 constexpr char KEY_CODE[] = "code";
56 constexpr int32_t ERR_OK = 0;
57 constexpr int32_t ERR_INVALID_PARAM = 101;
58 constexpr int32_t ERR_NOT_FOUND_TARGET_NODE = 102;
59 constexpr int32_t ERR_NOT_FOUND_SCROLLABLE_NODE = 103;
60 
61 enum class TargetType {
62     UNKNOWN = 0,
63     NODE,
64     WEB,
65     ENUM_END,
66 };
67 
68 struct ScrollCommand {
69     TargetType type { TargetType::UNKNOWN };
70     int32_t nodeId { 0 };
71     float scrollOffset { 0.0 };
72     ScrollAlign scrollAlign { ScrollAlign::NONE };
73     std::string webContentJs;
74 };
75 
ParseCommandParam(const std::string & commandParams,ScrollCommand & command)76 bool ParseCommandParam(const std::string& commandParams, ScrollCommand& command)
77 {
78     auto jsonObj = JsonUtil::ParseJsonString(commandParams);
79     if (!jsonObj || !jsonObj->IsValid() || !jsonObj->IsObject()) {
80         return false;
81     }
82     auto action = jsonObj->GetString("action");
83     if (action != "scroll") {
84         return false;
85     }
86     auto type = jsonObj->GetInt("targetType", 0);
87     if (type >= static_cast<int32_t>(TargetType::UNKNOWN) && type < static_cast<int32_t>(TargetType::ENUM_END)) {
88         command.type = static_cast<TargetType>(type);
89     }
90     command.nodeId = jsonObj->GetInt("targetId", 0);
91     command.scrollOffset = static_cast<float>(jsonObj->GetDouble("scrollOffset", 0.0));
92     auto align = jsonObj->GetInt("scrollAlign", 0);
93     if (type >= static_cast<int32_t>(ScrollAlign::START) && type <= static_cast<int32_t>(ScrollAlign::NONE)) {
94         command.scrollAlign = static_cast<ScrollAlign>(align);
95     }
96     command.webContentJs = jsonObj->GetString("webContentJs");
97     return true;
98 }
99 
GetNodeById(const RefPtr<FrameNode> & root,int32_t id)100 RefPtr<UINode> GetNodeById(const RefPtr<FrameNode>& root, int32_t id)
101 {
102     std::queue<RefPtr<UINode>> elements;
103     elements.push(root);
104     RefPtr<UINode> inspectorElement;
105     while (!elements.empty()) {
106         auto current = elements.front();
107         elements.pop();
108         if (current == nullptr) {
109             continue;
110         }
111         if (id == current->GetId()) {
112             return current;
113         }
114 
115         const auto& children = current->GetChildrenForInspector(true);
116         for (const auto& child : children) {
117             elements.push(child);
118         }
119     }
120     return nullptr;
121 }
122 
IsScrollable(const RefPtr<NG::FrameNode> & frameNode)123 bool IsScrollable(const RefPtr<NG::FrameNode>& frameNode)
124 {
125     CHECK_NULL_RETURN(frameNode, false);
126     auto tag = frameNode->GetTag();
127     if (tag == V2::LIST_ETS_TAG || tag == V2::SCROLL_ETS_TAG || tag == V2::WATERFLOW_ETS_TAG ||
128         tag == V2::GRID_ETS_TAG) {
129         auto pattern = frameNode->GetPattern<ScrollablePattern>();
130         CHECK_NULL_RETURN(pattern, false);
131         return pattern->IsScrollable();
132     }
133     return false;
134 }
135 
FindParentScrollable(const RefPtr<FrameNode> & child)136 RefPtr<FrameNode> FindParentScrollable(const RefPtr<FrameNode>& child)
137 {
138     auto parentFrameNode = child->GetAncestorNodeOfFrame(true);
139     while (parentFrameNode) {
140         if (IsScrollable(parentFrameNode)) {
141             return parentFrameNode;
142         }
143         parentFrameNode = parentFrameNode->GetAncestorNodeOfFrame(true);
144     }
145     return nullptr;
146 }
147 
ScrollToTarget(const ScrollCommand & command,const RefPtr<NG::FrameNode> & pageRootNode)148 int32_t ScrollToTarget(const ScrollCommand& command, const RefPtr<NG::FrameNode>& pageRootNode)
149 {
150     CHECK_NULL_RETURN(pageRootNode, ERR_NOT_FOUND_TARGET_NODE);
151     auto targetNode = GetNodeById(pageRootNode, command.nodeId);
152     CHECK_NULL_RETURN(targetNode, ERR_NOT_FOUND_TARGET_NODE);
153     auto target = AceType::DynamicCast<FrameNode>(targetNode);
154     CHECK_NULL_RETURN(target, ERR_NOT_FOUND_TARGET_NODE);
155     auto scrollable = FindParentScrollable(target);
156     CHECK_NULL_RETURN(scrollable, ERR_NOT_FOUND_SCROLLABLE_NODE);
157     ScrollablePattern::ScrollToTarget(scrollable, target, command.scrollOffset, command.scrollAlign);
158     return ERR_OK;
159 }
160 } // namespace
161 
TestScrollToTarget(const std::vector<std::string> & params,const RefPtr<FrameNode> & pageRootNode)162 void SimplifiedInspector::TestScrollToTarget(
163     const std::vector<std::string>& params, const RefPtr<FrameNode>& pageRootNode)
164 {
165     CHECK_NULL_VOID(pageRootNode);
166     // -element -lastpage ${nodeid} ${offset} ${align}
167     const int32_t PARAM_NODE_ID = 2;
168     const int32_t PARAM_OFFSET = 3;
169     const int32_t PARAM_ALIGN = 4;
170     auto id = StringUtils::StringToInt(params[PARAM_NODE_ID]);
171     auto offset = StringUtils::StringToFloat(params[PARAM_OFFSET]);
172     auto align = StringUtils::StringToInt(params[PARAM_ALIGN]);
173     ScrollCommand command { TargetType::NODE, id, offset, static_cast<ScrollAlign>(align) };
174     ScrollToTarget(command, pageRootNode);
175 }
176 
SimplifiedInspector(int32_t containerId,const TreeParams & params)177 SimplifiedInspector::SimplifiedInspector(int32_t containerId, const TreeParams& params)
178     : containerId_(containerId), params_(params), inspectorCfg_({ params.isContentOnly, !params.enableBackground }),
179       isBackground_(params.enableBackground)
180 {}
181 
SimplifiedInspector(int32_t containerId,const UICommandParams & params)182 SimplifiedInspector::SimplifiedInspector(int32_t containerId, const UICommandParams& params)
183     : containerId_(containerId), commandParams_(params)
184 {}
185 
GetOverlayNode(const RefPtr<NG::UINode> & pageNode)186 RefPtr<NG::UINode> GetOverlayNode(const RefPtr<NG::UINode>& pageNode)
187 {
188     CHECK_NULL_RETURN(pageNode, nullptr);
189     auto stageNode = pageNode->GetParent();
190     CHECK_NULL_RETURN(stageNode, nullptr);
191     auto stageParent = stageNode->GetParent();
192     CHECK_NULL_RETURN(stageParent, nullptr);
193     auto overlayNode = stageParent->GetChildren().back();
194     if (overlayNode->GetTag() == "stage") {
195         return nullptr;
196     }
197     return overlayNode;
198 }
199 
GetInspector()200 std::string SimplifiedInspector::GetInspector()
201 {
202     TAG_LOGD(AceLogTag::ACE_UIEVENT, "Inspector1:container %{public}d", containerId_);
203     auto jsonRoot = JsonUtil::Create(true);
204     RefPtr<FrameNode> pageRootNode;
205     auto success = GetInspectorStep1(jsonRoot, pageRootNode);
206     if (!success) {
207         return jsonRoot->ToString();
208     }
209     GetInspectorStep2(jsonRoot, pageRootNode);
210     return jsonRoot->ToString();
211 }
212 
GetInspectorStep1(const std::unique_ptr<JsonValue> & jsonRoot,RefPtr<FrameNode> & pageRootNode)213 bool SimplifiedInspector::GetInspectorStep1(const std::unique_ptr<JsonValue>& jsonRoot, RefPtr<FrameNode>& pageRootNode)
214 {
215     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
216     auto context = NG::PipelineContext::GetContextByContainerId(containerId_);
217     CHECK_NULL_RETURN(context, false);
218     auto scale = context->GetViewScale();
219     auto rootHeight = context->GetRootHeight();
220     auto rootWidth = context->GetRootWidth();
221     deviceRect_.SetRect(0, 0, rootWidth * scale, rootHeight * scale);
222     jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
223     jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
224     jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(SystemProperties::GetResolution()).c_str());
225     jsonRoot->Put(INSPECTOR_NAV_DST_NAME, context->GetCurrentPageNameCallback().c_str());
226 
227     CHECK_NULL_RETURN(context->GetStageManager(), false);
228     pageRootNode = context->GetStageManager()->GetLastPage();
229     return pageRootNode != nullptr;
230 }
231 
GetInspectorStep2(const std::unique_ptr<JsonValue> & jsonRoot,const RefPtr<FrameNode> & pageRootNode)232 bool SimplifiedInspector::GetInspectorStep2(
233     const std::unique_ptr<JsonValue>& jsonRoot, const RefPtr<FrameNode>& pageRootNode)
234 {
235     auto pagePattern = pageRootNode->GetPattern<PagePattern>();
236     CHECK_NULL_RETURN(pagePattern, false);
237     auto pageInfo = pagePattern->GetPageInfo();
238     CHECK_NULL_RETURN(pageInfo, false);
239     jsonRoot->Put(INSPECTOR_BUNDLE, AceApplicationInfo::GetInstance().GetPackageName().c_str());
240     jsonRoot->Put(INSPECTOR_ABILITY, AceApplicationInfo::GetInstance().GetAbilityName().c_str());
241     jsonRoot->Put(INSPECTOR_PAGE_URL, pageInfo->GetPageUrl().c_str());
242 
243     pageId_ = pageRootNode->GetPageId();
244     std::list<RefPtr<NG::UINode>> children;
245     for (const auto& item : pageRootNode->GetChildrenForInspector(params_.enableCacheNode)) {
246         GetFrameNodeChildren(item, children);
247     }
248     auto overlayNode = GetOverlayNode(pageRootNode);
249     if (overlayNode) {
250         GetFrameNodeChildren(overlayNode, children);
251     }
252     auto jsonNodeArray = JsonUtil::CreateArray(true);
253     size_ = children.size();
254     for (auto& uiNode : children) {
255         GetInspectorChildren(uiNode, jsonNodeArray, true);
256     }
257     if (jsonNodeArray->GetArraySize()) {
258         jsonRoot->PutRef(INSPECTOR_CHILDREN, std::move(jsonNodeArray));
259     }
260     jsonRoot->Put(INSPECTOR_CHILDREN_COUNT, size_);
261     return true;
262 }
263 
GetFrameNodeChildren(const RefPtr<UINode> & uiNode,std::list<RefPtr<UINode>> & children)264 void SimplifiedInspector::GetFrameNodeChildren(const RefPtr<UINode>& uiNode, std::list<RefPtr<UINode>>& children)
265 {
266     CHECK_NULL_VOID(uiNode);
267     if (isBackground_) {
268         collector_->RetainNode(uiNode);
269     }
270     if (AceType::InstanceOf<NG::FrameNode>(uiNode) || AceType::InstanceOf<SpanNode>(uiNode) ||
271         AceType::InstanceOf<CustomNode>(uiNode)) {
272         if (uiNode->GetTag() == "page") {
273             if (uiNode->GetPageId() != pageId_) {
274                 return;
275             }
276         } else if (uiNode->GetTag() != "stage") {
277             auto frameNode = AceType::DynamicCast<NG::FrameNode>(uiNode);
278             auto spanNode = AceType::DynamicCast<NG::SpanNode>(uiNode);
279             if ((frameNode && !frameNode->IsInternal()) || spanNode) {
280                 children.emplace_back(uiNode);
281                 return;
282             }
283         }
284     }
285     for (const auto& frameChild : uiNode->GetChildrenForInspector(params_.enableCacheNode)) {
286         GetFrameNodeChildren(frameChild, children);
287     }
288 }
289 
GetInspectorChildren(const RefPtr<NG::UINode> & parent,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray,bool isActive)290 void SimplifiedInspector::GetInspectorChildren(
291     const RefPtr<NG::UINode>& parent, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray, bool isActive)
292 {
293     // Span is a special case in Inspector since span inherits from UINode
294     if (AceType::InstanceOf<SpanNode>(parent)) {
295         size_ += 1;
296         GetSpanInspector(parent, jsonNodeArray);
297         return;
298     }
299     auto jsonNode = JsonUtil::Create(true);
300     auto node = AceType::DynamicCast<FrameNode>(parent);
301     CHECK_NULL_VOID(node);
302     auto active = isActive && node->IsActive();
303     if (!isActive && !params_.enableAllNodes) {
304         return;
305     }
306     auto lp = node->GetLayoutProperty();
307     CHECK_NULL_VOID(lp);
308     bool isVisible = lp->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE;
309     if (!isVisible && !params_.enableAllNodes) {
310         return;
311     }
312     jsonNode->Put(INSPECTOR_ID, node->GetId());
313     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
314     RectF rect;
315     if (!CheckNodeRect(node, rect, params_.isVisibleOnly)) {
316         return;
317     }
318     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
319     size_ += 1;
320     GetWebContentIfNeed(node);
321     FillInspectorAttrs(parent, jsonNode);
322     std::list<RefPtr<NG::UINode>> children;
323     for (const auto& item : parent->GetChildrenForInspector(params_.enableCacheNode)) {
324         GetFrameNodeChildren(item, children);
325     }
326     auto jsonChildrenArray = JsonUtil::CreateArray(true);
327     for (auto uiNode : children) {
328         GetInspectorChildren(uiNode, jsonChildrenArray, active);
329     }
330     if (jsonChildrenArray->GetArraySize()) {
331         jsonNode->PutRef(INSPECTOR_CHILDREN, std::move(jsonChildrenArray));
332     }
333     jsonNodeArray->PutRef(std::move(jsonNode));
334 }
335 
GetSpanInspector(const RefPtr<UINode> & parent,std::unique_ptr<JsonValue> & jsonNodeArray)336 void SimplifiedInspector::GetSpanInspector(const RefPtr<UINode>& parent, std::unique_ptr<JsonValue>& jsonNodeArray)
337 {
338     // span rect follows parent text size
339     auto spanParentNode = parent->GetParent();
340     CHECK_NULL_VOID(spanParentNode);
341     auto node = AceType::DynamicCast<FrameNode>(spanParentNode);
342     CHECK_NULL_VOID(node);
343     auto jsonNode = JsonUtil::Create(true);
344 
345     FillInspectorAttrs(parent, jsonNode);
346 
347     jsonNode->Put(INSPECTOR_ID, parent->GetId());
348     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
349     RectF rect = node->GetTransformRectRelativeToWindow();
350     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
351     jsonNodeArray->PutRef(std::move(jsonNode));
352 }
353 
FillInspectorAttrs(const RefPtr<UINode> & parent,std::unique_ptr<JsonValue> & jsonNode)354 void SimplifiedInspector::FillInspectorAttrs(const RefPtr<UINode>& parent, std::unique_ptr<JsonValue>& jsonNode)
355 {
356     if (params_.isNewVersion) {
357         auto tmpJson = JsonUtil::Create(true);
358         parent->ToTreeJson(tmpJson, inspectorCfg_);
359         jsonNode->PutRef(INSPECTOR_ATTRS, std::move(tmpJson));
360         return;
361     }
362     auto tmpJson = JsonUtil::Create(true);
363     InspectorFilter filter;
364     parent->ToJsonValue(tmpJson, filter);
365     if (params_.enableFullAttrs) {
366         jsonNode->PutRef(INSPECTOR_ATTRS, std::move(tmpJson));
367         return;
368     }
369     jsonNode->Put(INSPECTOR_ATTR_ID, tmpJson->GetString(INSPECTOR_ATTR_ID).c_str());
370 
371     auto jsonObject = JsonUtil::Create(true);
372     if (tmpJson->Contains(INSPECTOR_LABEL)) {
373         jsonObject->Put(INSPECTOR_LABEL, tmpJson->GetString(INSPECTOR_LABEL).c_str());
374     }
375     if (tmpJson->Contains(INSPECTOR_CONTENT)) {
376         jsonObject->Put(INSPECTOR_CONTENT, tmpJson->GetString(INSPECTOR_CONTENT).c_str());
377     }
378     jsonObject->Put(INSPECTOR_ENABLED, tmpJson->GetBool(INSPECTOR_ENABLED));
379     jsonObject->Put(INSPECTOR_OPACITY, tmpJson->GetDouble(INSPECTOR_OPACITY));
380     jsonObject->Put(INSPECTOR_ZINDEX, tmpJson->GetInt(INSPECTOR_ZINDEX));
381     jsonObject->Put(INSPECTOR_VISIBILITY, tmpJson->GetString(INSPECTOR_VISIBILITY).c_str());
382     jsonNode->PutRef(INSPECTOR_ATTRS, std::move(jsonObject));
383 }
384 
CheckNodeRect(const RefPtr<FrameNode> & node,RectF & rect,bool isVisibleOnly)385 bool SimplifiedInspector::CheckNodeRect(const RefPtr<FrameNode>& node, RectF& rect, bool isVisibleOnly)
386 {
387     auto renderContext = node->GetRenderContext();
388     CHECK_NULL_RETURN(renderContext, false);
389     auto paintRect = renderContext->GetPaintRectWithoutTransform();
390     if (paintRect.IsEmpty()) {
391         return false;
392     }
393     rect = node->GetTransformRectRelativeToWindow();
394     if (isVisibleOnly && !deviceRect_.IsIntersectWith(rect)) {
395         return false;
396     }
397     return true;
398 }
399 
GetWebContentIfNeed(const RefPtr<FrameNode> & node)400 void SimplifiedInspector::GetWebContentIfNeed(const RefPtr<FrameNode>& node)
401 {
402     if (!isAsync_ || !collector_) {
403         return;
404     }
405     if (node->GetTag() != V2::WEB_ETS_TAG) {
406         return;
407     }
408 #if !defined(CROSS_PLATFORM) && defined(WEB_SUPPORTED)
409     if (params_.enableWeb && params_.webAccessibility && !params_.enableBackground) {
410         auto pattern = node->GetPattern<WebPattern>();
411         CHECK_NULL_VOID(pattern);
412         if (!pattern->GetActiveStatus()) {
413             return;
414         }
415         auto lambda = [collector = collector_](std::shared_ptr<JsonValue>& jsonValue, int32_t webId) {
416             std::string key = "Web_" + std::to_string(webId);
417             collector->GetJson()->Put(key.c_str(), jsonValue->ToString().c_str());
418             collector->DecreaseTaskNum();
419         };
420         collector_->IncreaseTaskNum();
421         pattern->GetAllWebAccessibilityNodeInfos(std::move(lambda), node->GetId(), false);
422         return;
423     }
424     if (params_.enableWeb && !params_.webContentJs.empty()) {
425         auto pattern = node->GetPattern<WebPattern>();
426         CHECK_NULL_VOID(pattern);
427         if (!pattern->GetActiveStatus()) {
428             return;
429         }
430         auto lambda = [webId = node->GetId(), collector = collector_](const std::string& result) {
431             std::string key = "Web_" + std::to_string(webId);
432             collector->GetJson()->Put(key.c_str(), result.c_str());
433             collector->DecreaseTaskNum();
434         };
435         collector_->IncreaseTaskNum();
436         if (!pattern->RunJavascriptAsync(params_.webContentJs, std::move(lambda))) {
437             collector_->DecreaseTaskNum();
438         }
439     }
440 #endif
441 }
442 
GetInspectorAsync(const std::shared_ptr<Recorder::InspectorTreeCollector> & collector)443 void SimplifiedInspector::GetInspectorAsync(const std::shared_ptr<Recorder::InspectorTreeCollector>& collector)
444 {
445 #if !defined(PREVIEW) && !defined(ACE_UNITTEST)
446     ContainerScope scope(Container::CurrentIdSafely());
447     CHECK_NULL_VOID(collector);
448     collector->CreateJson();
449     collector_ = collector;
450     isAsync_ = true;
451     TAG_LOGD(AceLogTag::ACE_UIEVENT, "Inspector2:container %{public}d", containerId_);
452     collector->IncreaseTaskNum();
453     auto& jsonRoot = collector->GetJson();
454     RefPtr<FrameNode> pageRootNode;
455     auto success = GetInspectorStep1(jsonRoot, pageRootNode);
456     if (!success) {
457         collector->DecreaseTaskNum();
458         return;
459     }
460     GetInspectorStep2(jsonRoot, pageRootNode);
461     collector->DecreaseTaskNum();
462 #endif
463 }
464 
GetInspectorBackgroundAsync(const std::shared_ptr<Recorder::InspectorTreeCollector> & collector)465 void SimplifiedInspector::GetInspectorBackgroundAsync(
466     const std::shared_ptr<Recorder::InspectorTreeCollector>& collector)
467 {
468     ContainerScope scope(Container::CurrentIdSafely());
469     CHECK_NULL_VOID(collector);
470     collector->CreateJson();
471     collector_ = collector;
472     isAsync_ = true;
473     auto context = NG::PipelineContext::GetContextByContainerId(containerId_);
474     CHECK_NULL_VOID(context);
475     CHECK_NULL_VOID(context->GetStageManager());
476     auto pageRootNode = context->GetStageManager()->GetLastPage();
477     CHECK_NULL_VOID(pageRootNode);
478     pageId_ = pageRootNode->GetPageId();
479     auto pagePattern = pageRootNode->GetPattern<PagePattern>();
480     CHECK_NULL_VOID(pagePattern);
481     auto pageInfo = pagePattern->GetPageInfo();
482     CHECK_NULL_VOID(pageInfo);
483     auto pageUrl = pageInfo->GetPageUrl();
484     auto pageName = context->GetCurrentPageNameCallback();
485 
486     auto treeNode = std::make_shared<SimplifiedInspectorTree>();
487     GetInspectorTreeNode(pageRootNode, treeNode);
488 
489     CHECK_NULL_VOID(context->GetTaskExecutor());
490     collector->SetTaskExecutor(context->GetTaskExecutor());
491     collector->IncreaseTaskNum();
492     context->GetTaskExecutor()->PostTask(
493         [inspector = shared_from_this(), context, pageUrl, pageName, treeNode]() {
494             auto& jsonRoot = inspector->collector_->GetJson();
495             jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
496             auto scale = context->GetViewScale();
497             auto rootHeight = context->GetRootHeight();
498             auto rootWidth = context->GetRootWidth();
499             inspector->deviceRect_.SetRect(0, 0, rootWidth * scale, rootHeight * scale);
500             jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
501             jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
502             jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(SystemProperties::GetResolution()).c_str());
503             jsonRoot->Put(INSPECTOR_ABILITY, AceApplicationInfo::GetInstance().GetAbilityName().c_str());
504             jsonRoot->Put(INSPECTOR_BUNDLE, AceApplicationInfo::GetInstance().GetPackageName().c_str());
505             jsonRoot->Put(INSPECTOR_PAGE_URL, pageUrl.c_str());
506             jsonRoot->Put(INSPECTOR_NAV_DST_NAME, pageName.c_str());
507             auto jsonNodeArray = JsonUtil::CreateArray(true);
508             inspector->size_ = 1;
509             for (auto& subTreeNode : treeNode->children) {
510                 inspector->GetInspectorChildrenBackground(subTreeNode, jsonNodeArray);
511             }
512             if (jsonNodeArray->GetArraySize()) {
513                 jsonRoot->PutRef(INSPECTOR_CHILDREN, std::move(jsonNodeArray));
514             }
515             jsonRoot->Put(INSPECTOR_CHILDREN_COUNT, inspector->size_);
516             inspector->collector_->DecreaseTaskNum();
517         }, TaskExecutor::TaskType::BACKGROUND, "GetSimplifiedInspector");
518 }
519 
GetInspectorTreeNode(const RefPtr<NG::UINode> & pageRootNode,std::shared_ptr<SimplifiedInspectorTree> & root)520 void SimplifiedInspector::GetInspectorTreeNode(
521     const RefPtr<NG::UINode>& pageRootNode, std::shared_ptr<SimplifiedInspectorTree>& root)
522 {
523     collector_->RetainNode(pageRootNode);
524     std::list<RefPtr<NG::UINode>> children;
525     for (const auto& item : pageRootNode->GetChildrenForInspector(params_.enableCacheNode)) {
526         GetFrameNodeChildren(item, children);
527     }
528     auto overlayNode2 = GetOverlayNode(pageRootNode);
529     if (overlayNode2) {
530         GetFrameNodeChildren(overlayNode2, children);
531     }
532     root->node = pageRootNode;
533     std::list<std::shared_ptr<SimplifiedInspectorTree>> childNodes;
534     for (const auto& uiNode : children) {
535         auto treeNode = std::make_shared<SimplifiedInspectorTree>();
536         GetInspectorTreeNodeChildren(uiNode, treeNode, true);
537         if (treeNode->node.Upgrade()) {
538             childNodes.emplace_back(treeNode);
539         }
540     }
541     root->children = std::move(childNodes);
542 }
543 
GetInspectorTreeNodeChildren(const RefPtr<NG::UINode> & parent,std::shared_ptr<SimplifiedInspectorTree> & treeNode,bool isActive)544 void SimplifiedInspector::GetInspectorTreeNodeChildren(
545     const RefPtr<NG::UINode>& parent, std::shared_ptr<SimplifiedInspectorTree>& treeNode, bool isActive)
546 {
547     if (AceType::InstanceOf<SpanNode>(parent)) {
548         treeNode->node = parent;
549         return;
550     }
551     auto node = AceType::DynamicCast<FrameNode>(parent);
552     if (!node) {
553         return;
554     }
555     auto active = isActive && node->IsActive();
556     if (!isActive && !params_.enableAllNodes) {
557         return;
558     }
559     treeNode->node = parent;
560     std::list<RefPtr<NG::UINode>> children;
561     for (const auto& item : parent->GetChildrenForInspector(params_.enableCacheNode)) {
562         GetFrameNodeChildren(item, children);
563     }
564     for (auto uiNode : children) {
565         auto subTreeNode = std::make_shared<SimplifiedInspectorTree>();
566         GetInspectorTreeNodeChildren(uiNode, subTreeNode, active);
567         if (subTreeNode->node.Upgrade()) {
568             treeNode->children.emplace_back(subTreeNode);
569         }
570     }
571 }
572 
GetInspectorChildrenBackground(const std::shared_ptr<SimplifiedInspectorTree> & treeNode,std::unique_ptr<OHOS::Ace::JsonValue> & jsonNodeArray)573 void SimplifiedInspector::GetInspectorChildrenBackground(
574     const std::shared_ptr<SimplifiedInspectorTree>& treeNode, std::unique_ptr<OHOS::Ace::JsonValue>& jsonNodeArray)
575 {
576     auto parent = treeNode->node.Upgrade();
577     CHECK_NULL_VOID(parent);
578     // Span is a special case in Inspector since span inherits from UINode
579     if (AceType::InstanceOf<SpanNode>(parent)) {
580         size_ += 1;
581         GetSpanInspector(parent, jsonNodeArray);
582         return;
583     }
584     auto jsonNode = JsonUtil::Create(true);
585     auto node = AceType::DynamicCast<FrameNode>(parent);
586     CHECK_NULL_VOID(node);
587     auto lp = node->GetLayoutProperty();
588     CHECK_NULL_VOID(lp);
589     bool isVisible = lp->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE;
590     if (!isVisible && !params_.enableAllNodes) {
591         return;
592     }
593     jsonNode->Put(INSPECTOR_ID, node->GetId());
594     jsonNode->Put(INSPECTOR_TYPE, parent->GetTag().c_str());
595     RectF rect;
596     if (!CheckNodeRect(node, rect, params_.isVisibleOnly)) {
597         return;
598     }
599     jsonNode->Put(INSPECTOR_RECT, rect.ToBounds().c_str());
600     size_ += 1;
601     GetWebContentIfNeed(node);
602     FillInspectorAttrs(parent, jsonNode);
603     std::list<RefPtr<NG::UINode>> children;
604     for (const auto& item : parent->GetChildrenForInspector(params_.enableCacheNode)) {
605         GetFrameNodeChildren(item, children);
606     }
607     auto jsonChildrenArray = JsonUtil::CreateArray(true);
608     for (auto subTreeNode : treeNode->children) {
609         GetInspectorChildrenBackground(subTreeNode, jsonChildrenArray);
610     }
611     if (jsonChildrenArray->GetArraySize()) {
612         jsonNode->PutRef(INSPECTOR_CHILDREN, std::move(jsonChildrenArray));
613     }
614     jsonNodeArray->PutRef(std::move(jsonNode));
615 }
616 
ExecuteUICommand(const std::shared_ptr<Recorder::InspectorTreeCollector> & collector)617 void SimplifiedInspector::ExecuteUICommand(const std::shared_ptr<Recorder::InspectorTreeCollector>& collector)
618 {
619     CHECK_NULL_VOID(collector);
620     collector_ = collector;
621     ContainerScope scope(Container::CurrentIdSafely());
622     collector->CreateJson();
623     collector->IncreaseTaskNum();
624     ScrollCommand command;
625     if (!ParseCommandParam(commandParams_.params, command)) {
626         collector->GetJson()->Put(KEY_CODE, ERR_INVALID_PARAM);
627         collector->DecreaseTaskNum();
628         return;
629     }
630     auto context = PipelineContext::GetCurrentContext();
631     CHECK_NULL_VOID(context);
632     CHECK_NULL_VOID(context->GetStageManager());
633     auto pageRootNode = context->GetStageManager()->GetLastPage();
634     CHECK_NULL_VOID(pageRootNode);
635     if (command.type == TargetType::NODE) {
636         TAG_LOGD(AceLogTag::ACE_UIEVENT, "ExecuteUICommand node");
637         auto ret = ScrollToTarget(command, pageRootNode);
638         collector->GetJson()->Put(KEY_CODE, ret);
639         collector->DecreaseTaskNum();
640     } else if (command.type == TargetType::WEB) {
641         TAG_LOGD(AceLogTag::ACE_UIEVENT, "ExecuteUICommand web");
642         auto ret = ExecuteWebScrollCommand(pageRootNode, command.nodeId, command.webContentJs);
643         if (ret != ERR_OK) {
644             collector->GetJson()->Put(KEY_CODE, ret);
645             collector->DecreaseTaskNum();
646         }
647     }
648 }
649 
ExecuteWebScrollCommand(const RefPtr<FrameNode> & rootNode,int32_t nodeId,const std::string & jsCode)650 int32_t SimplifiedInspector::ExecuteWebScrollCommand(
651     const RefPtr<FrameNode>& rootNode, int32_t nodeId, const std::string& jsCode)
652 {
653 #if !defined(CROSS_PLATFORM) && defined(WEB_SUPPORTED)
654     if (jsCode.empty()) {
655         return ERR_INVALID_PARAM;
656     }
657     auto targetNode = GetNodeById(rootNode, nodeId);
658     CHECK_NULL_RETURN(targetNode, ERR_NOT_FOUND_TARGET_NODE);
659     if (targetNode->GetTag() != V2::WEB_ETS_TAG) {
660         return ERR_NOT_FOUND_TARGET_NODE;
661     }
662     auto frameNode = AceType::DynamicCast<NG::FrameNode>(targetNode);
663     CHECK_NULL_RETURN(frameNode, ERR_NOT_FOUND_TARGET_NODE);
664     auto pattern = frameNode->GetPattern<WebPattern>();
665     CHECK_NULL_RETURN(pattern, ERR_NOT_FOUND_TARGET_NODE);
666     pattern->RunJavascriptAsync(jsCode, [collector = collector_](const std::string& result) {
667         collector->GetJson()->Put(KEY_CODE, ERR_OK);
668         collector->GetJson()->Put("ret", result.c_str());
669         collector->DecreaseTaskNum();
670     });
671     return ERR_OK;
672 #else
673     return ERR_NOT_FOUND_TARGET_NODE;
674 #endif
675 }
676 } // namespace OHOS::Ace::NG
677