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 36namespace OHOS::NWeb { 37namespace { 38const int LOAD_SA_TIMEOUT_MS = 2 * 1000; 39const int FOUNDATION_UID = 5523; 40const std::set<std::string> ARK_WEB_DEFAULT_BUNDLE_NAME_SET = { "com.ohos.nweb", "com.ohos.arkwebcore" }; 41} // namespace 42 43AppFwkUpdateClient::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 51AppFwkUpdateClient& AppFwkUpdateClient::GetInstance() 52{ 53 static AppFwkUpdateClient singleAppFwkUpdateClient; 54 return singleAppFwkUpdateClient; 55} 56void 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 65sptr<IAppFwkUpdateService> AppFwkUpdateClient::GetFwkUpdate() 66{ 67 std::lock_guard<std::mutex> lock(mutex_); 68 return fwkUpdateProxy_; 69} 70 71sptr<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 101int 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 123bool 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 157void 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 174void AppFwkUpdateClient::OnLoadSystemAbilityFail() 175{ 176 SetFwkUpdate(nullptr); 177 std::unique_lock<std::mutex> lock(loadSaMutex_); 178 loadSaFinished_ = true; 179 loadSaCondition_.notify_one(); 180} 181 182void 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 191void 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