• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #define ABILITY_WANT_PARAMS_UIEXTENSIONTARGETTYPE "ability.want.params.uiExtensionTargetType"
16 
17 #include "cj_picker.h"
18 
19 #include "modal_ui_extension_config.h"
20 #include "ability.h"
21 #include "ui_extension_context.h"
22 
23 namespace OHOS {
24 namespace CjPicker {
25 
26 using namespace OHOS::Ace;
27 
28 const int32_t ERR_OK = 0;
29 const int32_t ERR_INVALID_ARG = 13900020;
30 const int32_t ERR_INV = -1;
31 
GetUIContextByContext(OHOS::AbilityRuntime::Context * context)32 static Ace::UIContent* GetUIContextByContext(OHOS::AbilityRuntime::Context* context)
33 {
34     auto contextsptr = context->shared_from_this();
35     auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(contextsptr);
36     if (abilityContext == nullptr) {
37         auto uiExtensionContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(contextsptr);
38         if (uiExtensionContext == nullptr) {
39             HILOG_ERROR("[picker]: Fail to convert to abilityContext or uiExtensionContext");
40             return nullptr;
41         }
42         return uiExtensionContext->GetUIContent();
43     }
44     return abilityContext->GetUIContent();
45 }
46 
StartCjPickerExtension(OHOS::AbilityRuntime::Context * context,WantHandle want,void (* cjCallback)(PickerResult))47 static int32_t StartCjPickerExtension(OHOS::AbilityRuntime::Context* context,
48     WantHandle want, void (*cjCallback)(PickerResult))
49 {
50     HILOG_INFO("[picker]: StartPickerExtension begin.");
51     Ace::UIContent *uiContent;
52     if (window_) {
53         HILOG_INFO("[picker] Will get uiContent by window.");
54         uiContent = window_->GetUIContent();
55     } else {
56         HILOG_INFO("[picker] Will get uiContent by context.");
57         uiContent = GetUIContextByContext(context);
58     }
59 
60     if (uiContent == nullptr) {
61         HILOG_ERROR("[picker]: get uiContent failed");
62         return ERR_INVALID_ARG;
63     }
64     AAFwk::Want request = *reinterpret_cast<AAFwk::Want*>(want);
65 
66     std::string targetType = request.GetStringParam("extType");
67     std::string pickerType;
68     if (request.GetParams().HasParam("pickerType")) {
69         pickerType = request.GetStringParam("pickerType");
70     }
71     request.SetParam(ABILITY_WANT_PARAMS_UIEXTENSIONTARGETTYPE, targetType);
72     auto pickerCallback = std::make_shared<CjPickerCallBack>();
73     auto callback = std::make_shared<CjModalUICallback>(uiContent, pickerCallback, cjCallback);
74     Ace::ModalUIExtensionCallbacks extensionCallback = {
75         .onRelease = std::bind(&CjModalUICallback::OnRelease, callback, std::placeholders::_1),
76         .onResult = std::bind(&CjModalUICallback::OnResultForModal, callback, std::placeholders::_1,
77             std::placeholders::_2),
78         .onReceive = std::bind(&CjModalUICallback::OnReceive, callback, std::placeholders::_1),
79         .onError = std::bind(&CjModalUICallback::OnError, callback, std::placeholders::_1, std::placeholders::_2,
80             std::placeholders::_3),
81         .onDestroy = std::bind(&CjModalUICallback::OnDestroy, callback),
82     };
83     Ace::ModalUIExtensionConfig config;
84     config.prohibitedRemoveByNavigation = false;
85     config.prohibitedRemoveByRouter = false;
86     HILOG_INFO("[picker]: will CreateModalUIExtension by extType: %{public}s, pickerType: %{public}s",
87         targetType.c_str(), pickerType.c_str());
88     int sessionId = uiContent->CreateModalUIExtension(request, extensionCallback, config);
89     if (sessionId == 0) {
90         HILOG_ERROR("[picker]: create modalUIExtension failed");
91         return ERR_INVALID_ARG;
92     }
93     callback->SetSessionId(sessionId);
94     return ERR_OK;
95 }
96 
GetWindow(char * windowName,sptr<Rosen::Window> & window)97 static int32_t GetWindow(char* windowName, sptr<Rosen::Window> &window)
98 {
99     auto customWindow = Rosen::Window::Find(windowName);
100     if (!customWindow) {
101         HILOG_ERROR("[picker] Window find fail.");
102         return ERR_INV;
103     }
104     window = customWindow;
105     HILOG_INFO("[picker] Window found: %{public}s", windowName);
106     return ERR_OK;
107 }
108 
MallocCString(const std::string & origin)109 static char* MallocCString(const std::string &origin)
110 {
111     if (origin.empty()) {
112         return nullptr;
113     }
114     auto length = origin.length() + 1;
115     char *res = static_cast<char *>(malloc(sizeof(char) * length));
116     if (res == nullptr) {
117         return nullptr;
118     }
119     return std::char_traits<char>::copy(res, origin.c_str(), length);
120 }
121 
MallocStringVec(std::vector<std::string> & origin)122 static CArrString MallocStringVec(std::vector<std::string> &origin)
123 {
124     CArrString res{};
125     if (origin.empty()) {
126         return res;
127     }
128 
129     size_t size = origin.size();
130     if (size == 0 || size > std::numeric_limits<size_t>::max() / sizeof(char *)) {
131         return res;
132     }
133     res.head = static_cast<char **>(malloc(sizeof(char *) * size));
134     if (res.head == nullptr) {
135         return res;
136     }
137     size_t i = 0;
138     for (; i < size; ++i) {
139         res.head[i] = MallocCString(origin[i]);
140     }
141     res.size = static_cast<int64_t>(i);
142 
143     return res;
144 }
145 
MakePickerResult(std::shared_ptr<CjPickerCallBack> pickerCallback)146 static PickerResult MakePickerResult(std::shared_ptr<CjPickerCallBack> pickerCallback)
147 {
148     PickerResult ret{};
149     ret.resultCode = pickerCallback->resultCode;
150     ret.userSuffixIndex = pickerCallback->want.GetIntParam("userSuffixIndex", -1);
151     ret.isOriginal = pickerCallback->want.GetBoolParam("isOriginal", false);
152     if (pickerCallback->want.GetParams().HasParam("ability.params.stream")) {
153         auto list = pickerCallback->want.GetStringArrayParam("ability.params.stream");
154         ret.ability_params_stream = MallocStringVec(list);
155     }
156     if (pickerCallback->want.GetParams().HasParam("uriArr")) {
157         auto list = pickerCallback->want.GetStringArrayParam("uriArr");
158         ret.uriArr = MallocStringVec(list);
159     }
160     if (pickerCallback->want.GetParams().HasParam("select-item-list")) {
161         auto list = pickerCallback->want.GetStringArrayParam("select-item-list");
162         ret.photoUris = MallocStringVec(list);
163     }
164     return ret;
165 }
166 
167 extern "C" {
FfiOHOSFilePickerModalPicker(OHOS::AbilityRuntime::Context * context,WantHandle config,char * windowName,void (* callback)(PickerResult))168 int32_t FfiOHOSFilePickerModalPicker(OHOS::AbilityRuntime::Context* context,
169     WantHandle config, char* windowName, void (*callback)(PickerResult))
170 {
171     if (!context || !config) {
172         HILOG_ERROR("[picker] context or config is nullptr.");
173         return ERR_INVALID_ARG;
174     }
175     if (windowName) {
176         int32_t status = GetWindow(windowName, window_);
177         if (status != ERR_OK) {
178             return status;
179         }
180     }
181     return StartCjPickerExtension(context, config, callback);
182 }
183 }
184 
CjModalUICallback(Ace::UIContent * uiContent,std::shared_ptr<CjPickerCallBack> pickerCallBack,void (* callback)(PickerResult))185 CjModalUICallback::CjModalUICallback(Ace::UIContent* uiContent,
186     std::shared_ptr<CjPickerCallBack> pickerCallBack, void (*callback)(PickerResult))
187 {
188     this->uiContent = uiContent;
189     this->pickerCallBack_ = pickerCallBack;
190     this->callback = CJLambda::Create(callback);
191 }
192 
SetSessionId(int32_t sessionId)193 void CjModalUICallback::SetSessionId(int32_t sessionId)
194 {
195     this->sessionId_ = sessionId;
196 }
197 
OnRelease(int32_t releaseCode)198 void CjModalUICallback::OnRelease(int32_t releaseCode)
199 {
200     HILOG_INFO("[picker] OnRelease enter. release code is %{public}d", releaseCode);
201     if (!pickerCallBack_) {
202         HILOG_ERROR("[picker] OnRelease error");
203         return;
204     }
205     this->uiContent->CloseModalUIExtension(this->sessionId_);
206     pickerCallBack_->ready = true;
207 
208     auto ret = MakePickerResult(pickerCallBack_);
209     this->callback(ret);
210     if (window_) {
211         window_ = nullptr;
212     }
213 }
214 
OnError(int32_t code,const std::string & name,const std::string & message)215 void CjModalUICallback::OnError(int32_t code, const std::string& name, const std::string& message)
216 {
217     HILOG_ERROR("[picker] OnError enter. errorCode=%{public}d, name=%{public}s, message=%{public}s",
218         code, name.c_str(), message.c_str());
219     this->uiContent->CloseModalUIExtension(this->sessionId_);
220 }
221 
OnResultForModal(int32_t resultCode,const OHOS::AAFwk::Want & result)222 void CjModalUICallback::OnResultForModal(int32_t resultCode, const OHOS::AAFwk::Want &result)
223 {
224     HILOG_INFO("[picker] OnResultForModal enter. resultCode is %{public}d,", resultCode);
225     if (!pickerCallBack_) {
226         HILOG_ERROR("[picker] OnResultForModal error.");
227         return;
228     }
229     pickerCallBack_->resultCode = resultCode;
230     pickerCallBack_->want = result;
231 }
232 
OnReceive(const OHOS::AAFwk::WantParams & request)233 void CjModalUICallback::OnReceive(const OHOS::AAFwk::WantParams &request)
234 {
235     HILOG_INFO("[picker] OnReceive enter.");
236 }
237 
OnDestroy()238 void CjModalUICallback::OnDestroy()
239 {
240     HILOG_INFO("[picker] OnDestroy enter.");
241 }
242 
243 } // namespace CjPicker
244 } // namespace OHOS