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/event_recorder.h"
16
17 #include "core/common/container.h"
18 #include "core/common/recorder/event_controller.h"
19 #include "core/common/recorder/node_data_cache.h"
20
21 namespace OHOS::Ace::Recorder {
22 constexpr char IGNORE_WINDOW_NAME[] = "$HA_FLOAT_WINDOW$";
23
IsCacheAvaliable()24 bool IsCacheAvaliable()
25 {
26 return EventRecorder::Get().IsComponentRecordEnable() && !NodeDataCache::Get().IsShareNodeEmpty();
27 }
28
EventParamsBuilder()29 EventParamsBuilder::EventParamsBuilder()
30 {
31 params_ = std::make_shared<std::unordered_map<std::string, std::string>>();
32 }
33
SetEventType(EventType eventType)34 EventParamsBuilder& EventParamsBuilder::SetEventType(EventType eventType)
35 {
36 eventType_ = eventType;
37 return *this;
38 }
39
SetId(const std::string & id)40 EventParamsBuilder& EventParamsBuilder::SetId(const std::string& id)
41 {
42 if (!id.empty()) {
43 params_->emplace(KEY_ID, id);
44 }
45 return *this;
46 }
47
SetType(const std::string & type)48 EventParamsBuilder& EventParamsBuilder::SetType(const std::string& type)
49 {
50 params_->emplace(KEY_TYPE, type);
51 return *this;
52 }
53
SetDescription(const std::string & desc)54 EventParamsBuilder& EventParamsBuilder::SetDescription(const std::string& desc)
55 {
56 if (!desc.empty()) {
57 params_->emplace(KEY_DESCRIPTION, desc);
58 }
59 return *this;
60 }
61
SetNavDst(const std::string & dstName)62 EventParamsBuilder& EventParamsBuilder::SetNavDst(const std::string& dstName)
63 {
64 if (!dstName.empty()) {
65 params_->emplace(KEY_NAV_DST, dstName);
66 }
67 return *this;
68 }
69
SetPageUrl(const std::string & pageUrl)70 EventParamsBuilder& EventParamsBuilder::SetPageUrl(const std::string& pageUrl)
71 {
72 if (!pageUrl.empty()) {
73 params_->emplace(KEY_PAGE, pageUrl);
74 }
75 return *this;
76 }
77
SetText(const std::string & value)78 EventParamsBuilder& EventParamsBuilder::SetText(const std::string& value)
79 {
80 if (!value.empty()) {
81 params_->emplace(KEY_TEXT, value);
82 }
83 return *this;
84 }
85
SetChecked(bool value)86 EventParamsBuilder& EventParamsBuilder::SetChecked(bool value)
87 {
88 std::string strVal = value ? "true" : "false";
89 params_->emplace(KEY_CHECKED, strVal);
90 return *this;
91 }
92
SetIndex(int value)93 EventParamsBuilder& EventParamsBuilder::SetIndex(int value)
94 {
95 params_->emplace(KEY_INDEX, std::to_string(value));
96 return *this;
97 }
98
SetTextArray(const std::vector<std::string> & value)99 EventParamsBuilder& EventParamsBuilder::SetTextArray(const std::vector<std::string>& value)
100 {
101 auto jsonArray = JsonUtil::CreateArray(true);
102 for (size_t i = 0; i < value.size(); i++) {
103 jsonArray->Put(std::to_string(i).c_str(), value.at(i).c_str());
104 }
105 params_->emplace(KEY_TEXT_ARRAY, jsonArray->ToString());
106 return *this;
107 }
108
SetExtra(const std::string & key,const std::string & value)109 EventParamsBuilder& EventParamsBuilder::SetExtra(const std::string& key, const std::string& value)
110 {
111 if (!key.empty() && !value.empty()) {
112 params_->emplace(key, value);
113 }
114 return *this;
115 }
116
build()117 std::shared_ptr<std::unordered_map<std::string, std::string>> EventParamsBuilder::build()
118 {
119 return params_;
120 }
121
GetEventType() const122 EventType EventParamsBuilder::GetEventType() const
123 {
124 return eventType_;
125 }
126
GetText() const127 std::string EventParamsBuilder::GetText() const
128 {
129 auto iter = params_->find(KEY_TEXT);
130 if (iter != params_->end()) {
131 return iter->second;
132 }
133 return "";
134 }
135
ToString() const136 std::string EventParamsBuilder::ToString() const
137 {
138 std::stringstream ss;
139 ss << "{";
140 if (eventType_ != EventType::INVALID) {
141 ss << "eventType:" << eventType_ << ", ";
142 }
143 for (auto&& it : *params_) {
144 ss << it.first << ":" << it.second << ", ";
145 }
146 ss << "}";
147 return ss.str();
148 }
149
MapToString(const std::shared_ptr<std::unordered_map<std::string,std::string>> & input)150 std::string MapToString(const std::shared_ptr<std::unordered_map<std::string, std::string>>& input)
151 {
152 if (!input) {
153 return "";
154 }
155 std::stringstream ss;
156 ss << "{";
157 for (auto it = input->begin(); it != input->end(); it++) {
158 ss << it->first << ":" << it->second << ", ";
159 }
160 ss << "}";
161 return ss.str();
162 }
163
Get()164 EventRecorder& EventRecorder::Get()
165 {
166 static EventRecorder eventRecorder;
167 return eventRecorder;
168 }
169
EventRecorder()170 EventRecorder::EventRecorder() {}
171
UpdateEventSwitch(const EventSwitch & eventSwitch)172 void EventRecorder::UpdateEventSwitch(const EventSwitch& eventSwitch)
173 {
174 eventSwitch_ = eventSwitch;
175 }
176
IsPageRecordEnable() const177 bool EventRecorder::IsPageRecordEnable() const
178 {
179 return pageEnable_ && eventSwitch_.pageEnable;
180 }
181
IsPageParamRecordEnable() const182 bool EventRecorder::IsPageParamRecordEnable() const
183 {
184 return pageParamEnable_ && eventSwitch_.pageParamEnable;
185 }
186
IsExposureRecordEnable() const187 bool EventRecorder::IsExposureRecordEnable() const
188 {
189 return exposureEnable_ && eventSwitch_.exposureEnable;
190 }
191
IsComponentRecordEnable() const192 bool EventRecorder::IsComponentRecordEnable() const
193 {
194 return componentEnable_ && eventSwitch_.componentEnable;
195 }
196
SetContainerInfo(const std::string & windowName,int32_t id,bool foreground)197 void EventRecorder::SetContainerInfo(const std::string& windowName, int32_t id, bool foreground)
198 {
199 if (windowName == IGNORE_WINDOW_NAME) {
200 return;
201 }
202 if (foreground) {
203 containerId_ = id;
204 containerCount_++;
205 } else {
206 containerCount_--;
207 }
208 if (containerCount_ <= 0) {
209 containerCount_ = 0;
210 containerId_ = -1;
211 }
212 }
213
SetFocusContainerInfo(const std::string & windowName,int32_t id)214 void EventRecorder::SetFocusContainerInfo(const std::string& windowName, int32_t id)
215 {
216 isFocusContainerChanged_ = focusContainerId_ != id;
217 if (windowName == IGNORE_WINDOW_NAME) {
218 return;
219 }
220 focusContainerId_ = id;
221 }
222
GetContainerId()223 int32_t EventRecorder::GetContainerId()
224 {
225 if (containerId_ == -1) {
226 return -1;
227 }
228 return focusContainerId_;
229 }
230
GetPageUrl()231 const std::string& EventRecorder::GetPageUrl()
232 {
233 if (pageUrl_.empty() || isFocusContainerChanged_) {
234 pageUrl_ = GetCurrentPageUrl();
235 }
236 return pageUrl_;
237 }
238
GetNavDstName() const239 const std::string& EventRecorder::GetNavDstName() const
240 {
241 return navDstName_;
242 }
243
OnPageShow(const std::string & pageUrl,const std::string & param)244 void EventRecorder::OnPageShow(const std::string& pageUrl, const std::string& param)
245 {
246 pageUrl_ = pageUrl;
247 NodeDataCache::Get().OnPageShow(pageUrl);
248 Recorder::EventParamsBuilder builder;
249 builder.SetType(std::to_string(PageEventType::ROUTER_PAGE))
250 .SetText(pageUrl)
251 .SetExtra(Recorder::KEY_PAGE_PARAM, param);
252 EventController::Get().NotifyEvent(
253 EventCategory::CATEGORY_PAGE, static_cast<int32_t>(EventType::PAGE_SHOW), std::move(builder.build()));
254 }
255
OnPageHide(const std::string & pageUrl,const int64_t duration)256 void EventRecorder::OnPageHide(const std::string& pageUrl, const int64_t duration)
257 {
258 Recorder::EventParamsBuilder builder;
259 builder.SetType(std::to_string(PageEventType::ROUTER_PAGE))
260 .SetText(pageUrl)
261 .SetExtra(KEY_DURATION, std::to_string(duration));
262 EventController::Get().NotifyEvent(
263 EventCategory::CATEGORY_PAGE, static_cast<int32_t>(EventType::PAGE_HIDE), std::move(builder.build()));
264 }
265
OnClick(EventParamsBuilder && builder)266 void EventRecorder::OnClick(EventParamsBuilder&& builder)
267 {
268 if (!taskExecutor_) {
269 auto container = Container::Current();
270 CHECK_NULL_VOID(container);
271 taskExecutor_ = container->GetTaskExecutor();
272 }
273 CHECK_NULL_VOID(taskExecutor_);
274 builder.SetPageUrl(GetPageUrl());
275 builder.SetNavDst(navDstName_);
276 auto params = builder.build();
277 taskExecutor_->PostTask(
278 [taskExecutor = taskExecutor_, params]() {
279 EventController::Get().NotifyEvent(
280 EventCategory::CATEGORY_COMPONENT, static_cast<int32_t>(EventType::CLICK), std::move(params));
281 },
282 TaskExecutor::TaskType::UI, "ArkUINotifyClickEvent");
283 }
284
OnChange(EventParamsBuilder && builder)285 void EventRecorder::OnChange(EventParamsBuilder&& builder)
286 {
287 builder.SetPageUrl(GetPageUrl());
288 builder.SetNavDst(navDstName_);
289 auto params = builder.build();
290 EventController::Get().NotifyEvent(
291 EventCategory::CATEGORY_COMPONENT, static_cast<int32_t>(EventType::CHANGE), std::move(params));
292 }
293
OnEvent(EventParamsBuilder && builder)294 void EventRecorder::OnEvent(EventParamsBuilder&& builder)
295 {
296 builder.SetPageUrl(GetPageUrl());
297 builder.SetNavDst(navDstName_);
298 auto eventType = builder.GetEventType();
299 auto params = builder.build();
300 EventController::Get().NotifyEvent(
301 EventCategory::CATEGORY_COMPONENT, static_cast<int32_t>(eventType), std::move(params));
302 }
303
OnNavDstShow(EventParamsBuilder && builder)304 void EventRecorder::OnNavDstShow(EventParamsBuilder&& builder)
305 {
306 navDstName_ = builder.GetText();
307 navShowTime_ = GetCurrentTimestamp();
308 builder.SetPageUrl(GetPageUrl());
309 builder.SetType(std::to_string(PageEventType::NAV_PAGE));
310 auto params = builder.build();
311 EventController::Get().NotifyEvent(
312 EventCategory::CATEGORY_PAGE, static_cast<int32_t>(EventType::PAGE_SHOW), std::move(params));
313 }
314
OnNavDstHide(EventParamsBuilder && builder)315 void EventRecorder::OnNavDstHide(EventParamsBuilder&& builder)
316 {
317 if (builder.GetText() == navDstName_) {
318 navDstName_ = "";
319 if (navShowTime_ > 0) {
320 int64_t duration = GetCurrentTimestamp() - navShowTime_;
321 builder.SetExtra(KEY_DURATION, std::to_string(duration));
322 navShowTime_ = 0;
323 }
324 }
325 builder.SetPageUrl(GetPageUrl());
326 builder.SetType(std::to_string(PageEventType::NAV_PAGE));
327 auto params = builder.build();
328 EventController::Get().NotifyEvent(
329 EventCategory::CATEGORY_PAGE, static_cast<int32_t>(EventType::PAGE_HIDE), std::move(params));
330 }
331
OnExposure(EventParamsBuilder && builder)332 void EventRecorder::OnExposure(EventParamsBuilder&& builder)
333 {
334 auto params = builder.build();
335 EventController::Get().NotifyEvent(
336 EventCategory::CATEGORY_EXPOSURE, static_cast<int32_t>(EventType::EXPOSURE), std::move(params));
337 }
338 } // namespace OHOS::Ace::Recorder
339