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()36 NdefHarDispatch::NdefHarDispatch()
37 {
38 }
39 
GetInstance()40 NdefHarDispatch& NdefHarDispatch::GetInstance()
41 {
42     static NdefHarDispatch instance;
43     return instance;
44 }
45 
GetBundleMgrProxy()46 sptr<AppExecFwk::IBundleMgr> NdefHarDispatch::GetBundleMgrProxy()
47 {
48     sptr<ISystemAbilityManager> systemAbilityManager =
49         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
50     if (!systemAbilityManager) {
51         ErrorLog("GetBundleMgrProxy, systemAbilityManager is null");
52         return nullptr;
53     }
54     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
55     if (!remoteObject) {
56         ErrorLog("GetBundleMgrProxy, remoteObject is null");
57         return nullptr;
58     }
59     return iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
60 }
61 
62 /* Implicit matching, using mimetype to pull up app */
DispatchMimeType(const std::string & type,std::shared_ptr<KITS::TagInfo> tagInfo)63 bool NdefHarDispatch::DispatchMimeType(const std::string &type, std::shared_ptr<KITS::TagInfo> tagInfo)
64 {
65     if (type.empty() || tagInfo == nullptr) {
66         ErrorLog("NdefHarDispatch::DispatchMimeType type is empty");
67         return false;
68     }
69     AAFwk::Want want;
70     want.SetType(type);
71     ExternalDepsProxy::GetInstance().SetWantExtraParam(tagInfo, want);
72     if (GetBundleMgrProxy() == nullptr) {
73         ErrorLog("NdefHarDispatch::DispatchMimeType GetBundleMgrProxy is nullptr");
74         return false;
75     }
76     bool withDefault = false;
77     auto abilityInfoFlag = AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_DEFAULT
78         | AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_SKILL_URI
79         | AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_METADATA;
80     std::vector<AbilityInfo> abilityInfos;
81     std::vector<ExtensionAbilityInfo> extensionInfos;
82     bool findDefaultApp = false;
83     if (!GetBundleMgrProxy()->ImplicitQueryInfos(
84         want, abilityInfoFlag, USER_ID, withDefault, abilityInfos, extensionInfos, findDefaultApp)) {
85         ErrorLog("NdefHarDispatch::DispatchMimeType ImplicitQueryInfos false");
86         return false;
87     }
88     int32_t errCode = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
89     if (errCode) {
90         ErrorLog("NdefHarDispatch::DispatchMimeType call StartAbility fail. ret = %{public}d", errCode);
91         return false;
92     }
93     return true;
94 }
95 
96 /* Call GetLaunchWantForBundle through bundlename to obtain the want and pull up the app */
DispatchBundleAbility(const std::string & harPackage,std::shared_ptr<KITS::TagInfo> tagInfo,const std::string & mimeType,const std::string & uri)97 bool NdefHarDispatch::DispatchBundleAbility(const std::string &harPackage, std::shared_ptr<KITS::TagInfo> tagInfo,
98                                             const std::string &mimeType, const std::string &uri)
99 {
100     if (harPackage.empty()) {
101         ErrorLog("NdefHarDispatch::DispatchBundleAbility harPackage is empty");
102         return false;
103     }
104     std::string harPackageString = NfcSdkCommon::HexStringToAsciiString(harPackage);
105     AAFwk::Want want;
106     if (GetBundleMgrProxy() == nullptr) {
107         ErrorLog("NdefHarDispatch::GetBundleMgrProxy is nullptr");
108         return false;
109     }
110     int32_t errCode = GetBundleMgrProxy()->GetLaunchWantForBundle(harPackageString, want, USER_ID);
111     if (errCode) {
112         ErrorLog("NdefHarDispatch::GetLaunchWantForBundle fail. ret = %{public}d, harPackage = %{public}s",
113             errCode, harPackageString.c_str());
114         return false;
115     }
116     if (!mimeType.empty() && tagInfo != nullptr) {
117         want.SetType(mimeType);
118         ExternalDepsProxy::GetInstance().SetWantExtraParam(tagInfo, want);
119     }
120     if (uri.size() > 0) {
121         want.SetUri(uri);
122     }
123     errCode = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
124     if (errCode) {
125         ErrorLog("NdefHarDispatch::StartAbility fail. ret = %{public}d, harPackage = %{public}s",
126             errCode, harPackageString.c_str());
127         return false;
128     }
129     return true;
130 }
131 
DispatchUriToBundleAbility(const std::string & uri)132 bool NdefHarDispatch::DispatchUriToBundleAbility(const std::string &uri)
133 {
134     if (uri.empty()) {
135         ErrorLog("NdefHarDispatch::DispatchUriToBundleAbility uri is empty");
136         return false;
137     }
138     bool canOpen = false;
139     if (GetBundleMgrProxy() == nullptr) {
140         ErrorLog("NdefHarDispatch::DispatchUriToBundleAbility GetBundleMgrProxy is nullptr");
141         return false;
142     }
143     int32_t errCode = GetBundleMgrProxy()->CanOpenLink(uri, canOpen);
144     if (!errCode && canOpen) {
145         InfoLog("NdefHarDispatch::DispatchUriToBundleAbility CanOpenLink");
146     }
147     ErrorLog("CanOpenLink fail. errCode = %{public}d, canOpen = %{public}d", errCode, canOpen);
148     return false;
149 }
150 
151 /* Pulling web page links through browser */
DispatchWebLink(const std::string & webAddress,const std::string & browserBundleName)152 bool NdefHarDispatch::DispatchWebLink(const std::string &webAddress, const std::string &browserBundleName)
153 {
154     std::unique_lock<std::shared_mutex> guard(mutex_);
155     InfoLog("NdefHarDispatch::DispatchWebLink enter");
156     if (webAddress.empty() || browserBundleName.empty()) {
157         ErrorLog("NdefHarDispatch::DispatchWebLink is empty");
158         return false;
159     }
160     uri_ = webAddress;
161     browserBundleName_ = browserBundleName;
162     ExternalDepsProxy::GetInstance().PublishNfcNotification(NFC_BROWSER_NOTIFICATION_ID, uri_, 0);
163     return true;
164 }
165 
OnBrowserOpenLink()166 void NdefHarDispatch::OnBrowserOpenLink()
167 {
168     std::unique_lock<std::shared_mutex> guard(mutex_);
169     InfoLog("NdefHarDispatch::OnBrowserOpenLink, %{public}s, %{public}s",
170         NfcSdkCommon::CodeMiddlePart(browserBundleName_).c_str(), NfcSdkCommon::CodeMiddlePart(uri_).c_str());
171     AAFwk::Want want;
172     const std::string ABILITY_NAME = "MainAbility";
173     const std::string ACTION_NAME = "ohos.want.action.viewData";
174     const std::string ENTITY_NAME = "entity.system.browsable";
175     want.SetElementName(browserBundleName_, ABILITY_NAME);
176     want.SetAction(ACTION_NAME);
177     want.SetUri(uri_);
178     want.AddEntity(ENTITY_NAME);
179     int32_t errCode = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
180     if (errCode) {
181         ErrorLog("NdefHarDispatch::DispatchWebLink call StartAbility fail. ret = %{public}d", errCode);
182     }
183 }
184 } // namespace TAG
185 } // namespace NFC
186 } // namespace OHOS