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