• 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 
NotifyFWKAfterBmsStart()92 ErrCode AppFwkUpdateService::NotifyFWKAfterBmsStart()
93 {
94     const std::string bundleName = OHOS::system::GetParameter(PERSIST_ARKWEBCORE_PACKAGE_NAME, "");
95     if (bundleName.empty()) {
96         WVLOG_E("NotifyFWKAfterBmsStart bundleName is empty");
97         return ERR_INVALID_VALUE;
98     }
99     WVLOG_I("NotifyFWKAfterBmsStart bundleName: %{public}s", bundleName.c_str());
100     int ret = SendAppSpawnMessage(bundleName, MSG_LOAD_WEBLIB_IN_APPSPAWN);
101     if (ret != 0) {
102         return ERR_INVALID_VALUE;
103     }
104     return ERR_OK;
105 }
106 
VerifyPackageInstall(const std::string & bundleName,const std::string & hapPath,int32_t & isSuccess)107 ErrCode AppFwkUpdateService::VerifyPackageInstall(
108     const std::string& bundleName, const std::string& hapPath, int32_t& isSuccess)
109 {
110     if (IPCSkeleton::GetCallingUid() != FOUNDATION_UID) {
111         return ERR_INVALID_VALUE;
112     }
113     int ret = 0;
114     isSuccess = 0;
115     if (OHOS::system::GetParameter("persist.arkwebcore.install_path", "") == hapPath) {
116         WVLOG_I("OnPackageChangedEvent install path not changed.");
117         return ERR_OK;
118     }
119 
120     ret = SetWebInstallPath(hapPath);
121     if (ret != 1) {
122         isSuccess = -1;
123         WVLOG_I("SetWebInstallPath happend error: %{public}d", isSuccess);
124         return ERR_INVALID_VALUE;
125     }
126 
127     ret = SetWebCorePackageName(bundleName);
128     if (ret != 1) {
129         isSuccess = -1;
130         WVLOG_I("SetWebInstallPath happend error: %{public}d", isSuccess);
131         return ERR_INVALID_VALUE;
132     }
133 
134     ret = SendAppSpawnMessage(bundleName, MSG_UPDATE_MOUNT_POINTS);
135     if (ret != 0) {
136         isSuccess = -1;
137         WVLOG_I("SendAppSpawnMessage happend error: %{public}d", isSuccess);
138         return ERR_INVALID_VALUE;
139     }
140     return ERR_OK;
141 }
142 
OnStart(const SystemAbilityOnDemandReason & startReason)143 void AppFwkUpdateService::OnStart(const SystemAbilityOnDemandReason& startReason)
144 {
145     WVLOG_I("Servie on start.");
146     if (registerToService_) {
147         WVLOG_I("App fwk update service is running.");
148     }
149     if (!Init(startReason)) {
150         return;
151     }
152 }
153 
Init(const SystemAbilityOnDemandReason & startReason)154 bool AppFwkUpdateService::Init(const SystemAbilityOnDemandReason& startReason)
155 {
156     std::string reasonName = startReason.GetName();
157     std::string reasonValue = startReason.GetValue();
158     WVLOG_I("AppFwkUpdateService reasonName: %{public}s", reasonName.c_str());
159     PostDelayUnloadTask();
160     bool ret = Publish(this);
161     if (!ret) {
162         WVLOG_I("Service publish failed.");
163         return false;
164     }
165     AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID);
166 
167     std::string bundleName = "";
168     if (startReason.HasExtraData()) {
169         auto reasonMap = startReason.GetExtraData().GetWant();
170         for (auto i = reasonMap.begin(); i != reasonMap.end(); ++i) {
171             std::string key = std::string(i->first.data());
172             std::string value = std::string(i->second.data());
173             if (key == "bundleName") {
174                 bundleName = value;
175                 WVLOG_I("AppFwkUpdateService bundleName: %{public}s", bundleName.c_str());
176                 break;
177             }
178         }
179     }
180     if (!ARK_WEB_DEFAULT_BUNDLE_NAME_SET.count(bundleName)) {
181         WVLOG_I("Bundle name is not nweb.");
182         return false;
183     }
184     registerToService_ = true;
185     WVLOG_I("Service init success.");
186     return true;
187 }
188 
SendAppSpawnMessage(const std::string & bundleName,AppSpawnMsgType msgType)189 int AppFwkUpdateService::SendAppSpawnMessage(const std::string& bundleName, AppSpawnMsgType msgType)
190 {
191     WVLOG_I("Send appspawn message start,uid = %{public}d.", getuid());
192     int ret = 0;
193     int retryCount = 0;
194     AppSpawnClientHandle clientHandle = nullptr;
195     AppSpawnReqMsgHandle reqHandle = 0;
196     do {
197         ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle);
198         if (ret != 0) {
199             WVLOG_I("Failed to create reqMgr,retry count = %{public}d.", retryCount);
200             continue;
201         }
202         ret = AppSpawnReqMsgCreate(msgType, bundleName.c_str(), &reqHandle);
203         if (ret != 0) {
204             WVLOG_I("Failed to create req,retry count = %{public}d.", retryCount);
205             continue;
206         }
207         AppSpawnResult result = {};
208         ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
209     } while (++retryCount < RETRY_COUNT && ret != 0);
210     AppSpawnClientDestroy(clientHandle);
211     WVLOG_I("Send appspawn message success.");
212     return ret;
213 }
214 
SendNWebSpawnMesage(const std::string & bundleName)215 int AppFwkUpdateService::SendNWebSpawnMesage(const std::string& bundleName)
216 {
217     WVLOG_I("Send nweb spawn messagestart,uid = %{public}d.", getuid());
218     int ret = 0;
219     int retryCount = 0;
220     AppSpawnClientHandle clientHandle = nullptr;
221     AppSpawnReqMsgHandle reqHandle = 0;
222     do {
223         ret = AppSpawnClientInit(NWEBSPAWN_SERVER_NAME, &clientHandle);
224         if (ret != 0) {
225             WVLOG_I("Failed to create reqMgr,retry count = %{public}d.", retryCount);
226             continue;
227         }
228         ret = AppSpawnReqMsgCreate(MSG_RESTART_SPAWNER, bundleName.c_str(), &reqHandle);
229         if (ret != 0) {
230             WVLOG_I("Failed to create req,retry count = %{public}d.", retryCount);
231             continue;
232         }
233         AppSpawnResult result = {};
234         ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
235     } while (++retryCount < RETRY_COUNT && ret != 0);
236     AppSpawnClientDestroy(clientHandle);
237     WVLOG_I("SendNWebSpawnMesage  res = %{public}d.", ret);
238     return ret;
239 }
240 
SetWebInstallPath(const std::string & path)241 int AppFwkUpdateService::SetWebInstallPath(const std::string& path)
242 {
243     int res = OHOS::system::SetParameter("persist.arkwebcore.install_path", path);
244     WVLOG_I("SetWebInstallPath  res = %{public}d.", res);
245     return res;
246 }
SetWebCorePackageName(const std::string & packageName)247 int AppFwkUpdateService::SetWebCorePackageName(const std::string& packageName)
248 {
249     int res = OHOS::system::SetParameter("persist.arkwebcore.package_name", packageName);
250     WVLOG_I("SetWebCorePackageName  res = %{public}d.", res);
251     return res;
252 }
253 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)254 void AppFwkUpdateService::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
255 {
256     WVLOG_I("OnAddSystemAbility systemAbilityId:%{public}d added!", systemAbilityId);
257     if (systemAbilityId == COMMON_EVENT_SERVICE_ID) {
258         SubscribePackageChangedEvent();
259         return;
260     }
261 }
262 
SubscribePackageChangedEvent()263 void AppFwkUpdateService::SubscribePackageChangedEvent()
264 {
265     EventFwk::MatchingSkills matchingSkills;
266     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED);
267     EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
268     PackageCommonEventCallback callback = { std::bind(
269         &AppFwkUpdateService::OnPackageChangedEvent, this, std::placeholders::_1, std::placeholders::_2) };
270     pkgSubscriber_ = std::make_shared<PackageChangedReceiver>(subscribeInfo, callback);
271     if (pkgSubscriber_ == nullptr) {
272         WVLOG_I("Create package changed subscriber failed");
273         return;
274     }
275     if (!EventFwk::CommonEventManager::SubscribeCommonEvent(pkgSubscriber_)) {
276         WVLOG_I("Subscribe package changed event fail");
277     }
278 }
279 
OnPackageChangedEvent(const std::string & bunldeName,const std::string & hapPath)280 void AppFwkUpdateService::OnPackageChangedEvent(const std::string& bunldeName, const std::string& hapPath)
281 {
282     SendNWebSpawnMesage(bunldeName);
283 }
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)284 void AppFwkUpdateService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
285 {
286     if (systemAbilityId != COMMON_EVENT_SERVICE_ID) {
287         WVLOG_I("systemAbilityId is not COMMON_EVENT_SERVICE_ID");
288         return;
289     }
290     if (pkgSubscriber_ == nullptr) {
291         WVLOG_I("OnRemoveSystemAbility subscribeer is nullptr");
292         return;
293     }
294     bool result = OHOS::EventFwk::CommonEventManager::UnSubscribeCommonEvent(pkgSubscriber_);
295     WVLOG_I("UnSubscribeCommonEvent subscriber result = %{public}d", result);
296 }
297 
OnStop()298 void AppFwkUpdateService::OnStop()
299 {
300     WVLOG_I("Ready to stop service.");
301     registerToService_ = false;
302 }
303 
PostDelayUnloadTask()304 void AppFwkUpdateService::PostDelayUnloadTask()
305 {
306     if (runner_ == nullptr) {
307         runner_ = AppExecFwk::EventRunner::Create("unload");
308     }
309     if (unloadHandler_ == nullptr) {
310         unloadHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
311     }
312     if (unloadHandler_ == nullptr) {
313         WVLOG_I("PostDelayUnloadTask invoke failed return.");
314         return;
315     }
316 
317     auto task = [this]() {
318         auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
319         if (samgrProxy == nullptr) {
320             WVLOG_I("Get samgrProxy failed.");
321             return;
322         }
323         int32_t ret = samgrProxy->UnloadSystemAbility(SUBSYS_WEBVIEW_SYS_UPDATE_SERVICE_ID);
324         if (ret != 0) {
325             WVLOG_I("Unload sa failed.");
326             return;
327         }
328         WVLOG_I("Do unload task done.");
329     };
330     unloadHandler_->RemoveTask(TASK_ID);
331     unloadHandler_->PostTask(task, TASK_ID, TASK_DELAY_TIME);
332 }
333 } // namespace OHOS::NWeb
334