1 /*
2 * Copyright (c) 2023 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 "page_url_checker_ohos.h"
17
18 #include <string>
19
20 #include "ability_runtime/context/context.h"
21 #include "atomic_service_status_callback.h"
22 #include "errors.h"
23 #include "iremote_broker.h"
24 #include "iremote_object.h"
25 #include "iremote_stub.h"
26 #include "iservice_registry.h"
27 #include "nocopyable.h"
28 #include "system_ability_definition.h"
29 #include "want.h"
30
31 namespace OHOS::Ace {
32 const char BUNDLE_TAG[] = "@bundle:";
33 constexpr size_t BUNDLE_START_POS = 8;
34 constexpr int32_t SILENT_INSTALL_SUCCESS = 0;
35
36 /**
37 * @class IAtomicServiceStatusCallback
38 * IAtomicServiceStatusCallback is used to notify caller ability that free install is complete.
39 */
40 class IAtomicServiceStatusCallback : public IRemoteBroker {
41 public:
42 DECLARE_INTERFACE_DESCRIPTOR(u"ohos.IAtomicServiceStatusCallback");
43
44 /**
45 * @brief OnActionEvent.
46 */
47 virtual int32_t OnActionEvent() = 0;
48 /**
49 * @brief OnError.
50 * @param code The code.
51 * @param msg The msg.
52 */
53 virtual int32_t OnError(int32_t code, const std::string& msg) = 0;
54 };
55
56 /**
57 * @class AtomicServiceStatusCallbackStub
58 * AtomicServiceStatusCallbackStub.
59 */
60 class AtomicServiceStatusCallbackStub : public IRemoteStub<IAtomicServiceStatusCallback> {
61 public:
AtomicServiceStatusCallbackStub()62 AtomicServiceStatusCallbackStub()
63 {
64 handleOnActionEventFunc_ = &AtomicServiceStatusCallbackStub::HandleOnActionEvent;
65 handleOnErrorFunc_ = &AtomicServiceStatusCallbackStub::HandleOnError;
66 }
~AtomicServiceStatusCallbackStub()67 ~AtomicServiceStatusCallbackStub() override
68 {
69 handleOnActionEventFunc_ = nullptr;
70 handleOnErrorFunc_ = nullptr;
71 }
72
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)73 int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override
74 {
75 LOGI("AtomicServiceStatusCallbackStub::OnReceived, code = %{public}u, flags= %{public}d.",
76 code, option.GetFlags());
77 std::u16string descriptor = AtomicServiceStatusCallbackStub::GetDescriptor();
78 std::u16string remoteDescriptor = data.ReadInterfaceToken();
79 if (descriptor != remoteDescriptor) {
80 LOGE("%{public}s failed, local descriptor is not equal to remote", __func__);
81 return ERR_INVALID_VALUE;
82 }
83
84 auto resultCode = data.ReadInt32();
85 if (resultCode == SILENT_INSTALL_SUCCESS) {
86 if (handleOnActionEventFunc_ != nullptr) {
87 return (this->*handleOnActionEventFunc_)();
88 }
89 }
90
91 if (resultCode < SILENT_INSTALL_SUCCESS) {
92 if (handleOnErrorFunc_ != nullptr) {
93 return (this->*handleOnErrorFunc_)(data);
94 }
95 }
96
97 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
98 }
99
100 private:
HandleOnActionEvent()101 int32_t HandleOnActionEvent()
102 {
103 return OnActionEvent();
104 }
HandleOnError(MessageParcel & data)105 int32_t HandleOnError(MessageParcel &data)
106 {
107 int32_t code = data.ReadInt32();
108 std::string msg = data.ReadString();
109 return OnError(code, msg);
110 }
111
112 using HandleOnActionEventFunc = int32_t (AtomicServiceStatusCallbackStub::*)();
113 HandleOnActionEventFunc handleOnActionEventFunc_;
114
115 using HandleOnErrorFunc = int32_t (AtomicServiceStatusCallbackStub::*)(MessageParcel &data);
116 HandleOnErrorFunc handleOnErrorFunc_;
117
118 DISALLOW_COPY_AND_MOVE(AtomicServiceStatusCallbackStub);
119 };
120
121 /**
122 * @class AtomicServiceStatusCallback
123 * AtomicServiceStatusCallback.
124 */
125 class AtomicServiceStatusCallback : public AtomicServiceStatusCallbackStub {
126 public:
127 AtomicServiceStatusCallback() = default;
128 ~AtomicServiceStatusCallback() override = default;
129
130 /**
131 * @brief OnActionEvent.
132 */
OnActionEvent()133 int32_t OnActionEvent() override
134 {
135 if (!actionEventHandler_) {
136 LOGE("actionEventHandler_ is null.");
137 return ERR_INVALID_VALUE;
138 }
139 actionEventHandler_();
140 return ERR_OK;
141 }
142 /**
143 * @brief OnError.
144 * @param code The code.
145 * @param msg The msg.
146 */
OnError(int32_t code,const std::string & msg)147 int32_t OnError(int32_t code, const std::string& msg) override
148 {
149 LOGE("OnError code: %{public}d, msg: %{public}s", code, msg.c_str());
150 if (!errorEventHandler_) {
151 LOGE("errorEventHandler_ is null");
152 return ERR_INVALID_VALUE;
153 }
154
155 errorEventHandler_(code, msg);
156 return ERR_OK;
157 }
158
SetActionEventHandler(const std::function<void ()> & listener)159 void SetActionEventHandler(const std::function<void()>& listener)
160 {
161 actionEventHandler_ = listener;
162 }
SetErrorEventHandler(const std::function<void (int32_t,const std::string &)> & listener)163 void SetErrorEventHandler(const std::function<void(int32_t, const std::string&)>& listener)
164 {
165 errorEventHandler_ = listener;
166 }
167
168 private:
169 std::function<void()> actionEventHandler_;
170 std::function<void(int32_t, const std::string&)> errorEventHandler_;
171 };
172
GetBundleManager()173 sptr<AppExecFwk::IBundleMgr> PageUrlCheckerOhos::GetBundleManager()
174 {
175 auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
176 if (systemAbilityMgr == nullptr) {
177 LOGE("Failed to get SystemAbilityManager.");
178 return nullptr;
179 }
180
181 auto bundleObj = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
182 if (bundleObj == nullptr) {
183 LOGE("Failed to get bundle manager service");
184 return nullptr;
185 }
186
187 return iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
188 }
189
LoadPageUrl(const std::string & url,const std::function<void ()> & callback,const std::function<void (int32_t,const std::string &)> & silentInstallErrorCallBack)190 void PageUrlCheckerOhos::LoadPageUrl(const std::string& url, const std::function<void()>& callback,
191 const std::function<void(int32_t, const std::string&)>& silentInstallErrorCallBack)
192 {
193 if (url.substr(0, strlen(BUNDLE_TAG)) != BUNDLE_TAG) {
194 return;
195 }
196
197 size_t bundleEndPos = url.find('/');
198 std::string bundleName = url.substr(BUNDLE_START_POS, bundleEndPos - BUNDLE_START_POS);
199 size_t moduleStartPos = bundleEndPos + 1;
200 size_t moduleEndPos = url.find('/', moduleStartPos);
201 std::string moduleName = url.substr(moduleStartPos, moduleEndPos - moduleStartPos);
202
203 auto appInfo = context_->GetApplicationInfo();
204 if (appInfo) {
205 std::vector<OHOS::AppExecFwk::ModuleInfo> moduleList = appInfo->moduleInfos;
206 bool isInstalled = false;
207 auto res = std::any_of(moduleList.begin(), moduleList.end(), [moduleName](const auto &module) {
208 return module.moduleName == moduleName;
209 });
210 if (res) {
211 isInstalled = true;
212 }
213
214 if (!isInstalled) {
215 auto bms = GetBundleManager();
216 CHECK_NULL_VOID(bms);
217 AAFwk::Want want;
218 want.SetBundle(bundleName);
219 want.SetModuleName(moduleName);
220 sptr<AtomicServiceStatusCallback> routerCallback = new AtomicServiceStatusCallback();
221 routerCallback->SetActionEventHandler(callback);
222 routerCallback->SetErrorEventHandler(silentInstallErrorCallBack);
223 if (bms->SilentInstall(want, appInfo->uid / AppExecFwk::Constants::BASE_USER_RANGE, routerCallback)) {
224 LOGI("Begin to silent install");
225 }
226 } else {
227 callback();
228 }
229 }
230 }
231
CheckPreload(const std::string & url)232 void PageUrlCheckerOhos::CheckPreload(const std::string& url)
233 {
234 if (url.substr(0, strlen(BUNDLE_TAG)) != BUNDLE_TAG) {
235 return;
236 }
237
238 size_t bundleEndPos = url.find('/');
239 std::string bundleName = url.substr(BUNDLE_START_POS, bundleEndPos - BUNDLE_START_POS);
240 size_t moduleStartPos = bundleEndPos + 1;
241 size_t moduleEndPos = url.find('/', moduleStartPos);
242 std::string moduleName = url.substr(moduleStartPos, moduleEndPos - moduleStartPos);
243
244 auto appInfo = context_->GetApplicationInfo();
245 CHECK_NULL_VOID(appInfo);
246 if (appInfo->CheckNeedPreload(moduleName)) {
247 auto bms = GetBundleManager();
248 CHECK_NULL_VOID(bms);
249 AAFwk::Want want;
250 // only need to Transfer bundleName and moduleName
251 want.SetElementName("", bundleName, "", moduleName);
252 want.SetParam("uid", appInfo->uid);
253 bms->ProcessPreload(want);
254 }
255 }
256 } // namespace OHOS::Ace