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 
16 #include "app_fwk_update_service.h"
17 
18 #include "appspawn.h"
19 #include "bundle_mgr_client.h"
20 #include "bundle_mgr_interface.h"
21 #include "bundle_mgr_proxy.h"
22 #include "common_event_manager.h"
23 #include "common_event_support.h"
24 #include "event_handler.h"
25 #include "ipc_skeleton.h"
26 #include "iremote_object.h"
27 #include "iservice_registry.h"
28 #include "nweb_log.h"
29 #include "parameter.h"
30 #include "parameters.h"
31 #include "system_ability_definition.h"
32 #include "sysversion.h"
33 
34 namespace OHOS::NWeb {
35 
36 namespace {
37 const std::string PACKAGE_CHANGE_EVENT = "usual.event.PACKAGE_CHANGED";
38 const std::string ARK_WEB_BUNDLE_NAME = "com.ohos.nweb";
39 const int RETRY_COUNT = 2;
40 const int FOUNDATION_UID = 5523;
41 REGISTER_SYSTEM_ABILITY_BY_ID(AppFwkUpdateService, SUBSYS_WEBVIEW_SYS_UPDATE_SERVICE_ID, false);
42 
43 constexpr int32_t TASK_DELAY_TIME = 60000; // 1min = 1*60*1000
44 const std::string TASK_ID = "unload";
45 const std::string PERSIST_ARKWEBCORE_PACKAGE_NAME = "persist.arkwebcore.package_name";
46 const std::set<std::string> ARK_WEB_DEFAULT_BUNDLE_NAME_SET = { "com.ohos.nweb", "com.ohos.arkwebcore" };
47 const std::string NWEB_HAP_PATH_MODULE_UPDATE = "/module_update/ArkWebCore/app/com.ohos.nweb/NWeb.hap";
48 } // namespace
49 
PackageChangedReceiver(const EventFwk::CommonEventSubscribeInfo & subscribeInfo,const PackageCommonEventCallback & callback)50 PackageChangedReceiver::PackageChangedReceiver(
51     const EventFwk::CommonEventSubscribeInfo& subscribeInfo, const PackageCommonEventCallback& callback)
52     : EventFwk::CommonEventSubscriber(subscribeInfo), callback_(callback)
53 {}
54 
OnReceiveEvent(const EventFwk::CommonEventData & data)55 void PackageChangedReceiver::OnReceiveEvent(const EventFwk::CommonEventData& data)
56 {
57     std::string action = data.GetWant().GetAction();
58     if (action.empty()) {
59         WVLOG_I("action is empty");
60         return;
61     }
62 
63     std::string bundleName = data.GetWant().GetBundle();
64     if (!ARK_WEB_DEFAULT_BUNDLE_NAME_SET.count(bundleName)) {
65         WVLOG_I("Bundle name is not nweb.");
66         return;
67     }
68 
69     WVLOG_I("packagechangeReceiver OnReceiveEvent, ret = %{public}s.", action.c_str());
70     if (action == EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED) {
71         std::string hapPath;
72         OHOS::AppExecFwk::BundleInfo bundleInfo;
73         OHOS::AppExecFwk::BundleMgrClient client;
74 
75         bool result = client.GetBundleInfo(bundleName, OHOS::AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo,
76             AppExecFwk::Constants::ALL_USERID);
77         if (result) {
78             if (bundleInfo.hapModuleInfos.size() > 0) {
79                 hapPath = bundleInfo.hapModuleInfos[0].hapPath;
80                 WVLOG_I("PackagechangeReceiver hapPath is %{public}s.", hapPath.c_str());
81             }
82             callback_.OnPackageChangedEvent(bundleName, hapPath);
83         } else {
84             WVLOG_I("Failed to get bundleInfo.");
85         }
86     }
87 }
88 
AppFwkUpdateService(int32_t saId,bool runOnCreate)89 AppFwkUpdateService::AppFwkUpdateService(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate) {}
90 
~AppFwkUpdateService()91 AppFwkUpdateService::~AppFwkUpdateService() {}
92 
VerifyPackageInstall(const std::string & bundleName,const std::string & hapPath,int32_t & isSuccess)93 ErrCode AppFwkUpdateService::VerifyPackageInstall(
94     const std::string& bundleName, const std::string& hapPath, int32_t& isSuccess)
95 {
96     if (IPCSkeleton::GetCallingUid() != FOUNDATION_UID) {
97         return ERR_INVALID_VALUE;
98     }
99     int ret = 0;
100     isSuccess = 0;
101     if (OHOS::system::GetParameter("persist.arkwebcore.install_path", "") == hapPath) {
102         WVLOG_I("OnPackageChangedEvent install path not changed.");
103         return ERR_OK;
104     }
105 
106     ret = SetWebInstallPath(hapPath);
107     if (ret != 1) {
108         isSuccess = -1;
109         WVLOG_I("SetWebInstallPath happend error: %{public}d", isSuccess);
110         return ERR_INVALID_VALUE;
111     }
112 
113     ret = SetWebCorePackageName(bundleName);
114     if (ret != 1) {
115         isSuccess = -1;
116         WVLOG_I("SetWebInstallPath happend error: %{public}d", isSuccess);
117         return ERR_INVALID_VALUE;
118     }
119 
120     ret = SendAppSpawnMessage(bundleName);
121     if (ret != 0) {
122         isSuccess = -1;
123         WVLOG_I("SendAppSpawnMessage happend error: %{public}d", isSuccess);
124         return ERR_INVALID_VALUE;
125     }
126     return ERR_OK;
127 }
128 
OnStart(const SystemAbilityOnDemandReason & startReason)129 void AppFwkUpdateService::OnStart(const SystemAbilityOnDemandReason& startReason)
130 {
131     WVLOG_I("Servie on start.");
132     if (registerToService_) {
133         WVLOG_I("App fwk update service is running.");
134     }
135     if (!Init(startReason)) {
136         return;
137     }
138 }
139 
Init(const SystemAbilityOnDemandReason & startReason)140 bool AppFwkUpdateService::Init(const SystemAbilityOnDemandReason& startReason)
141 {
142     std::string reasonName = startReason.GetName();
143     std::string reasonValue = startReason.GetValue();
144     WVLOG_I("AppFwkUpdateService reasonName: %{public}s", reasonName.c_str());
145     PostDelayUnloadTask();
146     bool ret = Publish(this);
147     if (!ret) {
148         WVLOG_I("Service publish failed.");
149         return false;
150     }
151     AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID);
152 
153     std::string bundleName = "";
154     if (startReason.HasExtraData()) {
155         auto reasonMap = startReason.GetExtraData().GetWant();
156         for (auto i = reasonMap.begin(); i != reasonMap.end(); ++i) {
157             std::string key = std::string(i->first.data());
158             std::string value = std::string(i->second.data());
159             if (key == "bundleName") {
160                 bundleName = value;
161                 WVLOG_I("AppFwkUpdateService bundleName: %{public}s", bundleName.c_str());
162                 break;
163             }
164         }
165     }
166     if (!ARK_WEB_DEFAULT_BUNDLE_NAME_SET.count(bundleName)) {
167         WVLOG_I("Bundle name is not nweb.");
168         return false;
169     }
170     registerToService_ = true;
171     WVLOG_I("Service init success.");
172     return true;
173 }
174 
SendAppSpawnMessage(const std::string & bundleName)175 int AppFwkUpdateService::SendAppSpawnMessage(const std::string& bundleName)
176 {
177     WVLOG_I("Send appspawn message start,uid = %{public}d.", getuid());
178     int ret = 0;
179     int retryCount = 0;
180     AppSpawnClientHandle clientHandle = nullptr;
181     AppSpawnReqMsgHandle reqHandle = 0;
182     do {
183         ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle);
184         if (ret != 0) {
185             WVLOG_I("Failed to create reqMgr,retry count = %{public}d.", retryCount);
186             continue;
187         }
188         ret = AppSpawnReqMsgCreate(MSG_UPDATE_MOUNT_POINTS, bundleName.c_str(), &reqHandle);
189         if (ret != 0) {
190             WVLOG_I("Failed to create req,retry count = %{public}d.", retryCount);
191             continue;
192         }
193         AppSpawnResult result = {};
194         ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
195     } while (++retryCount < RETRY_COUNT && ret != 0);
196     AppSpawnClientDestroy(clientHandle);
197     WVLOG_I("Send appspawn message success.");
198     return ret;
199 }
200 
SendNWebSpawnMesage(const std::string & bundleName)201 int AppFwkUpdateService::SendNWebSpawnMesage(const std::string& bundleName)
202 {
203     WVLOG_I("Send nweb spawn messagestart,uid = %{public}d.", getuid());
204     int ret = 0;
205     int retryCount = 0;
206     AppSpawnClientHandle clientHandle = nullptr;
207     AppSpawnReqMsgHandle reqHandle = 0;
208     do {
209         ret = AppSpawnClientInit(NWEBSPAWN_SERVER_NAME, &clientHandle);
210         if (ret != 0) {
211             WVLOG_I("Failed to create reqMgr,retry count = %{public}d.", retryCount);
212             continue;
213         }
214         ret = AppSpawnReqMsgCreate(MSG_RESTART_SPAWNER, bundleName.c_str(), &reqHandle);
215         if (ret != 0) {
216             WVLOG_I("Failed to create req,retry count = %{public}d.", retryCount);
217             continue;
218         }
219         AppSpawnResult result = {};
220         ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
221     } while (++retryCount < RETRY_COUNT && ret != 0);
222     AppSpawnClientDestroy(clientHandle);
223     WVLOG_I("SendNWebSpawnMesage  res = %{public}d.", ret);
224     return ret;
225 }
226 
SetWebInstallPath(const std::string & path)227 int AppFwkUpdateService::SetWebInstallPath(const std::string& path)
228 {
229     int res = OHOS::system::SetParameter("persist.arkwebcore.install_path", path);
230     WVLOG_I("SetWebInstallPath  res = %{public}d.", res);
231     return res;
232 }
233 
SetWebCorePackageName(const std::string & packageName)234 int AppFwkUpdateService::SetWebCorePackageName(const std::string& packageName)
235 {
236     int res = OHOS::system::SetParameter("persist.arkwebcore.package_name", packageName);
237     WVLOG_I("SetWebCorePackageName  res = %{public}d.", res);
238     return res;
239 }
240 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)241 void AppFwkUpdateService::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
242 {
243     WVLOG_I("OnAddSystemAbility systemAbilityId:%{public}d added!", systemAbilityId);
244     if (systemAbilityId == COMMON_EVENT_SERVICE_ID) {
245         SubscribePackageChangedEvent();
246         return;
247     }
248 }
249 
SubscribePackageChangedEvent()250 void AppFwkUpdateService::SubscribePackageChangedEvent()
251 {
252     EventFwk::MatchingSkills matchingSkills;
253     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED);
254     EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
255     PackageCommonEventCallback callback = { std::bind(
256         &AppFwkUpdateService::OnPackageChangedEvent, this, std::placeholders::_1, std::placeholders::_2) };
257     pkgSubscriber_ = std::make_shared<PackageChangedReceiver>(subscribeInfo, callback);
258     if (pkgSubscriber_ == nullptr) {
259         WVLOG_I("Create package changed subscriber failed");
260         return;
261     }
262     if (!EventFwk::CommonEventManager::SubscribeCommonEvent(pkgSubscriber_)) {
263         WVLOG_I("Subscribe package changed event fail");
264     }
265 }
266 
OnPackageChangedEvent(const std::string & bunldeName,const std::string & hapPath)267 void AppFwkUpdateService::OnPackageChangedEvent(const std::string& bunldeName, const std::string& hapPath)
268 {
269     SendNWebSpawnMesage(bunldeName);
270 }
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)271 void AppFwkUpdateService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
272 {
273     if (systemAbilityId != COMMON_EVENT_SERVICE_ID) {
274         WVLOG_I("systemAbilityId is not COMMON_EVENT_SERVICE_ID");
275         return;
276     }
277     if (pkgSubscriber_ == nullptr) {
278         WVLOG_I("OnRemoveSystemAbility subscribeer is nullptr");
279         return;
280     }
281     bool result = OHOS::EventFwk::CommonEventManager::UnSubscribeCommonEvent(pkgSubscriber_);
282     WVLOG_I("UnSubscribeCommonEvent subscriber result = %{public}d", result);
283 }
284 
OnStop()285 void AppFwkUpdateService::OnStop()
286 {
287     WVLOG_I("Ready to stop service.");
288     registerToService_ = false;
289 }
290 
PostDelayUnloadTask()291 void AppFwkUpdateService::PostDelayUnloadTask()
292 {
293     if (runner_ == nullptr) {
294         runner_ = AppExecFwk::EventRunner::Create("unload");
295     }
296     if (unloadHandler_ == nullptr) {
297         unloadHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
298     }
299     if (unloadHandler_ == nullptr) {
300         WVLOG_I("PostDelayUnloadTask invoke failed return.");
301         return;
302     }
303 
304     auto task = [this]() {
305         auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
306         if (samgrProxy == nullptr) {
307             WVLOG_I("Get samgrProxy failed.");
308             return;
309         }
310         int32_t ret = samgrProxy->UnloadSystemAbility(SUBSYS_WEBVIEW_SYS_UPDATE_SERVICE_ID);
311         if (ret != 0) {
312             WVLOG_I("Unload sa failed.");
313             return;
314         }
315         WVLOG_I("Do unload task done.");
316     };
317     unloadHandler_->RemoveTask(TASK_ID);
318     unloadHandler_->PostTask(task, TASK_ID, TASK_DELAY_TIME);
319 }
320 
321 } // namespace OHOS::NWeb
322