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_client.h"
17
18 #include <fcntl.h>
19 #include <string>
20 #include <sys/ioctl.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 #include "app_fwk_update_load_callback.h"
26 #include "if_system_ability_manager.h"
27 #include "ipc_skeleton.h"
28 #include "iservice_registry.h"
29 #include "isystem_ability_load_callback.h"
30 #include "nweb_log.h"
31 #include "system_ability_definition.h"
32
33 #include "base/web/webview/sa/app_fwk_update_service_proxy.h"
34 #include "base/web/webview/sa/iapp_fwk_update_service.h"
35
36 namespace OHOS::NWeb {
37 namespace {
38 const int LOAD_SA_TIMEOUT_MS = 4 * 1000;
39 const int FOUNDATION_UID = 5523;
40 const std::set<std::string> ARK_WEB_DEFAULT_BUNDLE_NAME_SET = { "com.ohos.nweb", "com.ohos.arkwebcore" };
41 } // namespace
42
AppFwkUpdateClient()43 AppFwkUpdateClient::AppFwkUpdateClient()
44 {
45 appFwkUpdateDiedRecipient_ = new (std::nothrow) AppFwkUpdateDiedRecipient();
46 if (appFwkUpdateDiedRecipient_ == nullptr) {
47 WVLOG_I("create fwk update service died recipient failed");
48 }
49 }
50
GetInstance()51 AppFwkUpdateClient& AppFwkUpdateClient::GetInstance()
52 {
53 static AppFwkUpdateClient singleAppFwkUpdateClient;
54 return singleAppFwkUpdateClient;
55 }
SetFwkUpdate(const sptr<IRemoteObject> & remoteObject)56 void AppFwkUpdateClient::SetFwkUpdate(const sptr<IRemoteObject>& remoteObject)
57 {
58 std::lock_guard<std::mutex> lock(mutex_);
59 fwkUpdateProxy_ = iface_cast<IAppFwkUpdateService>(remoteObject);
60 if (fwkUpdateProxy_) {
61 WVLOG_I("SetFwkUpdate is not null");
62 }
63 }
64
GetFwkUpdate()65 sptr<IAppFwkUpdateService> AppFwkUpdateClient::GetFwkUpdate()
66 {
67 std::lock_guard<std::mutex> lock(mutex_);
68 return fwkUpdateProxy_;
69 }
70
GetFwkUpdateProxy()71 sptr<IAppFwkUpdateService> AppFwkUpdateClient::GetFwkUpdateProxy()
72 {
73 auto fwkUpdateProxy = GetFwkUpdate();
74 if (fwkUpdateProxy != nullptr) {
75 return fwkUpdateProxy;
76 }
77 auto sam = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
78 if (sam == nullptr) {
79 WVLOG_E("load fwk service sam is null");
80 return {};
81 }
82
83 auto remoteObj = sam->CheckSystemAbility(SUBSYS_WEBVIEW_SYS_UPDATE_SERVICE_ID);
84 if (remoteObj != nullptr) {
85 fwkUpdateProxy = iface_cast<IAppFwkUpdateService>(remoteObj);
86 return fwkUpdateProxy;
87 }
88 if (!LoadFwkService()) {
89 WVLOG_I("get fwk update service is null");
90 return nullptr;
91 }
92 fwkUpdateProxy = GetFwkUpdate();
93 if (fwkUpdateProxy == nullptr) {
94 WVLOG_I("get fwk update service proxy is null");
95 return nullptr;
96 }
97 WVLOG_I("load fwk service sa finished");
98 return fwkUpdateProxy;
99 }
100
NotifyFWKAfterBmsStart()101 void AppFwkUpdateClient::NotifyFWKAfterBmsStart()
102 {
103 WVLOG_I("NotifyFWKAfterBmsStart received message");
104 auto proxy = GetFwkUpdateProxy();
105 if (proxy == nullptr) {
106 WVLOG_E("NotifyFWKAfterBmsStart failed, proxy is null");
107 return;
108 }
109 proxy->NotifyFWKAfterBmsStart();
110 }
111
VerifyPackageInstall(const std::string & bundleName,const std::string & hapPath)112 int AppFwkUpdateClient::VerifyPackageInstall(const std::string& bundleName, const std::string& hapPath)
113 {
114 WVLOG_I("verify package install callingUid: %{public}d", IPCSkeleton::GetCallingUid());
115 if (IPCSkeleton::GetCallingUid() != FOUNDATION_UID) {
116 return -1;
117 }
118 if (!ARK_WEB_DEFAULT_BUNDLE_NAME_SET.count(bundleName)) {
119 WVLOG_I("bundle name is not nweb.");
120 return 0;
121 }
122
123 auto proxy = GetFwkUpdateProxy();
124 if (proxy == nullptr) {
125 WVLOG_E("verify package install failed, proxy is null");
126 return -1;
127 }
128 int32_t isSuccess = -1;
129 proxy->VerifyPackageInstall(bundleName, hapPath, isSuccess);
130 WVLOG_I("verify package install result: %{public}d", isSuccess);
131 return isSuccess;
132 }
133
LoadFwkService()134 bool AppFwkUpdateClient::LoadFwkService()
135 {
136 {
137 std::unique_lock<std::mutex> lock(loadSaMutex_);
138 loadSaFinished_ = false;
139 }
140 auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
141 if (systemAbilityMgr == nullptr) {
142 WVLOG_I("failed to get system ability manager");
143 return false;
144 }
145 sptr<AppFwkUpdateLoadCallback> loadCallback = new (std::nothrow) AppFwkUpdateLoadCallback();
146 if (loadCallback == nullptr) {
147 WVLOG_I("failed to create load callback");
148 return false;
149 }
150 auto ret = systemAbilityMgr->LoadSystemAbility(SUBSYS_WEBVIEW_SYS_UPDATE_SERVICE_ID, loadCallback);
151 if (ret != 0) {
152 WVLOG_W("load fwk update service failed.");
153 return false;
154 }
155 {
156 std::unique_lock<std::mutex> lock(loadSaMutex_);
157 auto waitStatus = loadSaCondition_.wait_for(
158 lock, std::chrono::milliseconds(LOAD_SA_TIMEOUT_MS), [this]() { return loadSaFinished_; });
159 if (!waitStatus) {
160 auto remoteObj = systemAbilityMgr->CheckSystemAbility(SUBSYS_WEBVIEW_SYS_UPDATE_SERVICE_ID);
161 if (remoteObj != nullptr) {
162 SetFwkUpdate(remoteObj);
163 return true;
164 }
165 WVLOG_I("load fwk service timeout.");
166 return false;
167 }
168 WVLOG_I("load fwk service success.");
169 return true;
170 }
171 }
172
OnLoadSystemAbilitySuccess(const sptr<IRemoteObject> & remoteObject)173 void AppFwkUpdateClient::OnLoadSystemAbilitySuccess(const sptr<IRemoteObject>& remoteObject)
174 {
175 WVLOG_I("on load systemAbility success");
176 if (appFwkUpdateDiedRecipient_ == nullptr) {
177 WVLOG_E("register fwk update service died recipient failed");
178 return;
179 }
180 if (!remoteObject->AddDeathRecipient(appFwkUpdateDiedRecipient_)) {
181 WVLOG_E("add fwk update service died recipient failed");
182 return;
183 }
184 SetFwkUpdate(remoteObject);
185 std::unique_lock<std::mutex> lock(loadSaMutex_);
186 loadSaFinished_ = true;
187 loadSaCondition_.notify_one();
188 }
189
OnLoadSystemAbilityFail()190 void AppFwkUpdateClient::OnLoadSystemAbilityFail()
191 {
192 SetFwkUpdate(nullptr);
193 std::unique_lock<std::mutex> lock(loadSaMutex_);
194 loadSaFinished_ = true;
195 loadSaCondition_.notify_one();
196 }
197
OnRemoteDied(const wptr<IRemoteObject> & remoteObject)198 void AppFwkUpdateClient::AppFwkUpdateDiedRecipient::OnRemoteDied(const wptr<IRemoteObject>& remoteObject)
199 {
200 if (remoteObject == nullptr) {
201 WVLOG_E("remote object of fwk update service died recipient is nullptr");
202 return;
203 }
204 AppFwkUpdateClient::GetInstance().AppFwkUpdateOnRemoteDied(remoteObject);
205 }
206
AppFwkUpdateOnRemoteDied(const wptr<IRemoteObject> & remoteObject)207 void AppFwkUpdateClient::AppFwkUpdateOnRemoteDied(const wptr<IRemoteObject>& remoteObject)
208 {
209 WVLOG_I("remote object of fwk update service died recipient is died");
210 auto fwkUpdateProxy = GetFwkUpdate();
211 if (fwkUpdateProxy == nullptr) {
212 WVLOG_E("app fwk update proxy is nullptr");
213 return;
214 }
215 sptr<IRemoteObject> remotePromote = remoteObject.promote();
216 if (remotePromote == nullptr) {
217 WVLOG_E("remote object of fwk update service promote fail");
218 return;
219 }
220 if (fwkUpdateProxy->AsObject() != remotePromote) {
221 WVLOG_E("app fwk update died recipient not find remote object");
222 return;
223 }
224 remotePromote->RemoveDeathRecipient(appFwkUpdateDiedRecipient_);
225 SetFwkUpdate(nullptr);
226 }
227 } // namespace OHOS::NWeb
228