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