1 /* 2 * Copyright (c) 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 "json.hpp" 17 #include "ui_model.h" 18 19 namespace OHOS::uitest { 20 using namespace std; 21 using namespace nlohmann; 22 23 struct DumperCache { 24 std::map<std::string, int> visitWidgetMap_; 25 std::map<std::string, int> widgetCountMap_; 26 std::set<std::string> visibleWidgetHies_; 27 }; 28 GetMiddleStr(string_view str, size_t &index, string_view startStr, string_view endStr)29 static string_view GetMiddleStr(string_view str, size_t &index, string_view startStr, string_view endStr) 30 { 31 size_t ori = index; 32 auto begin = str.find(startStr, index); 33 if (begin != string::npos) { 34 index = begin + startStr.size(); 35 auto end = str.find(endStr, index); 36 if (end != string::npos) { 37 string_view result = str.substr(index, end - index); 38 index = end; 39 return result; 40 } 41 } 42 index = ori; 43 return ""; 44 } 45 HasVisibleChild(const std::set<std::string> &visibleWidgetHies, const string &hie)46 static bool HasVisibleChild(const std::set<std::string> &visibleWidgetHies, const string &hie) 47 { 48 for (auto visibleHie : visibleWidgetHies) { 49 if (visibleHie.find(hie) != string::npos) { 50 return true; 51 } 52 } 53 return false; 54 } 55 DFSMarshalWidget(std::vector<Widget> &allWidget, int index, nlohmann::json &dom, const DumperCache &cache)56 static void DFSMarshalWidget(std::vector<Widget> &allWidget, int index, nlohmann::json &dom, 57 const DumperCache &cache) 58 { 59 auto attrData = json(); 60 allWidget.at(index).WrapperWidgetToJson(attrData); 61 auto childrenData = json::array(); 62 int childIndex = 0; 63 int childCount = 0; 64 int childVisit = 0; 65 auto hierarchy = allWidget.at(index).GetHierarchy(); 66 if (cache.widgetCountMap_.find(hierarchy) != cache.widgetCountMap_.cend()) { 67 childCount = cache.widgetCountMap_.at(hierarchy); 68 } 69 while (childVisit < childCount) { 70 auto tempChildHierarchy = WidgetHierarchyBuilder::GetChildHierarchy(hierarchy, childIndex); 71 ++childIndex; 72 if (cache.visitWidgetMap_.find(tempChildHierarchy) == cache.visitWidgetMap_.cend()) { 73 continue; 74 } 75 auto childWidIndex = cache.visitWidgetMap_.at(tempChildHierarchy); 76 if (!allWidget.at(childWidIndex).IsVisible()) { 77 if (!HasVisibleChild(cache.visibleWidgetHies_, tempChildHierarchy)) { 78 ++childVisit; 79 continue; 80 } 81 } 82 auto childData = json(); 83 DFSMarshalWidget(allWidget, childWidIndex, childData, cache); 84 childrenData.emplace_back(childData); 85 ++childVisit; 86 } 87 dom["attributes"] = attrData; 88 dom["children"] = childrenData; 89 } 90 AddExtraAttrs(nlohmann::json &root, const map<int32_t, string_view> &elementTrees, size_t index)91 void DumpHandler::AddExtraAttrs(nlohmann::json &root, const map<int32_t, string_view> &elementTrees, size_t index) 92 { 93 auto windowIdValue = root["attributes"]["hostWindowId"].dump(); 94 auto windowId = atoi(windowIdValue.substr(1, windowIdValue.size() - 2).c_str()); 95 auto find = elementTrees.find(windowId); 96 auto elementTree = (find != elementTrees.end()) ? find->second : ""; 97 string_view nodeEndStr = "|->"; 98 auto accessibilityIdInfo = root["attributes"]["accessibilityId"].dump(); 99 auto accessibilityId = accessibilityIdInfo.substr(1, accessibilityIdInfo.size() - 2); 100 string_view accessibilityIdStr = "AccessibilityId: " + accessibilityId; 101 string_view nodeAttrStr = GetMiddleStr(elementTree, index, accessibilityIdStr, nodeEndStr); 102 auto extraAttrs = json(); 103 size_t nodeAttrTraverlIndex = 0; 104 auto backgroundColor = GetMiddleStr(nodeAttrStr, nodeAttrTraverlIndex, "BackgroundColor: ", "\n"); 105 auto content = GetMiddleStr(nodeAttrStr, nodeAttrTraverlIndex, "Content: ", "\n"); 106 auto fontColor = GetMiddleStr(nodeAttrStr, nodeAttrTraverlIndex, "FontColor: ", "\n"); 107 auto fontSize = GetMiddleStr(nodeAttrStr, nodeAttrTraverlIndex, "FontSize: ", "\n"); 108 if (!backgroundColor.empty()) { 109 extraAttrs["BackgroundColor"] = backgroundColor; 110 } 111 if (!content.empty()) { 112 extraAttrs["Content"] = move(content); 113 } 114 if (!fontColor.empty()) { 115 extraAttrs["FontColor"] = move(fontColor); 116 } 117 if (!fontSize.empty()) { 118 extraAttrs["FontSize"] = move(fontSize); 119 } 120 if (!extraAttrs.empty()) { 121 root["extraAttrs"] = extraAttrs; 122 } 123 auto &childrenData = root["children"]; 124 auto childCount = childrenData.size(); 125 for (size_t idx = 0; idx < childCount; idx++) { 126 auto &child = childrenData.at(idx); 127 AddExtraAttrs(child, elementTrees, index); 128 } 129 } 130 DumpWindowInfoToJson(vector<Widget> &allWidget, nlohmann::json &root)131 void DumpHandler::DumpWindowInfoToJson(vector<Widget> &allWidget, nlohmann::json &root) 132 { 133 DumperCache cache; 134 for (size_t i = 0; i < allWidget.size(); ++i) { 135 const Widget &wid = allWidget.at(i); 136 std::string hie = wid.GetHierarchy(); 137 cache.visitWidgetMap_.emplace(hie, i); 138 std::string parentHie = WidgetHierarchyBuilder::GetParentWidgetHierarchy(hie); 139 if (cache.widgetCountMap_.find(parentHie) == cache.widgetCountMap_.cend()) { 140 cache.widgetCountMap_[parentHie] = 1; 141 } else { 142 cache.widgetCountMap_[parentHie] = cache.widgetCountMap_[parentHie] + 1; 143 } 144 if (wid.IsVisible()) { 145 cache.visibleWidgetHies_.insert(hie); 146 } 147 } 148 DFSMarshalWidget(allWidget, 0, root, cache); 149 } 150 } // namespace OHOS::uitest