1 /*
2 * Copyright (C) 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 #include "deferred_link_mgr.h"
16
17 namespace OHOS::AppDomainVerify {
18 namespace {
19 constexpr const char* TASK_ID = "age";
20 constexpr int32_t DELAY_TIME = 60000; // 1min
21 constexpr int64_t MAX_CACHE_TIME = 600; // 10min
22 constexpr int MAX_CACHE_SIZE = 50;
23 }
PutDeferredLink(const DeferredLinkInfo & info)24 void DeferredLinkMgr::PutDeferredLink(const DeferredLinkInfo& info)
25 {
26 APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called.");
27 std::unique_lock<std::mutex> lock(cachesMutex_);
28 CheckStartTimerUnlocked();
29 CheckRemoveExistedUnlocked(info);
30 CheckFullUnlocked();
31
32 caches_.push_front(info);
33 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "info domain:%{private}s, link:%{private}s.",
34 info.domain.c_str(), info.url.c_str());
35 }
36
GetDeferredLink(const std::string & bundleName,const std::vector<std::string> & domains)37 std::string DeferredLinkMgr::GetDeferredLink(const std::string& bundleName, const std::vector<std::string>& domains)
38 {
39 APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called.");
40 {
41 std::unique_lock<std::mutex> lock(cachesMutex_);
42 if (caches_.empty() || domains.empty() || bundleName.empty()) {
43 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "empty to match return.");
44 return "";
45 }
46 }
47
48 std::set<std::string> domainSet(domains.begin(), domains.end());
49 auto filter = AbilityFilter::Create(bundleName);
50 std::list<DeferredLinkInfo> destination;
51
52 {
53 std::unique_lock<std::mutex> lock(cachesMutex_);
54 // find links in bundle's domain and can match bundle's ability, then remove all of them.
55 caches_.remove_if([filter, &domainSet, &destination](const DeferredLinkInfo& linkInfo) {
56 if (domainSet.count(linkInfo.domain) != 0 && filter->Filter({ .url = linkInfo.url })) {
57 // keep newly in front
58 destination.push_back(linkInfo);
59 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "matched.");
60 return true;
61 }
62 return false;
63 });
64 }
65
66 std::string result = destination.empty() ? "" : destination.front().url;
67 APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "get deferred link:%{private}s", result.c_str());
68 return result;
69 }
70
PostAgeCacheTask()71 void DeferredLinkMgr::PostAgeCacheTask()
72 {
73 if (ageHandler_) {
74 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "PostAgeCacheTask.");
75 ageHandler_->RemoveTask(TASK_ID);
76 ageHandler_->PostTask([this] { AgeCacheProcess(); }, TASK_ID, DELAY_TIME);
77 }
78 }
AgeCacheProcess()79 void DeferredLinkMgr::AgeCacheProcess()
80 {
81 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "age func in.");
82 std::unique_lock<std::mutex> lock(cachesMutex_);
83 int64_t now = GetSecondsSince1970ToNow();
84 caches_.remove_if([now](const DeferredLinkInfo& linkInfo) { return now - linkInfo.timeStamp >= MAX_CACHE_TIME; });
85 if (!caches_.empty()) {
86 APP_DOMAIN_VERIFY_HILOGD(
87 APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "post continue age task, remain size:%{public}zu.", caches_.size());
88 PostAgeCacheTask();
89 } else {
90 APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "age task end.");
91 }
92 }
CheckStartTimerUnlocked()93 void DeferredLinkMgr::CheckStartTimerUnlocked()
94 {
95 if (caches_.empty()) {
96 PostAgeCacheTask();
97 }
98 }
CheckFullUnlocked()99 void DeferredLinkMgr::CheckFullUnlocked()
100 {
101 if (caches_.size() == MAX_CACHE_SIZE) {
102 caches_.pop_back();
103 }
104 }
CheckRemoveExistedUnlocked(const DeferredLinkInfo & info)105 void DeferredLinkMgr::CheckRemoveExistedUnlocked(const DeferredLinkInfo& info)
106 {
107 caches_.remove_if([&info](const DeferredLinkInfo& curInfo) {
108 if (curInfo.url == info.url && curInfo.domain == info.domain) {
109 return true;
110 }
111 return false;
112 });
113 APP_DOMAIN_VERIFY_HILOGD(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called.");
114 }
RemoveDeferredLink(const DeferredLinkInfo & info)115 void DeferredLinkMgr::RemoveDeferredLink(const DeferredLinkInfo& info)
116 {
117 std::unique_lock<std::mutex> lock(cachesMutex_);
118 caches_.remove_if([&info](const DeferredLinkInfo& curInfo) {
119 if (curInfo.url == info.url && curInfo.domain == info.domain) {
120 return true;
121 }
122 return false;
123 });
124 APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called.");
125 }
DeferredLinkMgr()126 DeferredLinkMgr::DeferredLinkMgr()
127 {
128 ageRunner_ = AppExecFwk::EventRunner::Create("age_deferred_link", AppExecFwk::ThreadMode::FFRT);
129 if (ageRunner_ == nullptr) {
130 APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_AGENT_MODULE_SERVICE, "create runner failed.");
131 return;
132 }
133 ageHandler_ = std::make_shared<AppExecFwk::EventHandler>(ageRunner_);
134 }
135
~DeferredLinkMgr()136 DeferredLinkMgr::~DeferredLinkMgr()
137 {
138 if (ageHandler_) {
139 ageHandler_->RemoveAllEvents();
140 }
141 }
142 }