• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "core/common/recorder/node_data_cache.h"
16 
17 #include "core/components_ng/pattern/stage/page_pattern.h"
18 
19 namespace OHOS::Ace::Recorder {
20 constexpr int32_t PAGE_URL_SUFFIX_LENGTH = 3;
21 
GetPageUrlByNode(const RefPtr<NG::FrameNode> & node)22 std::string GetPageUrlByNode(const RefPtr<NG::FrameNode>& node)
23 {
24     auto pageNode = node->GetPageNode();
25     CHECK_NULL_RETURN(pageNode, "");
26     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
27     CHECK_NULL_RETURN(pagePattern, "");
28     return pagePattern->GetPageUrl();
29 }
30 
GetPageUrlByContainer(const RefPtr<Container> & container)31 const std::string GetPageUrlByContainer(const RefPtr<Container>& container)
32 {
33     CHECK_RUN_ON(UI);
34     auto frontEnd = container->GetFrontend();
35     CHECK_NULL_RETURN(frontEnd, "");
36     auto pageUrl = frontEnd->GetCurrentPageUrl();
37     // remove .js suffix if exists
38     if (StringUtils::EndWith(pageUrl, ".js")) {
39         return pageUrl.substr(0, pageUrl.length() - PAGE_URL_SUFFIX_LENGTH);
40     }
41     return pageUrl;
42 }
43 
GetPageUrlByContainerId(const int32_t containerId)44 std::string GetPageUrlByContainerId(const int32_t containerId)
45 {
46     auto container = Container::GetContainer(containerId);
47     CHECK_NULL_RETURN(container, "");
48     return GetPageUrlByContainer(container);
49 }
50 
GetCurrentPageUrl()51 std::string GetCurrentPageUrl()
52 {
53     auto container = Container::Current();
54     CHECK_NULL_RETURN(container, "");
55     return GetPageUrlByContainer(container);
56 }
57 
Get()58 NodeDataCache& NodeDataCache::Get()
59 {
60     static NodeDataCache cache;
61     return cache;
62 }
63 
NodeDataCache()64 NodeDataCache::NodeDataCache()
65 {
66     container_ = std::make_shared<NodeDataContainer>();
67     mergedConfig_ = std::make_shared<MergedConfig>();
68 }
69 
OnPageReady()70 void NodeDataCache::OnPageReady()
71 {
72     prePageUrl_ = pageUrl_;
73     pageUrl_ = GetCurrentPageUrl();
74 }
75 
OnPageShow(const std::string & pageUrl)76 void NodeDataCache::OnPageShow(const std::string& pageUrl)
77 {
78     prePageUrl_ = pageUrl_;
79     pageUrl_ = pageUrl;
80 }
81 
OnBeforePagePop(bool destroy)82 void NodeDataCache::OnBeforePagePop(bool destroy)
83 {
84     if (destroy) {
85         Clear(prePageUrl_);
86     } else {
87         Clear(pageUrl_);
88     }
89     shouldCollectFull_ = false;
90 }
91 
UpdateConfig(std::shared_ptr<MergedConfig> && mergedConfig)92 void NodeDataCache::UpdateConfig(std::shared_ptr<MergedConfig>&& mergedConfig)
93 {
94     std::unique_lock<std::shared_mutex> lock(configMutex_);
95     mergedConfig_ = mergedConfig;
96     shouldCollectFull_ = false;
97 }
98 
PutString(const RefPtr<NG::FrameNode> & node,const std::string & id,const std::string & value)99 bool NodeDataCache::PutString(const RefPtr<NG::FrameNode>& node, const std::string& id, const std::string& value)
100 {
101     if (id.empty() || value.empty() || value.length() > MAX_DATA_LENGTH) {
102         return false;
103     }
104     if (mergedConfig_->shareNodes.empty()) {
105         return false;
106     }
107     auto pageUrl = GetPageUrlByNode(node);
108     if (pageUrl.empty()) {
109         return false;
110     }
111     std::shared_lock<std::shared_mutex> configLock(configMutex_);
112     auto iter = mergedConfig_->shareNodes.find(pageUrl);
113     if (!shouldCollectFull_ && iter == mergedConfig_->shareNodes.end()) {
114         return false;
115     }
116     if (shouldCollectFull_ || iter->second.find(id) != iter->second.end()) {
117         std::unique_lock<std::shared_mutex> cacheLock(cacheMutex_);
118         auto iter = container_->find(pageUrl);
119         if (iter == container_->end()) {
120             auto pageContainer = std::unordered_map<std::string, std::string>();
121             pageContainer.emplace(id, value);
122             container_->emplace(pageUrl, std::move(pageContainer));
123         } else {
124             if (iter->second.size() >= MAX_SIZE_PER_PAGE) {
125                 return false;
126             }
127             iter->second[id] = value;
128         }
129     }
130     return true;
131 }
132 
PutBool(const RefPtr<NG::FrameNode> & node,const std::string & id,bool value)133 bool NodeDataCache::PutBool(const RefPtr<NG::FrameNode>& node, const std::string& id, bool value)
134 {
135     std::string strVal = value ? "true" : "false";
136     return PutString(node, id, strVal);
137 }
138 
PutInt(const RefPtr<NG::FrameNode> & node,const std::string & id,int value)139 bool NodeDataCache::PutInt(const RefPtr<NG::FrameNode>& node, const std::string& id, int value)
140 {
141     return PutString(node, id, std::to_string(value));
142 }
143 
PutStringArray(const RefPtr<NG::FrameNode> & node,const std::string & id,const std::vector<std::string> & value)144 bool NodeDataCache::PutStringArray(
145     const RefPtr<NG::FrameNode>& node, const std::string& id, const std::vector<std::string>& value)
146 {
147     auto jsonArray = JsonUtil::CreateArray(true);
148     for (size_t i = 0; i < value.size(); i++) {
149         jsonArray->Put(std::to_string(i).c_str(), value.at(i).c_str());
150     }
151     return PutString(node, id, jsonArray->ToString());
152 }
153 
PutMultiple(const RefPtr<NG::FrameNode> & node,const std::string & id,const std::string & name,bool value)154 bool NodeDataCache::PutMultiple(
155     const RefPtr<NG::FrameNode>& node, const std::string& id, const std::string& name, bool value)
156 {
157     auto json = JsonUtil::Create(true);
158     json->Put(KEY_TEXT, name.c_str());
159     json->Put(KEY_CHECKED, value);
160     return PutString(node, id, json->ToString());
161 }
162 
PutMultiple(const RefPtr<NG::FrameNode> & node,const std::string & id,const std::string & name,int index)163 bool NodeDataCache::PutMultiple(
164     const RefPtr<NG::FrameNode>& node, const std::string& id, const std::string& name, int index)
165 {
166     auto json = JsonUtil::Create(true);
167     json->Put(KEY_TEXT, name.c_str());
168     json->Put(KEY_INDEX, index);
169     return PutString(node, id, json->ToString());
170 }
171 
PutMultiple(const RefPtr<NG::FrameNode> & node,const std::string & id,const std::string & name,const std::vector<std::string> & value)172 bool NodeDataCache::PutMultiple(const RefPtr<NG::FrameNode>& node, const std::string& id, const std::string& name,
173     const std::vector<std::string>& value)
174 {
175     auto json = JsonUtil::Create(true);
176     json->Put(KEY_TEXT, name.c_str());
177     auto jsonArray = JsonUtil::CreateArray(true);
178     for (size_t i = 0; i < value.size(); i++) {
179         jsonArray->Put(std::to_string(i).c_str(), value.at(i).c_str());
180     }
181     json->Put(KEY_TEXT_ARRAY, jsonArray);
182     return PutString(node, id, json->ToString());
183 }
184 
GetNodeData(const std::string & pageUrl,std::unordered_map<std::string,std::string> & nodes)185 void NodeDataCache::GetNodeData(const std::string& pageUrl, std::unordered_map<std::string, std::string>& nodes)
186 {
187     if (pageUrl.empty()) {
188         return;
189     }
190     std::shared_lock<std::shared_mutex> lock(cacheMutex_);
191     auto iter = container_->find(pageUrl);
192     if (iter == container_->end()) {
193         return;
194     }
195     for (auto nodeIter = nodes.begin(); nodeIter != nodes.end(); nodeIter++) {
196         auto it = iter->second.find(nodeIter->first);
197         if (it != iter->second.end()) {
198             nodes[it->first] = it->second;
199         }
200     }
201 }
202 
Clear(const std::string & pageUrl)203 void NodeDataCache::Clear(const std::string& pageUrl)
204 {
205     if (pageUrl.empty()) {
206         return;
207     }
208     std::unique_lock<std::shared_mutex> lock(cacheMutex_);
209     auto iter = container_->find(pageUrl);
210     if (iter != container_->end()) {
211         container_->erase(iter);
212     }
213 }
214 
Reset()215 void NodeDataCache::Reset()
216 {
217     std::unique_lock<std::shared_mutex> lock(cacheMutex_);
218     container_->clear();
219     pageUrl_ = "";
220     prePageUrl_ = "";
221 }
222 
GetExposureCfg(const std::string & pageUrl,const std::string & inspectId,ExposureCfg & cfg)223 void NodeDataCache::GetExposureCfg(const std::string& pageUrl, const std::string& inspectId, ExposureCfg& cfg)
224 {
225     if (pageUrl.empty()) {
226         return;
227     }
228     std::shared_lock<std::shared_mutex> configLock(configMutex_);
229     auto iter = mergedConfig_->exposureNodes.find(pageUrl);
230     if (iter == mergedConfig_->exposureNodes.end()) {
231         return;
232     }
233     auto cfgIter = iter->second.find({ inspectId, 0.0, 0 });
234     if (cfgIter == iter->second.end()) {
235         return;
236     }
237     cfg.id = cfgIter->id;
238     cfg.ratio = cfgIter->ratio;
239     cfg.duration = cfgIter->duration;
240 }
241 } // namespace OHOS::Ace::Recorder
242