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 #include "ndef_har_dispatch.h"
16
17 #include "external_deps_proxy.h"
18 #include "iservice_registry.h"
19 #include "ndef_har_data_parser.h"
20 #include "tag_ability_dispatcher.h"
21 #include "ability_manager_client.h"
22 #include "loghelper.h"
23 #include "bundle_mgr_interface.h"
24 #include "if_system_ability_manager.h"
25
26 namespace OHOS {
27 namespace NFC {
28 namespace TAG {
29 const int USER_ID = 100;
30 const int BUNDLE_MGR_SERVICE_SYS_ABILITY_ID = 401;
31 using namespace OHOS::NFC::KITS;
32
33 std::string uri_ {};
34 std::string browserBundleName_ {};
35
NdefHarDispatch(std::weak_ptr<NCI::INciNfccInterface> nciNfccProxy)36 NdefHarDispatch::NdefHarDispatch(std::weak_ptr<NCI::INciNfccInterface> nciNfccProxy)
37 : nciNfccProxy_(nciNfccProxy)
38 {
39 }
40
GetBundleMgrProxy()41 sptr<AppExecFwk::IBundleMgr> NdefHarDispatch::GetBundleMgrProxy()
42 {
43 sptr<ISystemAbilityManager> systemAbilityManager =
44 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
45 if (!systemAbilityManager) {
46 ErrorLog("GetBundleMgrProxy, systemAbilityManager is null");
47 return nullptr;
48 }
49 sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
50 if (!remoteObject) {
51 ErrorLog("GetBundleMgrProxy, remoteObject is null");
52 return nullptr;
53 }
54 return iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
55 }
56
57 /* Implicit matching, using mimetype to pull up app */
DispatchMimeType(const std::string & type,const std::shared_ptr<KITS::TagInfo> & tagInfo)58 bool NdefHarDispatch::DispatchMimeType(const std::string &type, const std::shared_ptr<KITS::TagInfo> &tagInfo)
59 {
60 if (type.empty() || tagInfo == nullptr) {
61 ErrorLog("NdefHarDispatch::DispatchMimeType type is empty");
62 return false;
63 }
64 AAFwk::Want want;
65 want.SetType(type);
66 ExternalDepsProxy::GetInstance().SetWantExtraParam(tagInfo, want);
67 if (GetBundleMgrProxy() == nullptr) {
68 ErrorLog("NdefHarDispatch::DispatchMimeType GetBundleMgrProxy is nullptr");
69 return false;
70 }
71 bool withDefault = false;
72 auto abilityInfoFlag = AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_DEFAULT
73 | AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_SKILL_URI
74 | AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_METADATA;
75 std::vector<AbilityInfo> abilityInfos;
76 std::vector<ExtensionAbilityInfo> extensionInfos;
77 bool findDefaultApp = false;
78 if (!GetBundleMgrProxy()->ImplicitQueryInfos(
79 want, abilityInfoFlag, USER_ID, withDefault, abilityInfos, extensionInfos, findDefaultApp)) {
80 ErrorLog("NdefHarDispatch::DispatchMimeType ImplicitQueryInfos false");
81 return false;
82 }
83 int32_t errCode = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
84 if (errCode) {
85 ErrorLog("NdefHarDispatch::DispatchMimeType call StartAbility fail. ret = %{public}d", errCode);
86 return false;
87 }
88 ExternalDepsProxy::GetInstance().WriteDispatchToAppHiSysEvent(want.GetElement().GetBundleName(),
89 SubErrorCode::NDEF_HAR_DISPATCH);
90 return true;
91 }
92
93 /* Verify harPackageString as BundleName/ServiceName and call StartExtensionAbility to pull up app */
DispatchBundleExtensionAbility(const std::string & harPackageString,const std::shared_ptr<KITS::TagInfo> & tagInfo,const std::string & mimeType,const std::string & uri)94 bool NdefHarDispatch::DispatchBundleExtensionAbility(const std::string &harPackageString,
95 const std::shared_ptr<KITS::TagInfo> &tagInfo, const std::string &mimeType, const std::string &uri)
96 {
97 std::istringstream iss(harPackageString);
98 std::string bundleName;
99 std::string serviceName;
100 if (!getline(iss, bundleName, '/')) {
101 InfoLog("harPackageString bundleName invalid");
102 return false;
103 }
104 if (!getline(iss, serviceName, '/')) {
105 InfoLog("harPackageString serviceName invalid");
106 return false;
107 }
108 AAFwk::Want want;
109 want.SetElementName(bundleName, serviceName);
110 if (!mimeType.empty()) {
111 want.SetType(mimeType);
112 }
113 if (uri.size() > 0) {
114 want.SetUri(uri);
115 }
116 if (tagInfo != nullptr) {
117 ExternalDepsProxy::GetInstance().SetWantExtraParam(tagInfo, want);
118 }
119 int errCode = AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(want, nullptr);
120 InfoLog("StartExtensionAbility ret = %{public}d, bundleName = %{public}s, serviceName = %{public}s", errCode,
121 bundleName.c_str(), serviceName.c_str());
122 return (errCode == 0);
123 }
124
125 /* Call GetLaunchWantForBundle through bundlename to obtain the want and pull up the app */
DispatchBundleAbility(const std::string & harPackage,const std::shared_ptr<KITS::TagInfo> & tagInfo,const std::string & mimeType,const std::string & uri,OHOS::sptr<IRemoteObject> tagServiceIface)126 bool NdefHarDispatch::DispatchBundleAbility(const std::string &harPackage,
127 const std::shared_ptr<KITS::TagInfo> &tagInfo, const std::string &mimeType, const std::string &uri,
128 OHOS::sptr<IRemoteObject> tagServiceIface)
129 {
130 if (harPackage.empty()) {
131 ErrorLog("NdefHarDispatch::DispatchBundleAbility harPackage is empty");
132 return false;
133 }
134 std::string harPackageString = NfcSdkCommon::HexStringToAsciiString(harPackage);
135 AAFwk::Want want;
136 if (GetBundleMgrProxy() == nullptr) {
137 ErrorLog("GetBundleMgrProxy is nullptr");
138 return false;
139 }
140 int32_t errCode = GetBundleMgrProxy()->GetLaunchWantForBundle(harPackageString, want, USER_ID);
141 if (errCode) {
142 InfoLog("GetLaunchWantForBundle fail. ret = %{public}d, harPackage = %{public}s, try ExtensionAbility instead",
143 errCode, harPackageString.c_str());
144 if (DispatchBundleExtensionAbility(harPackageString, tagInfo, mimeType, uri)) {
145 return true;
146 }
147 return false;
148 }
149 if (!mimeType.empty()) {
150 want.SetType(mimeType);
151 }
152 if (tagServiceIface == nullptr) {
153 WarnLog("tagServiceIface is null");
154 }
155 if (tagInfo != nullptr) {
156 want.SetParam("remoteTagService", tagServiceIface);
157 ExternalDepsProxy::GetInstance().SetWantExtraParam(tagInfo, want);
158 }
159 if (uri.size() > 0) {
160 want.SetUri(uri);
161 }
162 errCode = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
163 if (errCode) {
164 ErrorLog("StartAbility fail. ret = %{public}d, harPackage = %{public}s",
165 errCode, harPackageString.c_str());
166 return false;
167 }
168 ExternalDepsProxy::GetInstance().WriteDispatchToAppHiSysEvent(want.GetElement().GetBundleName(),
169 SubErrorCode::NDEF_HAR_DISPATCH);
170 if (!nciNfccProxy_.expired()) {
171 nciNfccProxy_.lock()->NotifyMessageToVendor(KITS::TAG_DISPATCH_HAR_PACKAGE, harPackageString);
172 }
173 return true;
174 }
175
DispatchUriToBundleAbility(const std::string & uri)176 bool NdefHarDispatch::DispatchUriToBundleAbility(const std::string &uri)
177 {
178 if (uri.empty()) {
179 ErrorLog("NdefHarDispatch::DispatchUriToBundleAbility uri is empty");
180 return false;
181 }
182 bool canOpen = false;
183 if (GetBundleMgrProxy() == nullptr) {
184 ErrorLog("NdefHarDispatch::DispatchUriToBundleAbility GetBundleMgrProxy is nullptr");
185 return false;
186 }
187 int32_t errCode = GetBundleMgrProxy()->CanOpenLink(uri, canOpen);
188 if (!errCode && canOpen) {
189 InfoLog("NdefHarDispatch::DispatchUriToBundleAbility CanOpenLink");
190 }
191 ErrorLog("CanOpenLink fail. errCode = %{public}d, canOpen = %{public}d", errCode, canOpen);
192 return false;
193 }
194
195 /* If the corresponding app has been installed, the system jumps to the corresponding app and starts it.
196 * If the corresponding app is not installed, the default browser is used to open the corresponding page.
197 */
DispatchByAppLinkMode(const std::string & uriSchemeValue,const std::shared_ptr<KITS::TagInfo> & tagInfo,OHOS::sptr<IRemoteObject> tagServiceIface)198 bool NdefHarDispatch::DispatchByAppLinkMode(const std::string &uriSchemeValue,
199 const std::shared_ptr<KITS::TagInfo> &tagInfo, OHOS::sptr<IRemoteObject> tagServiceIface)
200 {
201 std::unique_lock<std::shared_mutex> guard(mutex_);
202 InfoLog("enter");
203 if (uriSchemeValue.empty()) {
204 ErrorLog("uriSchemeValue is empty");
205 return false;
206 }
207 if (tagInfo == nullptr) {
208 ErrorLog("tagInfo is null");
209 return false;
210 }
211 if (tagServiceIface == nullptr) {
212 WarnLog("tagServiceIface is null");
213 }
214 AAFwk::Want want;
215 const std::string PARAM_KEY = "appLinkingOnly"; // Use App Linking Mode
216 want.SetUri(uriSchemeValue);
217 want.SetParam(PARAM_KEY, false);
218 want.SetParam("remoteTagService", tagServiceIface);
219 ExternalDepsProxy::GetInstance().SetWantExtraParam(tagInfo, want);
220 int32_t errCode = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
221 if (errCode) {
222 ErrorLog(
223 "call StartAbility fail. uriSchemeValue = [%{public}s] ret = %{public}d", uriSchemeValue.c_str(), errCode);
224 return false;
225 }
226 ExternalDepsProxy::GetInstance().WriteDispatchToAppHiSysEvent(want.GetElement().GetBundleName(),
227 SubErrorCode::NDEF_URI_BROWSER_DISPATCH);
228 return true;
229 }
230 } // namespace TAG
231 } // namespace NFC
232 } // namespace OHOS