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 #ifndef CAMERA_PICKER_NAPI_H 17 #define CAMERA_PICKER_NAPI_H 18 19 #include <atomic> 20 #include <memory> 21 #include <cstdint> 22 23 #include "ability_context.h" 24 #include "camera_device.h" 25 #include "camera_napi_utils.h" 26 #include "context.h" 27 #include "ui_content.h" 28 #include "ui_extension_base/ui_extension_context.h" 29 30 namespace OHOS { 31 namespace CameraStandard { 32 33 typedef struct { 34 std::string saveUri; 35 CameraPosition cameraPosition; 36 int videoDuration; 37 } PickerProfile; 38 39 enum class PickerContextType : uint32_t { UNKNOWN, UI_EXTENSION, ABILITY }; 40 struct PickerContextProxy { PickerContextProxyPickerContextProxy41 PickerContextProxy(std::shared_ptr<AbilityRuntime::Context> context) : mContext_(context) 42 { 43 if (AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context) != nullptr) { 44 type_ = PickerContextType::UI_EXTENSION; 45 } else if (AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context) != nullptr) { 46 type_ = PickerContextType::ABILITY; 47 } else { 48 type_ = PickerContextType::UNKNOWN; 49 } 50 } 51 GetTypePickerContextProxy52 PickerContextType GetType() 53 { 54 return type_; 55 } 56 GetBundleNamePickerContextProxy57 std::string GetBundleName() 58 { 59 auto context = mContext_.lock(); 60 if (context != nullptr) { 61 return context->GetBundleName(); 62 } 63 return ""; 64 } 65 GetUIContentPickerContextProxy66 Ace::UIContent* GetUIContent() 67 { 68 auto context = mContext_.lock(); 69 if (context == nullptr) { 70 return nullptr; 71 } 72 switch (type_) { 73 case PickerContextType::UI_EXTENSION: { 74 auto ctx = AbilityRuntime::Context::ConvertTo<AbilityRuntime::UIExtensionContext>(context); 75 if (ctx != nullptr) { 76 return ctx->GetUIContent(); 77 } 78 break; 79 } 80 case PickerContextType::ABILITY: { 81 auto ctx = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context); 82 if (ctx != nullptr) { 83 return ctx->GetUIContent(); 84 } 85 break; 86 } 87 default: 88 // Do nothing 89 break; 90 } 91 return nullptr; 92 } 93 94 private: 95 std::weak_ptr<AbilityRuntime::Context> mContext_; 96 PickerContextType type_ = PickerContextType::UNKNOWN; 97 }; 98 99 enum class PickerMediaType : uint32_t { PHOTO, VIDEO }; 100 101 class UIExtensionCallback { 102 public: 103 explicit UIExtensionCallback(std::shared_ptr<PickerContextProxy> contextProxy); 104 void OnRelease(int32_t releaseCode); 105 void OnResult(int32_t resultCode, const OHOS::AAFwk::Want& result); 106 void OnReceive(const OHOS::AAFwk::WantParams& request); 107 void OnError(int32_t code, const std::string& name, const std::string& message); 108 void OnRemoteReady(const std::shared_ptr<OHOS::Ace::ModalUIExtensionProxy>& uiProxy); 109 void OnDestroy(); 110 void CloseWindow(); 111 SetSessionId(int32_t sessionId)112 inline void SetSessionId(int32_t sessionId) 113 { 114 sessionId_ = sessionId; 115 } 116 WaitResultLock()117 inline void WaitResultLock() 118 { 119 std::unique_lock<std::mutex> lock(cbMutex_); 120 while (!isCallbackReturned_) { 121 cbFinishCondition_.wait(lock); 122 } 123 } 124 NotifyResultLock()125 inline void NotifyResultLock() 126 { 127 std::unique_lock<std::mutex> lock(cbMutex_); 128 cbFinishCondition_.notify_one(); 129 } 130 GetResultCode()131 inline int32_t GetResultCode() 132 { 133 return resultCode_; 134 } 135 GetResultUri()136 inline std::string GetResultUri() 137 { 138 return resultUri_; 139 } 140 GetResultMediaType()141 inline std::string GetResultMediaType() 142 { 143 if (resultMode_ == "VIDEO") { 144 return "video"; 145 } 146 return "photo"; 147 } 148 149 private: 150 bool FinishPicker(int32_t code); 151 int32_t sessionId_ = 0; 152 int32_t resultCode_ = 0; 153 std::string resultUri_ = ""; 154 std::string resultMode_ = ""; 155 std::shared_ptr<PickerContextProxy> contextProxy_; 156 std::condition_variable cbFinishCondition_; 157 std::mutex cbMutex_; 158 bool isCallbackReturned_ = false; 159 }; 160 161 class CameraPickerNapi { 162 public: 163 static napi_value Init(napi_env env, napi_value exports); 164 static napi_value CreatePickerMediaType(napi_env env); 165 static napi_value CreatePickerProfile(napi_env env); 166 static napi_value CreatePickerResult(napi_env env); 167 168 static napi_value Pick(napi_env env, napi_callback_info info); 169 170 static napi_value CameraPickerNapiConstructor(napi_env env, napi_callback_info info); 171 static void CameraPickerNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint); 172 173 private: 174 static thread_local uint32_t cameraPickerTaskId; 175 static thread_local napi_ref sConstructor_; 176 static thread_local napi_ref mediaTypeRef_; 177 }; 178 179 struct CameraPickerAsyncContext : public AsyncContext { 180 std::string resultUri; 181 std::string errorMsg; 182 PickerProfile pickerProfile; 183 AAFwk::Want want; 184 std::shared_ptr<PickerContextProxy> contextProxy; 185 std::shared_ptr<UIExtensionCallback> uiExtCallback; 186 int32_t resultCode; 187 bool bRetBool; 188 }; 189 } // namespace CameraStandard 190 } // namespace OHOS 191 192 #endif /* CAMERA_PICKER_NAPI_H */ 193