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 = 2 * 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
VerifyPackageInstall(const std::string & bundleName,const std::string & hapPath)101 int AppFwkUpdateClient::VerifyPackageInstall(const std::string& bundleName, const std::string& hapPath)
102 {
103 WVLOG_I("verify package install callingUid: %{public}d", IPCSkeleton::GetCallingUid());
104 if (IPCSkeleton::GetCallingUid() != FOUNDATION_UID) {
105 return -1;
106 }
107 if (!ARK_WEB_DEFAULT_BUNDLE_NAME_SET.count(bundleName)) {
108 WVLOG_I("bundle name is not nweb.");
109 return 0;
110 }
111
112 auto proxy = GetFwkUpdateProxy();
113 if (proxy == nullptr) {
114 WVLOG_E("verify package install failed, proxy is null");
115 return -1;
116 }
117 int32_t isSuccess = -1;
118 proxy->VerifyPackageInstall(bundleName, hapPath, isSuccess);
119 WVLOG_I("verify package install result: %{public}d", isSuccess);
120 return isSuccess;
121 }
122
LoadFwkService()123 bool AppFwkUpdateClient::LoadFwkService()
124 {
125 {
126 std::unique_lock<std::mutex> lock(loadSaMutex_);
127 loadSaFinished_ = false;
128 }
129 auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
130 if (systemAbilityMgr == nullptr) {
131 WVLOG_I("failed to get system ability manager");
132 return false;
133 }
134 sptr<AppFwkUpdateLoadCallback> loadCallback = new (std::nothrow) AppFwkUpdateLoadCallback();
135 if (loadCallback == nullptr) {
136 WVLOG_I("failed to create load callback");
137 return false;
138 }
139 auto ret = systemAbilityMgr->LoadSystemAbility(SUBSYS_WEBVIEW_SYS_UPDATE_SERVICE_ID, loadCallback);
140 if (ret != 0) {
141 WVLOG_W("load fwk update service failed.");
142 return false;
143 }
144 {
145 std::unique_lock<std::mutex> lock(loadSaMutex_);
146 auto waitStatus = loadSaCondition_.wait_for(
147 lock, std::chrono::milliseconds(LOAD_SA_TIMEOUT_MS), [this]() { return loadSaFinished_; });
148 if (!waitStatus) {
149 WVLOG_I("load fwk service timeout.");
150 return false;
151 }
152 WVLOG_I("load fwk service success.");
153 return true;
154 }
155 }
156
OnLoadSystemAbilitySuccess(const sptr<IRemoteObject> & remoteObject)157 void AppFwkUpdateClient::OnLoadSystemAbilitySuccess(const sptr<IRemoteObject>& remoteObject)
158 {
159 WVLOG_I("on load systemAbility success");
160 if (appFwkUpdateDiedRecipient_ == nullptr) {
161 WVLOG_E("register fwk update service died recipient failed");
162 return;
163 }
164 if (!remoteObject->AddDeathRecipient(appFwkUpdateDiedRecipient_)) {
165 WVLOG_E("add fwk update service died recipient failed");
166 return;
167 }
168 SetFwkUpdate(remoteObject);
169 std::unique_lock<std::mutex> lock(loadSaMutex_);
170 loadSaFinished_ = true;
171 loadSaCondition_.notify_one();
172 }
173
OnLoadSystemAbilityFail()174 void AppFwkUpdateClient::OnLoadSystemAbilityFail()
175 {
176 SetFwkUpdate(nullptr);
177 std::unique_lock<std::mutex> lock(loadSaMutex_);
178 loadSaFinished_ = true;
179 loadSaCondition_.notify_one();
180 }
181
OnRemoteDied(const wptr<IRemoteObject> & remoteObject)182 void AppFwkUpdateClient::AppFwkUpdateDiedRecipient::OnRemoteDied(const wptr<IRemoteObject>& remoteObject)
183 {
184 if (remoteObject == nullptr) {
185 WVLOG_E("remote object of fwk update service died recipient is nullptr");
186 return;
187 }
188 AppFwkUpdateClient::GetInstance().AppFwkUpdateOnRemoteDied(remoteObject);
189 }
190
AppFwkUpdateOnRemoteDied(const wptr<IRemoteObject> & remoteObject)191 void AppFwkUpdateClient::AppFwkUpdateOnRemoteDied(const wptr<IRemoteObject>& remoteObject)
192 {
193 WVLOG_I("remote object of fwk update service died recipient is died");
194 auto fwkUpdateProxy = GetFwkUpdate();
195 if (fwkUpdateProxy == nullptr) {
196 WVLOG_E("app fwk update proxy is nullptr");
197 return;
198 }
199 sptr<IRemoteObject> remotePromote = remoteObject.promote();
200 if (remotePromote == nullptr) {
201 WVLOG_E("remote object of fwk update service promote fail");
202 return;
203 }
204 if (fwkUpdateProxy->AsObject() != remotePromote) {
205 WVLOG_E("app fwk update died recipient not find remote object");
206 return;
207 }
208 remotePromote->RemoveDeathRecipient(appFwkUpdateDiedRecipient_);
209 SetFwkUpdate(nullptr);
210 }
211 } // namespace OHOS::NWeb
212