diff --git a/bundle.json b/bundle.json index 9a6f3ee2e6062989551b44a2b0a7c4540ccd73ad..8d13cb9c063eb2b042dbb9941e55d85b5da74c1b 100644 --- a/bundle.json +++ b/bundle.json @@ -132,6 +132,7 @@ "//base/notification/distributed_notification_service/frameworks/ans:ans_client", "//base/notification/distributed_notification_service/frameworks/js/napi:napi_notification", "//base/notification/distributed_notification_service/frameworks/js/napi:napi_reminder", + "//base/notification/distributed_notification_service/interfaces/kits/napi:napi_packages", "//base/notification/distributed_notification_service/interfaces/ndk:ohnotification", "//base/notification/distributed_notification_service/frameworks/reminder:reminder_client", "//base/notification/distributed_notification_service/frameworks/ets:ani_packages" diff --git a/frameworks/ans/BUILD.gn b/frameworks/ans/BUILD.gn index c0b17fc2ecd1cbaff7fb247203d1836b3397a912..60c128ab75d15676aa2ac3bf070703a1f31eefeb 100644 --- a/frameworks/ans/BUILD.gn +++ b/frameworks/ans/BUILD.gn @@ -229,3 +229,48 @@ ohos_source_set("ans_manager_stub") { subsystem_name = "notification" part_name = "distributed_notification_service" } + +ohos_source_set("notification_subscriber_extension_ans") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + branch_protector_ret = "pac_ret" + + include_dirs = [] + + sources = [ + "${frameworks_module_ans_path}/src/notification_subscriber_extension.cpp", + "${frameworks_module_ans_path}/src/notification_subscriber_extension_context.cpp", + "${frameworks_module_ans_path}/src/notification_extension_content.cpp", + "${frameworks_module_ans_path}/src/notification_info.cpp", + ] + + configs = [] + public_configs = [ ":ans_innerkits_config" ] + + deps = [ ":ans_manager_interface" ] + + external_deps = [ + "ability_base:want", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "napi:ace_napi", + ] + + subsystem_name = "notification" + part_name = "distributed_notification_service" +} diff --git a/frameworks/ans/src/notification_extension_content.cpp b/frameworks/ans/src/notification_extension_content.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7dbfaba227822942c838e3dd1f77ea0ad935391c --- /dev/null +++ b/frameworks/ans/src/notification_extension_content.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "notification_extension_content.h" + +#include "ans_image_util.h" +#include "ans_log_wrapper.h" + +namespace OHOS { +namespace Notification { +void NotificationExtensionContent::SetTitle(const std::string& title) +{ + title_ = title; +} + +std::string NotificationExtensionContent::GetTitle() const +{ + return title_; +} + +void NotificationExtensionContent::SetText(const std::string& text) +{ + text_ = text; +} + +std::string NotificationExtensionContent::GetText() const +{ + return text_; +} + +std::string NotificationExtensionContent::Dump() +{ + return "title = " + title_ + ", text = " + text_; +} + +bool NotificationExtensionContent::ToJson(nlohmann::json &jsonObject) const +{ + jsonObject["title"] = title_; + jsonObject["text"] = text_; + return true; +} + +bool NotificationExtensionContent::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(title_)) { + ANS_LOGE("Failed to write title"); + return false; + } + + if (!parcel.WriteString(text_)) { + ANS_LOGE("Failed to write text"); + return false; + } + + return true; +} + +NotificationExtensionContent *NotificationExtensionContent::Unmarshalling(Parcel &parcel) +{ + auto templ = new (std::nothrow) NotificationExtensionContent(); + if (templ == nullptr) { + ANS_LOGE("null templ"); + return nullptr; + } + if (!templ->ReadFromParcel(parcel)) { + delete templ; + templ = nullptr; + } + + return templ; +} + +bool NotificationExtensionContent::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(title_)) { + ANS_LOGE("Failed to read title"); + return false; + } + + if (!parcel.ReadString(text_)) { + ANS_LOGE("Failed to read text"); + return false; + } + + return true; +} + +NotificationExtensionContent *NotificationExtensionContent::FromJson(const nlohmann::json &jsonObject) +{ + if (jsonObject.is_null() or !jsonObject.is_object()) { + ANS_LOGE("Invalid JSON object"); + return nullptr; + } + + auto pInfo = new (std::nothrow) NotificationExtensionContent(); + if (pInfo == nullptr) { + ANS_LOGE("null pInfo"); + return nullptr; + } + + const auto &jsonEnd = jsonObject.cend(); + if (jsonObject.find("title") != jsonEnd && jsonObject.at("title").is_string()) { + pInfo->title_ = jsonObject.at("title").get(); + } + + if (jsonObject.find("text") != jsonEnd && jsonObject.at("text").is_string()) { + pInfo->text_ = jsonObject.at("text").get(); + } + + return pInfo; +} +} // namespace Notification +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ans/src/notification_info.cpp b/frameworks/ans/src/notification_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a562f8ed76d987fbbaaca081302c0dfc40fe3b1b --- /dev/null +++ b/frameworks/ans/src/notification_info.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "notification_info.h" + +#include "ans_image_util.h" +#include "ans_log_wrapper.h" + +namespace OHOS { +namespace Notification { +void NotificationInfo::SetHashCode(const std::string& hashCode) +{ + hashCode_ = hashCode; +} + +std::string NotificationInfo::GetHashCode() const +{ + return hashCode_; +} + +void NotificationInfo::SetNotificationSlotType(NotificationConstant::SlotType notificationSlotType) +{ + notificationSlotType_ = notificationSlotType; +} + +NotificationConstant::SlotType NotificationInfo::GetNotificationSlotType() const +{ + return notificationSlotType_; +} + +void NotificationInfo::SetNotificationExtensionContent(std::shared_ptr content) +{ + content_ = content; +} + +std::shared_ptr NotificationInfo::GetNotificationExtensionContent() const +{ + return content_; +} + +void NotificationInfo::SetBundleName(const std::string& bundleName) +{ + bundleName_ = bundleName; +} + +std::string NotificationInfo::GetBundleName() const +{ + return bundleName_; +} + +void NotificationInfo::SetDeliveryTime(uint32_t deliveryTime) +{ + deliveryTime_ = deliveryTime; +} + +uint32_t NotificationInfo::GetDeliveryTime() const +{ + return deliveryTime_; +} + +void NotificationInfo::SetGroupName(const std::string& groupName) +{ + groupName_ = groupName; +} + +std::string NotificationInfo::GetGroupName() const +{ + return groupName_; +} + +std::string NotificationInfo::Dump() +{ + return "hashCode = " + hashCode_ + + ", notificationSlotType = " + std::to_string(static_cast(notificationSlotType_)) + + ", NotificationExtensionContent { title = " + (content_ ? content_->GetTitle() : "null") + + ", text = " + (content_ ? content_->GetText() : "null") + + " }, bundleName = " + bundleName_ + + ", deliveryTime = " + std::to_string(static_cast(deliveryTime_)) + + ", groupName = " + groupName_; +} + +bool NotificationInfo::ToJson(nlohmann::json &jsonObject) const +{ + jsonObject["hashCode"] = hashCode_; + jsonObject["notificationSlotType"] = notificationSlotType_; + + if (content_ != nullptr) { + nlohmann::json contentOptionObj; + if (!NotificationJsonConverter::ConvertToJson(content_.get(), contentOptionObj)) { + ANS_LOGE("Cannot convert notificationExtensionContent to JSON."); + return false; + } + jsonObject["content"] = contentOptionObj; + } + + jsonObject["bundleName"] = bundleName_; + jsonObject["deliveryTime"] = deliveryTime_; + jsonObject["groupName"] = groupName_; + + return true; +} + +bool NotificationInfo::Marshalling(Parcel &parcel) const +{ + if (!parcel.WriteString(hashCode_)) { + ANS_LOGE("Failed to write hashCode"); + return false; + } + + if (!parcel.WriteUint32(static_cast(notificationSlotType_))) { + ANS_LOGE("Failed to write notificationSlotType"); + return false; + } + + if (!parcel.WriteParcelable(content_.get())) { + ANS_LOGE("Failed to write content"); + return false; + } + + if (!parcel.WriteString(bundleName_)) { + ANS_LOGE("Failed to write bundleName"); + return false; + } + + if (!parcel.WriteUint32(static_cast(deliveryTime_))) { + ANS_LOGE("Failed to write deliveryTime"); + return false; + } + + if (!parcel.WriteString(groupName_)) { + ANS_LOGE("Failed to write groupName"); + return false; + } + + return true; +} + +NotificationInfo *NotificationInfo::Unmarshalling(Parcel &parcel) +{ + auto templ = new (std::nothrow) NotificationInfo(); + if (templ == nullptr) { + ANS_LOGE("null templ"); + return nullptr; + } + if (!templ->ReadFromParcel(parcel)) { + delete templ; + templ = nullptr; + } + + return templ; +} + +bool NotificationInfo::ReadFromParcel(Parcel &parcel) +{ + if (!parcel.ReadString(hashCode_)) { + ANS_LOGE("Failed to read hashCode"); + return false; + } + notificationSlotType_ = static_cast(parcel.ReadUint32()); + + content_ = std::shared_ptr(parcel.ReadParcelable()); + if (!content_) { + ANS_LOGE("Failed to read content"); + return false; + } + + bundleName_ = parcel.ReadString(); + deliveryTime_ = parcel.ReadUint32(); + groupName_ = parcel.ReadString(); + + return true; +} + +NotificationInfo *NotificationInfo::FromJson(const nlohmann::json &jsonObject) +{ + if (jsonObject.is_null() or !jsonObject.is_object()) { + ANS_LOGE("Invalid JSON object"); + return nullptr; + } + + auto pInfo = new (std::nothrow) NotificationInfo(); + if (pInfo == nullptr) { + ANS_LOGE("null pInfo"); + return nullptr; + } + + const auto &jsonEnd = jsonObject.cend(); + if (jsonObject.find("hashCode") != jsonEnd && jsonObject.at("hashCode").is_string()) { + pInfo->hashCode_ = jsonObject.at("hashCode").get(); + } + + if (jsonObject.find("notificationSlotType") != jsonEnd && + jsonObject.at("notificationSlotType").is_number_integer()) { + auto notificationSlotType = jsonObject.at("notificationSlotType").get(); + pInfo->notificationSlotType_ = static_cast(notificationSlotType); + } + + if (jsonObject.find("content") != jsonEnd) { + auto contentOptionObj = jsonObject.at("content"); + if (!contentOptionObj.is_null()) { + auto *pExtensionContent = + NotificationJsonConverter::ConvertFromJson(contentOptionObj); + if (pExtensionContent == nullptr) { + ANS_LOGE("null pExtensionContent"); + return nullptr; + } + + pInfo->content_ = std::shared_ptr(pExtensionContent); + } + } + + if (jsonObject.find("bundleName") != jsonEnd && jsonObject.at("bundleName").is_string()) { + pInfo->bundleName_ = jsonObject.at("bundleName").get(); + } + + if (jsonObject.find("deliveryTime") != jsonEnd && jsonObject.at("deliveryTime").is_number_integer()) { + pInfo->deliveryTime_ = jsonObject.at("deliveryTime").get(); + } + + if (jsonObject.find("groupName") != jsonEnd && jsonObject.at("groupName").is_string()) { + pInfo->groupName_ = jsonObject.at("groupName").get(); + } + + return pInfo; +} +} // namespace Notification +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ans/src/notification_subscriber_extension.cpp b/frameworks/ans/src/notification_subscriber_extension.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9414e608dfe39a6ac2ac9946a40392c6970e7d44 --- /dev/null +++ b/frameworks/ans/src/notification_subscriber_extension.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "notification_subscriber_extension.h" +#include "ans_log_wrapper.h" + +namespace OHOS { +namespace Notification { +using namespace OHOS::AppExecFwk; +NotificationSubscriberExtension* NotificationSubscriberExtension::Create( + const std::unique_ptr& runtime) +{ + return new (std::nothrow) NotificationSubscriberExtension(); +} + +void NotificationSubscriberExtension::Init(const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) +{ + ANS_LOGD("Init"); + ExtensionBase::Init(record, application, handler, token); +} + +std::shared_ptr NotificationSubscriberExtension::CreateAndInitContext( + const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) +{ + std::shared_ptr context = + ExtensionBase::CreateAndInitContext( + record, application, handler, token); + if (record == nullptr) { + ANS_LOGE("record is nullptr"); + return context; + } + return context; +} + +void NotificationSubscriberExtension::OnDestroy() +{ + ANS_LOGD("OnDestroy called"); +} + +void NotificationSubscriberExtension::OnReceiveMessage(const NotificationInfo& info) +{ + ANS_LOGD("OnReceiveMessage called"); +} + +void NotificationSubscriberExtension::OnCancelMessageList(const std::vector& hashCodes) +{ + ANS_LOGD("OnCancelMessageList called"); +} + +} // namespace Notification +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ans/src/notification_subscriber_extension_context.cpp b/frameworks/ans/src/notification_subscriber_extension_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..124bbf092f67d8c4dd004ff2a46a5ac9adc57822 --- /dev/null +++ b/frameworks/ans/src/notification_subscriber_extension_context.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "notification_subscriber_extension_context.h" + +#include "ans_image_util.h" +#include "ans_log_wrapper.h" +#include "ability_business_error.h" +#include "ability_manager_client.h" +#include "ability_manager_errors.h" +#include "accesstoken_kit.h" +#include "ipc_skeleton.h" +#include "tokenid_kit.h" + +namespace OHOS { +namespace Notification { +const size_t NotificationSubscriberExtensionContext::CONTEXT_TYPE_ID( + std::hash {} ("NotificationSubscriberExtensionContext")); + +NotificationSubscriberExtensionContext::NotificationSubscriberExtensionContext() {} + +NotificationSubscriberExtensionContext::~NotificationSubscriberExtensionContext() {} + +bool NotificationSubscriberExtensionContext::CheckCallerIsSystemApp() +{ + auto selfToken = IPCSkeleton::GetSelfTokenID(); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) { + ANS_LOGE("current app is not system app, not allow."); + return false; + } + return true; +} + +bool NotificationSubscriberExtensionContext::VerifyCallingPermission(const std::string& permissionName) const +{ + ANS_LOGD("VerifyCallingPermission permission %{public}s", permissionName.c_str()); + auto callerToken = IPCSkeleton::GetCallingTokenID(); + int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken, permissionName); + if (ret == Security::AccessToken::PermissionState::PERMISSION_DENIED) { + ANS_LOGE("permission %{public}s: PERMISSION_DENIED", permissionName.c_str()); + return false; + } + ANS_LOGD("verify AccessToken success"); + return true; +} +} // namespace Notification +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ets/BUILD.gn b/frameworks/ets/BUILD.gn index 6b425ad9b200f5eead3f5e9163f59f25f342a99e..c205765cd112ad0c548e6a6a3a643c2d2022ba3a 100644 --- a/frameworks/ets/BUILD.gn +++ b/frameworks/ets/BUILD.gn @@ -18,6 +18,7 @@ group("ani_packages") { deps = [ "./ani:notification_manager_ani", "./ani:notification_subscribe_ani", + "./ani:notification_subscribe_extension_ani", "./ets:ets_files", ] } diff --git a/frameworks/ets/ani/BUILD.gn b/frameworks/ets/ani/BUILD.gn index a322f9fc9bfdae8d597e2e000d983793791c59f8..55104bfe40fead2670771d5aa1d4a039ce713ac4 100644 --- a/frameworks/ets/ani/BUILD.gn +++ b/frameworks/ets/ani/BUILD.gn @@ -191,3 +191,62 @@ ohos_shared_library("notification_subscribe_ani") { subsystem_name = "${subsystem_name}" part_name = "${component_name}" } + +ohos_shared_library("notification_subscribe_extension_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "./include/extension", + "${core_path}/common/include", + "${inner_api_path}", + ] + + configs = [] + + sources = [ + "./src/extension/sts_notification_subscriber_extension.cpp", + "./src/extension/sts_notification_subscriber_extension_context.cpp", + "./src/sts_common.cpp", + "./src/sts_notification_extension_content.cpp", + "./src/sts_notification_info.cpp", + "./src/sts_notification_manager.cpp", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${frameworks_module_ans_path}:ans_innerkits", + "${frameworks_module_ans_path}:notification_subscriber_extension_ans", + ] + + external_deps = [ + "ability_base:want", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:ani_common", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "napi:ace_napi", + "resource_management:global_resmgr", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "${subsystem_name}" + part_name = "${component_name}" +} diff --git a/frameworks/ets/ani/include/extension/sts_notification_subscriber_extension.h b/frameworks/ets/ani/include/extension/sts_notification_subscriber_extension.h new file mode 100644 index 0000000000000000000000000000000000000000..1f1ca50f5cca8b1ef48cedcdee3e6f5f6e0fbe30 --- /dev/null +++ b/frameworks/ets/ani/include/extension/sts_notification_subscriber_extension.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_ANI_STS_SUBSCRIBER_EXTENSION_INFO_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_ANI_STS_SUBSCRIBER_EXTENSION_INFO_H + +#include "ability_handler.h" +#include "ani.h" +#include "context.h" +#include "ets_native_reference.h" +#include "ets_runtime.h" +#include "notification_subscriber_extension.h" +#include "notification_subscriber_extension_context.h" +#include "ohos_application.h" +#include "sts_notification_subscriber_extension_context.h" + +namespace OHOS { +namespace NotificationSts { +using namespace OHOS::AppExecFwk; +using namespace OHOS::AbilityRuntime; +using NotificationSubscriberExtension = OHOS::Notification::NotificationSubscriberExtension; +using NotificationInfo = OHOS::Notification::NotificationInfo; + +class StsNotificationSubscriberExtension : public NotificationSubscriberExtension { +public: + explicit StsNotificationSubscriberExtension(AbilityRuntime::ETSRuntime &stsRuntime); + virtual ~StsNotificationSubscriberExtension() override; + + static StsNotificationSubscriberExtension* Create(const std::unique_ptr& stsRuntime); + + void Init(const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) override; + + void OnStart(const AAFwk::Want& want) override; + + sptr OnConnect(const AAFwk::Want& want) override; + + void OnDisconnect(const AAFwk::Want& want) override; + + void OnStop() override; + + void OnDestroy() override; + void OnReceiveMessage(const NotificationInfo& info) override; + void OnCancelMessageList(const std::vector& hashCodes) override; + + void ResetEnv(ani_env* env); + + std::weak_ptr GetWeakPtr(); + + void CallObjectMethod(bool withResult, const char* name, const char* signature, ...); + +private: + void BindContext(ani_env *env, const std::shared_ptr &application); + ani_object CreateSTSContext(ani_env *env, std::shared_ptr context, + const std::shared_ptr &application); + AbilityRuntime::ETSRuntime& stsRuntime_; + std::unique_ptr stsObj_; +}; +} +} +#endif //BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_ANI_STS_SUBSCRIBER_EXTENSION_INFO_H \ No newline at end of file diff --git a/frameworks/ets/ani/include/extension/sts_notification_subscriber_extension_context.h b/frameworks/ets/ani/include/extension/sts_notification_subscriber_extension_context.h new file mode 100644 index 0000000000000000000000000000000000000000..eba28c2db9dabc4c11f97fce67f50c9153e9e01b --- /dev/null +++ b/frameworks/ets/ani/include/extension/sts_notification_subscriber_extension_context.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_ANI_STS_SUBSCRIBER_EXTENSION_CONTEXT_INFO_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_ANI_STS_SUBSCRIBER_EXTENSION_CONTEXT_INFO_H + +#include "ani.h" +#include "context.h" +#include "ohos_application.h" +#include "notification_subscriber_extension_context.h" + +namespace OHOS { +namespace NotificationSts { +using namespace OHOS::AbilityRuntime; +using NotificationSubscriberExtensionContext = OHOS::Notification::NotificationSubscriberExtensionContext; + +ani_object CreateNotificationSubscriberExtensionContext(ani_env *env, + std::shared_ptr context, + const std::shared_ptr &application); +} +} +#endif //BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_ANI_STS_SUBSCRIBER_EXTENSION_CONTEXT_INFO_H \ No newline at end of file diff --git a/frameworks/ets/ani/include/sts_notification_extension_content.h b/frameworks/ets/ani/include/sts_notification_extension_content.h new file mode 100644 index 0000000000000000000000000000000000000000..ddad2f79f72f79c47cf372144de1e3bc6d56a3b3 --- /dev/null +++ b/frameworks/ets/ani/include/sts_notification_extension_content.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_ETS_ANI_INCLUDE_STS_EXTENSION_CONTENT_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_ETS_ANI_INCLUDE_STS_EXTENSION_CONTENT_H + +#include "ani.h" +#include "notification_extension_content.h" + +namespace OHOS { +namespace NotificationSts { +using NotificationExtensionContent = OHOS::Notification::NotificationExtensionContent; + +ani_status UnwrapNotificationExtensionContent(ani_env *env, ani_object param, + NotificationExtensionContent &extensionContent); +ani_object WrapNotificationExtensionContent(ani_env* env, + const std::shared_ptr &extensionContent); +} +} +#endif //BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_ETS_ANI_INCLUDE_STS_EXTENSION_CONTENT_H \ No newline at end of file diff --git a/frameworks/ets/ani/include/sts_notification_info.h b/frameworks/ets/ani/include/sts_notification_info.h new file mode 100644 index 0000000000000000000000000000000000000000..21f00863cbbd5f0877dc4d15162100137b0b99ef --- /dev/null +++ b/frameworks/ets/ani/include/sts_notification_info.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_ETS_ANI_INCLUDE_STS_NOTIFICATION_INFO_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_ETS_ANI_INCLUDE_STS_NOTIFICATION_INFO_H + +#include "ani.h" +#include "notification_constant.h" +#include "notification_extension_content.h" +#include "notification_info.h" + +namespace OHOS { +namespace NotificationSts { +using NotificationInfo = OHOS::Notification::NotificationInfo; +using SlotType = OHOS::Notification::NotificationConstant::SlotType; + +ani_object WrapNotificationInfo(ani_env* env, const std::shared_ptr ¬ificationInfo); +} +} +#endif //BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_ETS_ANI_INCLUDE_STS_NOTIFICATION_INFO_H \ No newline at end of file diff --git a/frameworks/ets/ani/src/extension/sts_notification_subscriber_extension.cpp b/frameworks/ets/ani/src/extension/sts_notification_subscriber_extension.cpp new file mode 100644 index 0000000000000000000000000000000000000000..84a9066d3a04e98e5b8a7d804e1f33d61ab3771b --- /dev/null +++ b/frameworks/ets/ani/src/extension/sts_notification_subscriber_extension.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "sts_notification_subscriber_extension.h" + +#include "ability_manager_client.h" +#include "ans_log_wrapper.h" +#include "sts_common.h" +#include "sts_notification_info.h" + +namespace OHOS { +namespace NotificationSts { +using namespace OHOS::AppExecFwk; +using namespace OHOS::AbilityRuntime; + +StsNotificationSubscriberExtension* StsNotificationSubscriberExtension::Create(const std::unique_ptr& runtime) +{ + return new StsNotificationSubscriberExtension(static_cast(*runtime)); +} +StsNotificationSubscriberExtension::StsNotificationSubscriberExtension(ETSRuntime &stsRuntime) + : stsRuntime_(stsRuntime) {} +StsNotificationSubscriberExtension::~StsNotificationSubscriberExtension() +{ + ANS_LOGD("~StsNotificationSubscriberExtension called"); +} + +void StsNotificationSubscriberExtension::Init(const std::shared_ptr &record, + const std::shared_ptr &application, std::shared_ptr &handler, + const sptr &token) +{ + if (record == nullptr) { + ANS_LOGE("record null"); + return; + } + NotificationSubscriberExtension::Init(record, application, handler, token); + if (Extension::abilityInfo_ == nullptr || Extension::abilityInfo_->srcEntrance.empty()) { + ANS_LOGE("NotificationSubscriberExtension Init abilityInfo error"); + return; + } + std::string srcPath(Extension::abilityInfo_->moduleName + "/"); + srcPath.append(Extension::abilityInfo_->srcEntrance); + auto pos = srcPath.rfind("."); + if (pos != std::string::npos) { + srcPath.erase(pos); + srcPath.append(".abc"); + } + std::string moduleName(Extension::abilityInfo_->moduleName); + moduleName.append("::").append(abilityInfo_->name); + stsObj_ = stsRuntime_.LoadModule( + moduleName, srcPath, abilityInfo_->hapPath, abilityInfo_->compileMode == AppExecFwk::CompileMode::ES_MODULE, + false, abilityInfo_->srcEntrance); + if (stsObj_ == nullptr) { + ANS_LOGE("stsObj_ null"); + return; + } + + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + ANS_LOGE("null env"); + return; + } + BindContext(env, application); + return; +} + +void StsNotificationSubscriberExtension::BindContext(ani_env* env, const std::shared_ptr &application) +{ + ANS_LOGD("StsNotificationSubscriberExtension BindContext Call"); + auto context = GetContext(); + if (context == nullptr) { + ANS_LOGE("Failed to get context"); + return; + } + + ani_object contextObj = CreateSTSContext(env, context, application); + if (contextObj == nullptr) { + ANS_LOGE("null contextObj"); + return; + } + + ani_field contextField; + auto status = env->Class_FindField(stsObj_->aniCls, "context", &contextField); + if (status != ANI_OK) { + ANS_LOGE("Class_GetField context failed"); + ResetEnv(env); + return; + } + ani_ref contextRef = nullptr; + if (env->GlobalReference_Create(contextObj, &contextRef) != ANI_OK) { + ANS_LOGE("GlobalReference_Create contextObj failed"); + return; + } + if (env->Object_SetField_Ref(stsObj_->aniObj, contextField, contextRef) != ANI_OK) { + ANS_LOGE("Object_SetField_Ref contextObj failed"); + ResetEnv(env); + } +} + +ani_object StsNotificationSubscriberExtension::CreateSTSContext(ani_env* env, + std::shared_ptr context, + const std::shared_ptr &application) +{ + ani_object STSContext = CreateNotificationSubscriberExtensionContext(env, context, application); + return STSContext; +} + +std::weak_ptr StsNotificationSubscriberExtension::GetWeakPtr() +{ + return std::static_pointer_cast(shared_from_this()); +} + +void StsNotificationSubscriberExtension::OnDestroy() +{ + ANS_LOGD("OnDestroy called"); + + if (handler_ == nullptr) { + ANS_LOGE("handler is invalid"); + return; + } + std::weak_ptr wThis = GetWeakPtr(); + auto task = [wThis, this]() { + std::shared_ptr sThis = wThis.lock(); + if (sThis == nullptr) { + return; + } + ani_env* env = sThis->stsRuntime_.GetAniEnv(); + if (!env) { + ANS_LOGE("task env not found env"); + return; + } + + ani_object ani_data {}; + const char* signature = "V:V"; + CallObjectMethod(false, "onDestroy", signature, ani_data); + }; + handler_->PostTask(task, "OnDestroy"); +} + +void StsNotificationSubscriberExtension::OnReceiveMessage(const NotificationInfo& info) +{ + ANS_LOGD("OnReceiveMessage called"); + + if (handler_ == nullptr) { + ANS_LOGE("handler is invalid"); + return; + } + std::weak_ptr wThis = GetWeakPtr(); + auto task = [wThis, info, this]() { + std::shared_ptr sThis = wThis.lock(); + if (sThis == nullptr) { + return; + } + ani_env* env = sThis->stsRuntime_.GetAniEnv(); + if (!env) { + ANS_LOGE("task env not found env"); + return; + } + + ani_object ani_info = WrapNotificationInfo(env, std::make_shared(info)); + if(ani_info == nullptr){ + ANS_LOGW("WrapNotificationInfo failed"); + } + const char* signature = "Lnotification/notificationInfo/NotificationInfoInner;:V"; + CallObjectMethod(false, "onReceiveMessage", signature, ani_info); + }; + handler_->PostTask(task, "OnReceiveMessage"); +} + + +void StsNotificationSubscriberExtension::OnCancelMessageList(const std::vector& hashCodes) +{ + ANS_LOGD("OnCancelMessageList called"); + + if (handler_ == nullptr) { + ANS_LOGE("handler is invalid"); + return; + } + std::weak_ptr wThis = GetWeakPtr(); + auto task = [wThis, hashCodes, this]() { + std::shared_ptr sThis = wThis.lock(); + if (sThis == nullptr) { + return; + } + ani_env* env = sThis->stsRuntime_.GetAniEnv(); + if (!env) { + ANS_LOGE("task env not found env"); + return; + } + + ani_object aniObject {}; + ani_object aniArray = GetAniStringArrayByVectorString(env, const_cast&>(hashCodes)); + if (aniArray == nullptr) { + ANS_LOGE("aniArray is nullptr"); + return; + } + if (!SetPropertyByRef(env, aniObject, "hashCodes", aniArray)) { + ANS_LOGE("Set names failed"); + return; + } + const char* signature = "Lstd/core/Object;:V"; + CallObjectMethod(false, "onCancelMessageList", signature, aniObject); + }; + handler_->PostTask(task, "OnCancelMessageList"); +} + +void StsNotificationSubscriberExtension::ResetEnv(ani_env* env) +{ + env->DescribeError(); + env->ResetError(); +} + +void StsNotificationSubscriberExtension::OnStart(const AAFwk::Want& want) +{ + ANS_LOGD("%{public}s called.", __func__); + Extension::OnStart(want); +} + +void StsNotificationSubscriberExtension::OnStop() +{ + ANS_LOGD("%{public}s called.", __func__); + Extension::OnStop(); +} + +void StsNotificationSubscriberExtension::OnDisconnect(const AAFwk::Want& want) +{ + ANS_LOGD("%{public}s called.", __func__); + Extension::OnDisconnect(want); +} + +sptr StsNotificationSubscriberExtension::OnConnect(const AAFwk::Want& want) +{ + ANS_LOGD("%{public}s called.", __func__); + Extension::OnConnect(want); + return nullptr; +} + +void StsNotificationSubscriberExtension::CallObjectMethod( + bool withResult, const char *name, const char *signature, ...) +{ + ani_status status = ANI_ERROR; + ani_method method = nullptr; + auto env = stsRuntime_.GetAniEnv(); + if (!env) { + ANS_LOGE("env not found StsNotificationSubscriberExtensions"); + return; + } + if (stsObj_ == nullptr) { + ANS_LOGE("stsObj_ nullptr"); + return; + } + if ((status = env->Class_FindMethod(stsObj_->aniCls, name, signature, &method)) != ANI_OK) { + ANS_LOGE("Class_FindMethod nullptr:%{public}d", status); + return; + } + if (method == nullptr) { + return; + } + + ani_ref res = nullptr; + va_list args; + if (withResult) { + va_start(args, signature); + if ((status = env->Object_CallMethod_Ref_V(stsObj_->aniObj, method, &res, args)) != ANI_OK) { + ANS_LOGE("status : %{public}d", status); + } + va_end(args); + return; + } + va_start(args, signature); + if ((status = env->Object_CallMethod_Void_V(stsObj_->aniObj, method, args)) != ANI_OK) { + ANS_LOGE("status : %{public}d", status); + } + va_end(args); + return; +} +} +} \ No newline at end of file diff --git a/frameworks/ets/ani/src/extension/sts_notification_subscriber_extension_context.cpp b/frameworks/ets/ani/src/extension/sts_notification_subscriber_extension_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..edce563175c8617cb3028b56edbdd8eb7205c52b --- /dev/null +++ b/frameworks/ets/ani/src/extension/sts_notification_subscriber_extension_context.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "sts_notification_subscriber_extension_context.h" + +#include "ability_manager_client.h" +#include "ans_log_wrapper.h" +#include "ets_extension_context.h" +#include "sts_common.h" + +namespace OHOS { +namespace NotificationSts { +namespace { +constexpr const char* Notification_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME = +"L@ohos/application/NotificationSubscriberExtensionContext/NotificationSubscriberExtensionContext;"; +} + +static void StartAbility([[maybe_unused]] ani_env *env, + [[maybe_unused]] ani_object aniObj, ani_object wantObj) +{ + ANS_LOGD("StartAbility"); +} + +ani_object CreateNotificationSubscriberExtensionContext(ani_env *env, + std::shared_ptr context, + const std::shared_ptr &application) +{ + if (env == nullptr) { + ANS_LOGE("null env"); + return nullptr; + } + std::shared_ptr abilityInfo = nullptr; + if (context) { + abilityInfo = context->GetAbilityInfo(); + } + ani_class cls = nullptr; + ani_object contextObj = nullptr; + ani_field field = nullptr; + ani_method method = nullptr; + ani_status status = ANI_ERROR; + if ((status = env->FindClass(Notification_SUBSCRIBER_EXTENSION_CONTEXT_CLASS_NAME, &cls)) != ANI_OK) { + ANS_LOGE("find class status : %{public}d", status); + return nullptr; + } + std::array functions = { + ani_native_function { "", "L@ohos/app/ability/Want/Want;:V", + reinterpret_cast(StartAbility) }, + }; + if ((status = env->Class_BindNativeMethods(cls, functions.data(), functions.size())) != ANI_OK) { + ANS_LOGE("bind method status : %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindMethod(cls, "", ":V", &method)) != ANI_OK) { + ANS_LOGE("find Method status: %{public}d", status); + return nullptr; + } + if ((status = env->Object_New(cls, method, &contextObj)) != ANI_OK) { + ANS_LOGE("new Object status: %{public}d", status); + return nullptr; + } + if ((status = env->Class_FindField(cls, "nativeNotificationSubscriberExtensionContext", &field)) != ANI_OK) { + ANS_LOGE("find field status: %{public}d", status); + return nullptr; + } + ani_long nativeContextLong = (ani_long)context.get(); + if ((status = env->Object_SetField_Long(contextObj, field, nativeContextLong)) != ANI_OK) { + ANS_LOGE("set field status: %{public}d", status); + return nullptr; + } + if (application == nullptr) { + ANS_LOGE("application null"); + return nullptr; + } + OHOS::AbilityRuntime::CreateEtsExtensionContext(env, cls, contextObj, context, context->GetAbilityInfo()); + return contextObj; +} +} +} \ No newline at end of file diff --git a/frameworks/ets/ani/src/sts_notification_extension_content.cpp b/frameworks/ets/ani/src/sts_notification_extension_content.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b88d68059fab7183a3e066be0509b8f7f985e13 --- /dev/null +++ b/frameworks/ets/ani/src/sts_notification_extension_content.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "sts_notification_extension_content.h" + +#include "sts_common.h" +#include "ans_log_wrapper.h" + +namespace OHOS { +namespace NotificationSts { +ani_status UnwrapNotificationExtensionContent(ani_env *env, ani_object param, + NotificationExtensionContent &extensionContent) +{ + ANS_LOGD("UnwrapNotificationExtensionContent call"); + if (env == nullptr || param == nullptr) { + ANS_LOGE("UnwrapNotificationExtensionContent fail, has nullptr"); + return ANI_ERROR; + } + ani_status status = ANI_ERROR; + ani_boolean isUndefind = ANI_TRUE; + std::string title; + if ((status = GetPropertyString(env, param, "title", isUndefind, title)) != ANI_OK) { + ANS_LOGE("UnwrapNotificationExtensionContent : Get title failed"); + return ANI_INVALID_ARGS; + } + extensionContent.SetTitle(title); + + std::string text; + if ((status = GetPropertyString(env, param, "text", isUndefind, text)) != ANI_OK) { + ANS_LOGE("UnwrapNotificationExtensionContent : Get text failed"); + return ANI_INVALID_ARGS; + } + extensionContent.SetText(text); + + ANS_LOGD("UnwrapNotificationExtensionContent end"); + return status; +} + +bool SetNotificationExtensionContentByRequiredParameter( + ani_env *env, ani_class contentCls, ani_object &contentObject, + const std::shared_ptr &extensionContent) +{ + ANS_LOGD("SetExtensionContentParameter call"); + if (env == nullptr || contentCls == nullptr || contentObject == nullptr || extensionContent == nullptr) { + ANS_LOGE("SetExtensionContentParameter fail, has nullptr"); + return false; + } + // title: string; + if (!SetPropertyOptionalByString(env, contentObject, "title", extensionContent->GetTitle())) { + ANS_LOGE("SetExtensionContentParameter: Set title failed"); + return false; + } + + // text: string; + if (!SetPropertyOptionalByString(env, contentObject, "text", extensionContent->GetText())) { + ANS_LOGE("SetExtensionContentParameter: Set text failed"); + return false; + } + + ANS_LOGD("SetExtensionContentParameter end"); + return true; +} + +ani_object WrapNotificationExtensionContent(ani_env* env, + const std::shared_ptr &extensionContent) +{ + ANS_LOGD("WrapNotificationExtensionContent call"); + if (env == nullptr || extensionContent == nullptr) { + ANS_LOGE("WrapNotificationExtensionContent failed, has nullptr"); + return nullptr; + } + ani_object contentObject = nullptr; + ani_class contentCls = nullptr; + if (!CreateClassObjByClassName(env, + "Lnotification/notificationExtensionContent/NotificationExtensionContentInner;", contentCls, contentObject)) { + ANS_LOGE("WrapNotificationExtensionContent : CreateClassObjByClassName failed"); + return nullptr; + } + if (!SetNotificationExtensionContentByRequiredParameter(env, contentCls, contentObject, extensionContent)) { + ANS_LOGE("WrapNotificationExtensionContent : SetExtensionContentParameter failed"); + return nullptr; + } + + return contentObject; +} +} +} \ No newline at end of file diff --git a/frameworks/ets/ani/src/sts_notification_info.cpp b/frameworks/ets/ani/src/sts_notification_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..774c9ede9370f386c72125acc7369f8ffe9b15f3 --- /dev/null +++ b/frameworks/ets/ani/src/sts_notification_info.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "sts_notification_info.h" + +#include "sts_common.h" +#include "sts_notification_extension_content.h" +#include "sts_notification_manager.h" +#include "ans_log_wrapper.h" + +namespace OHOS { +namespace NotificationSts { + +bool SetOptionalFieldSlotType( + ani_env *env, const ani_class cls, ani_object &object, const std::string fieldName, const SlotType value) +{ + ANS_LOGD("SetOptionalFieldSlotType call"); + if (env == nullptr || cls == nullptr || object == nullptr) { + ANS_LOGE("SetOptionalFieldSlotType failed, has nullptr"); + return false; + } + ani_field field = nullptr; + ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field); + if (status != ANI_OK || field == nullptr) { + ANS_LOGE("Class_FindField failed or null field, status=%{public}d, fieldName=%{public}s", + status, fieldName.c_str()); + return false; + } + ani_enum_item enumItem = nullptr; + NotificationSts::SlotTypeCToEts(env, value, enumItem); + if (enumItem == nullptr) { + ANS_LOGE("null enumItem"); + return false; + } + status = env->Object_SetField_Ref(object, field, enumItem); + if (status != ANI_OK) { + ANS_LOGE("Object_SetField_Ref failed, status=%{public}d, fieldName=%{public}s", + status, fieldName.c_str()); + return false; + } + return true; +} + +bool SetNotificationInfoByRequiredParameter( + ani_env *env, ani_class infoCls, ani_object &infoObject, + const std::shared_ptr ¬ificationInfo) +{ + ANS_LOGD("SetNotificationInfoParameter call"); + if (env == nullptr || infoCls == nullptr || infoObject == nullptr || notificationInfo == nullptr) { + ANS_LOGE("SetNotificationInfoParameter fail, has nullptr"); + return false; + } + // hashCode: string; + if (!SetPropertyOptionalByString(env, infoObject, "hashCode", notificationInfo->GetHashCode())) { + ANS_LOGE("SetNotificationInfoParameter: Set hashCode failed"); + return false; + } + + // notificationSlotType: notificationManager.SlotType; + if (!SetOptionalFieldSlotType( + env, infoCls, infoObject, "notificationSlotType", notificationInfo->GetNotificationSlotType())) { + ANS_LOGE("SetNotificationInfoParameter: Set notificationSlotType failed"); + return false; + } + + // content: NotificationExtensionContent; + ani_object contentObj = WrapNotificationExtensionContent(env, notificationInfo->GetNotificationExtensionContent()); + if (contentObj == nullptr|| !SetPropertyByRef(env, infoObject, "content", contentObj)) { + ANS_LOGE("SetNotificationInfoParameter: Set content failed"); + return false; + } + + // bundleName?: string; + if (!SetPropertyOptionalByString(env, infoObject, "bundleName", notificationInfo->GetBundleName())) { + ANS_LOGD("SetNotificationInfoParameter: Set bundleName failed"); + } + + // deliveryTime?: number; + if (!SetPropertyOptionalByDouble(env, infoObject, "deliveryTime", notificationInfo->GetDeliveryTime())) { + ANS_LOGD("SetNotificationInfoParameter: Set time failed"); + } + + // groupName?: string; + if (!SetPropertyOptionalByString(env, infoObject, "groupName", notificationInfo->GetGroupName())) { + ANS_LOGD("SetNotificationInfoParameter: Set groupName failed"); + } + + ANS_LOGD("SetNotificationInfoParameter end"); + return true; +} + +ani_object WrapNotificationInfo(ani_env* env, + const std::shared_ptr ¬ificationInfo) +{ + ANS_LOGD("WrapNotificationInfo call"); + if (env == nullptr || notificationInfo == nullptr) { + ANS_LOGE("WrapNotificationInfo failed, has nullptr"); + return nullptr; + } + ani_object infoObject = nullptr; + ani_class infoCls = nullptr; + if (!CreateClassObjByClassName(env, + "Lnotification/notificationInfo/NotificationInfoInner;", infoCls, infoObject)) { + ANS_LOGE("WrapNotificationInfo : CreateClassObjByClassName failed"); + return nullptr; + } + if (!SetNotificationInfoByRequiredParameter(env, infoCls, infoObject, notificationInfo)) { + ANS_LOGE("WrapNotificationInfo : SetNotificationInfoParameter failed"); + return nullptr; + } + + return infoObject; +} +} +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.application.NotificationSubscriberExtensionAbility.ets b/frameworks/ets/ets/@ohos.application.NotificationSubscriberExtensionAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..5219d6a576dbbd4d9db05e981be9425300c1895f --- /dev/null +++ b/frameworks/ets/ets/@ohos.application.NotificationSubscriberExtensionAbility.ets @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type NotificationSubscriberExtensionContext from '@ohos.application.NotificationSubscriberExtensionContext'; +import { NotificationInfo } from 'notification.notificationInfo' + +export default class NotificationSubscriberExtensionAbility { + + context: NotificationSubscriberExtensionContext = {}; + + onDestroy(): void {} + + onReceiveMessage(notificationinfo: NotificationInfo): void { + console.log('onReceiveMessage, notificationinfo:' + notificationinfo.hashCode); + } + + onCancelMessageList(hashCodes: Array): void { + console.log('onReceiveMessage, hashCodes:' + hashCodes); + } +} diff --git a/frameworks/ets/ets/@ohos.application.NotificationSubscriberExtensionContext.ets b/frameworks/ets/ets/@ohos.application.NotificationSubscriberExtensionContext.ets new file mode 100644 index 0000000000000000000000000000000000000000..1fe0121dfeb473378619998d816d36ffdbc965fa --- /dev/null +++ b/frameworks/ets/ets/@ohos.application.NotificationSubscriberExtensionContext.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import ExtensionContext from 'application.ExtensionContext'; + +export default class NotificationSubscriberExtensionContext extends ExtensionContext {} \ No newline at end of file diff --git a/frameworks/ets/ets/notification/notificationExtensionContent.ets b/frameworks/ets/ets/notification/notificationExtensionContent.ets new file mode 100644 index 0000000000000000000000000000000000000000..726ca791706cf08a67212737063330d3695b0e5c --- /dev/null +++ b/frameworks/ets/ets/notification/notificationExtensionContent.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface NotificationExtensionContent { + title: string; + text: string; +} + +export class NotificationExtensionContentInner implements NotificationExtensionContent { + public title: string = ''; + public text: string = ''; +} \ No newline at end of file diff --git a/frameworks/ets/ets/notification/notificationExtensionContentInner.ets b/frameworks/ets/ets/notification/notificationExtensionContentInner.ets new file mode 100644 index 0000000000000000000000000000000000000000..c6a3d5f13d8c883279b9874fb74c78bee0d4e2b1 --- /dev/null +++ b/frameworks/ets/ets/notification/notificationExtensionContentInner.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { NotificationExtensionContent } from 'notification.notificationExtensionContent'; + +export class NotificationExtensionContentInner implements NotificationExtensionContent { + public title: string = ''; + public text: string = ''; +} \ No newline at end of file diff --git a/frameworks/ets/ets/notification/notificationInfo.ets b/frameworks/ets/ets/notification/notificationInfo.ets new file mode 100644 index 0000000000000000000000000000000000000000..cbc4fb9662ea44d27c70ce371db189515681560f --- /dev/null +++ b/frameworks/ets/ets/notification/notificationInfo.ets @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type notificationManager from '@ohos.notificationManager'; +import { NotificationExtensionContent } from 'notification.notificationExtensionContent'; +import { NotificationExtensionContentInner } from './notificationExtensionContentInner'; + +export interface NotificationInfo { + readonly hashCode: string; + readonly notificationSlotType: notificationManager.SlotType; + readonly content: NotificationExtensionContent; + readonly bundleName?: string; + readonly deliveryTime?: number; + readonly groupName?:string; +} + +class NotificationInfoInner implements NotificationInfo { + public readonly hashCode: string = ''; + public readonly notificationSlotType: notificationManager.SlotType = + notificationManager.SlotType.UNKNOWN_TYPE; + public readonly content: NotificationExtensionContent = new NotificationExtensionContentInner; + public readonly bundleName?: string | undefined; + public readonly deliveryTime?: number | undefined; + public readonly groupName?: string | undefined; +} \ No newline at end of file diff --git a/frameworks/js/napi/BUILD.gn b/frameworks/js/napi/BUILD.gn index ac0505b7841a38f8f784120ab7559e7bc100501f..1178a9b25cec65fabbf03ce0c6d830e02865e8cd 100644 --- a/frameworks/js/napi/BUILD.gn +++ b/frameworks/js/napi/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2023 Huawei Device Co., Ltd. +# Copyright (c) 2021-2025 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -24,6 +24,8 @@ group("napi_reminder") { group("napi_notification") { deps = [ ":notification", + "src/extension:notification_subscriber_extension", + "src/extension:notification_subscriber_extension_module", "src/manager:notificationmanager", "src/subscribe:notificationsubscribe", ] @@ -72,6 +74,7 @@ ohos_shared_library("notification") { "src/common_convert_content.cpp", "src/common_convert_liveview.cpp", "src/common_convert_notification.cpp", + "src/common_convert_notification_info.cpp", "src/common_convert_request.cpp", "src/common_utils.cpp", "src/constant.cpp", diff --git a/frameworks/js/napi/include/common.h b/frameworks/js/napi/include/common.h index 2f6db2f460aa19ab51bc6719e19f8fe0f97b20ff..b0e07c9f4fa8162c15123f14c5084934ac979005 100644 --- a/frameworks/js/napi/include/common.h +++ b/frameworks/js/napi/include/common.h @@ -20,6 +20,7 @@ #include "napi/native_node_api.h" #include "notification_button_option.h" #include "notification_helper.h" +#include "notification_info.h" #include "notification_local_live_view_button.h" #include "notification_progress.h" #include "notification_time.h" @@ -232,6 +233,28 @@ public: */ static napi_value SetNotification( const napi_env &env, const OHOS::Notification::Notification *notification, napi_value &result); + + /** + * @brief Sets a js object by specified NotificationInfo object + * + * @param env Indicates the environment that the API is invoked under + * @param notification Indicates a NotificationInfo object to be converted + * @param result Indicates a js object to be set + * @return Returns the null object if success, returns the null value otherwise + */ + static napi_value SetNotificationInfo( + const napi_env &env, const OHOS::Notification::NotificationInfo *notificationInfo, napi_value &result); + + /** + * @brief Sets a js object by specified NotificationExtensionContent object + * + * @param env Indicates the environment that the API is invoked under + * @param notification Indicates a NotificationExtensionContent object to be converted + * @param result Indicates a js object to be set + * @return Returns the null object if success, returns the null value otherwise + */ + static napi_value SetNotificationExtensionContent(const napi_env &env, + const std::shared_ptr ¬ificationExtensionContent, napi_value &result); /** * @brief Sets a js object by specified NotificationRequest object diff --git a/frameworks/js/napi/include/extension/js_notification_subscriber_extension.h b/frameworks/js/napi/include/extension/js_notification_subscriber_extension.h new file mode 100644 index 0000000000000000000000000000000000000000..7604d60450293102ae5f6ac32e1cda2ad09ddfd5 --- /dev/null +++ b/frameworks/js/napi/include/extension/js_notification_subscriber_extension.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_INCLUDE_SUBSCRIBER_EXTENSION_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_INCLUDE_SUBSCRIBER_EXTENSION_H +#include + +#include "common_event_data.h" +#include "js_runtime.h" +#include "native_engine/native_reference.h" +#include "native_engine/native_value.h" +#include "runtime.h" +#include "notification_subscriber_extension.h" + +namespace OHOS { +namespace NotificationNapi { +using namespace Notification; +class JsNotificationSubscriberExtension : public NotificationSubscriberExtension { +public: + explicit JsNotificationSubscriberExtension(AbilityRuntime::JsRuntime& jsRuntime); + virtual ~JsNotificationSubscriberExtension() override; + + /** + * @brief Create JsNotificationSubscriberExtension. + * + * @param runtime The runtime. + * @return The JsNotificationSubscriberExtension instance. + */ + static JsNotificationSubscriberExtension* Create(const std::unique_ptr& runtime); + + void Init(const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) override; + + void OnStart(const AAFwk::Want& want) override; + + sptr OnConnect(const AAFwk::Want& want) override; + + void OnDisconnect(const AAFwk::Want& want) override; + + void OnStop() override; + + virtual void OnDestroy() override; + virtual void OnReceiveMessage(const NotificationInfo& info) override; + virtual void OnCancelMessageList(const std::vector& hashCodes) override; + + void ExecNapiWrap(napi_env env, napi_value obj); + + std::weak_ptr GetWeakPtr(); + +private: + AbilityRuntime::JsRuntime& jsRuntime_; + std::unique_ptr jsObj_; +}; +} // namespace NotificationNapi +} // namespace OHOS + +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_INCLUDE_SUBSCRIBER_EXTENSION_H diff --git a/frameworks/js/napi/include/extension/js_notification_subscriber_extension_context.h b/frameworks/js/napi/include/extension/js_notification_subscriber_extension_context.h new file mode 100644 index 0000000000000000000000000000000000000000..64fa3e722a7002c23714f0a92ae1472ac2fce8de --- /dev/null +++ b/frameworks/js/napi/include/extension/js_notification_subscriber_extension_context.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_INCLUDE_SUBSCRIBER_EXTENSION_CONTEXT_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_INCLUDE_SUBSCRIBER_EXTENSION_CONTEXT_H + +#include + +#include "notification_subscriber_extension_context.h" +#include "native_engine/native_engine.h" + +namespace OHOS { +namespace NotificationNapi { +using namespace Notification; +napi_value CreateJsNotificationSubscriberExtensionContext(napi_env env, + std::shared_ptr context); + +class JsNotificationSubscriberExtensionContext final { +public: + explicit JsNotificationSubscriberExtensionContext( + const std::shared_ptr& context): context_(context) {} + ~JsNotificationSubscriberExtensionContext() = default; + + static void Finalizer(napi_env env, void* data, void* hint) + { + std::unique_ptr( + static_cast(data)); + } + + std::shared_ptr GetAbilityContext(); +private: + std::weak_ptr context_; +}; +} // namespace NotificationNapi +} // namespace OHOS + +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_INCLUDE_SUBSCRIBER_EXTENSION_CONTEXT_H + \ No newline at end of file diff --git a/frameworks/js/napi/include/extension/loader/notification_subscriber_extension_module_loader.h b/frameworks/js/napi/include/extension/loader/notification_subscriber_extension_module_loader.h new file mode 100644 index 0000000000000000000000000000000000000000..f1f07c8d880b0a6d41999093804eb36c7dc6f4ae --- /dev/null +++ b/frameworks/js/napi/include/extension/loader/notification_subscriber_extension_module_loader.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_SUBSCRIBER_EXTENSION_MODULE_LOADER_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_SUBSCRIBER_EXTENSION_MODULE_LOADER_H + +#include "extension_module_loader.h" +#include "runtime.h" + +namespace OHOS { +namespace EventFwk { +class NotificationSubscriberExtensionModuleLoader : public AbilityRuntime::ExtensionModuleLoader, + public Singleton { + DECLARE_SINGLETON(NotificationSubscriberExtensionModuleLoader); + +public: + /** + * @brief Create Extension. + * + * @param runtime The runtime. + * @return The Extension instance. + */ + AbilityRuntime::Extension* Create(const std::unique_ptr& runtime) const override; + + /** + * @brief Get the Params object + * + * @return std::map The map of extension type and extension name. + */ + std::map GetParams() override; +}; +} // namespace EventFwk +} // namespace OHOS +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_FRAMEWORKS_JS_NAPI_SUBSCRIBER_EXTENSION_MODULE_LOADER_H + \ No newline at end of file diff --git a/frameworks/js/napi/src/common_convert_notification_info.cpp b/frameworks/js/napi/src/common_convert_notification_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e8b24b1ff6ec241d9d0d0a311c44d1b0c2eb512 --- /dev/null +++ b/frameworks/js/napi/src/common_convert_notification_info.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" +#include "ans_inner_errors.h" +#include "ans_log_wrapper.h" +#include "js_native_api.h" +#include "js_native_api_types.h" +#include "napi_common.h" +#include "napi_common_util.h" +#include "notification_info.h" +#include "notification_extension_content.h" +#include "notification_constant.h" + +namespace OHOS { +namespace NotificationNapi { + +napi_value NapiGetNull(napi_env env) +{ + napi_value result = nullptr; + napi_get_null(env, &result); + + return result; +} + +napi_value Common::SetNotificationExtensionContent(const napi_env &env, + const std::shared_ptr ¬ificationExtensionContent, napi_value &result) +{ + ANS_LOGD("called"); + + if (notificationExtensionContent == nullptr) { + ANS_LOGE("null notificationExtensionContent"); + return NapiGetBoolean(env, false); + } + napi_value value = nullptr; + // title: string; + napi_create_string_utf8(env, notificationExtensionContent->GetTitle().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, "title", value); + + // text: string; + napi_create_string_utf8(env, notificationExtensionContent->GetText().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, "notificationText", value); + + return NapiGetBoolean(env, true); +} + +napi_value Common::SetNotificationInfo( + const napi_env &env, const OHOS::Notification::NotificationInfo *notificationInfo, napi_value &result) +{ + ANS_LOGD("called"); + + if (notificationInfo == nullptr) { + ANS_LOGE("null notificationInfo"); + return NapiGetBoolean(env, false); + } + napi_value value = nullptr; + + // readonly hashCode: string; + napi_create_string_utf8(env, notificationInfo->GetHashCode().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, "hashCode", value); + + // readonly notificationSlotType: notificationManager.SlotType; + napi_create_uint32(env, static_cast(notificationInfo->GetNotificationSlotType()), &value); + napi_set_named_property(env, result, "notificationSlotType", value); + + //readonly content: NotificationExtensionContent; + std::shared_ptr content = notificationInfo->GetNotificationExtensionContent(); + if (content) { + napi_value contentResult = nullptr; + napi_create_object(env, &contentResult); + if (!SetNotificationExtensionContent(env, content, contentResult)) { + ANS_LOGE("SetNotificationExtensionContent call failed"); + return NapiGetBoolean(env, false); + } + napi_set_named_property(env, result, "content", contentResult); + } else { + ANS_LOGE("null content"); + return NapiGetBoolean(env, false); + } + + // readonly bundleName?: string; + napi_create_string_utf8(env, notificationInfo->GetBundleName().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, "bundleName", value); + + // readonly deliveryTime?: number; + napi_create_uint32(env, notificationInfo->GetDeliveryTime(), &value); + napi_set_named_property(env, result, "deliveryTime", value); + + // readonly groupName?:string; + napi_create_string_utf8(env, notificationInfo->GetGroupName().c_str(), NAPI_AUTO_LENGTH, &value); + napi_set_named_property(env, result, "groupName", value); + + return NapiGetBoolean(env, true); +} +} +} \ No newline at end of file diff --git a/frameworks/js/napi/src/extension/BUILD.gn b/frameworks/js/napi/src/extension/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3b19162036faa23af0e883e572afa6e84efc31c6 --- /dev/null +++ b/frameworks/js/napi/src/extension/BUILD.gn @@ -0,0 +1,111 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/notification/distributed_notification_service/notification.gni") +import("//build/ohos.gni") + +ohos_shared_library("notification_subscriber_extension") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + branch_protector_ret = "pac_ret" + + include_dirs = [ + "${frameworks_path}/js/napi/include", + "${frameworks_path}/js/napi/include/extension", + ] + + sources = [ + "js_notification_subscriber_extension.cpp", + "js_notification_subscriber_extension_context.cpp", + "${frameworks_path}/js/napi/src/common_convert_notification_info.cpp", + "${frameworks_path}/js/napi/src/common_utils.cpp", + ] + + deps = [ + "${frameworks_module_ans_path}:ans_innerkits", + "${frameworks_module_ans_path}:notification_subscriber_extension_ans", + ] + + external_deps = [ + "ability_base:want", + "ability_runtime:ability_context_native", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_common", + "ability_runtime:runtime", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "c_utils:utils", + "ffrt:libffrt", + "eventhandler:libeventhandler", + "hilog:libhilog", + "image_framework:image", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + ] + + subsystem_name = "${subsystem_name}" + part_name = "${component_name}" +} + +ohos_shared_library("notification_subscriber_extension_module") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + branch_protector_ret = "pac_ret" + + include_dirs = [ + "${frameworks_path}/js/napi/include/extension/loader", + "${frameworks_path}/js/napi/include/extension", + ] + + sources = [ "./loader/notification_subscriber_extension_module_loader.cpp" ] + + deps = [ + ":notification_subscriber_extension", + "${frameworks_module_ans_path}:ans_innerkits", + ] + + external_deps = [ + "ability_base:configuration", + "ability_base:session_info", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:extensionkit_native", + "ability_runtime:runtime", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "ipc:ipc_napi", + "napi:ace_napi", + ] + + relative_install_dir = "extensionability" + subsystem_name = "${subsystem_name}" + part_name = "${component_name}" +} \ No newline at end of file diff --git a/frameworks/js/napi/src/extension/js_notification_subscriber_extension.cpp b/frameworks/js/napi/src/extension/js_notification_subscriber_extension.cpp new file mode 100644 index 0000000000000000000000000000000000000000..794c3dcd2863dc23bb70198cf9b5ae51fad3d71c --- /dev/null +++ b/frameworks/js/napi/src/extension/js_notification_subscriber_extension.cpp @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js_notification_subscriber_extension.h" +#include + +#include "ability_info.h" +#include "ability_handler.h" +#include "ans_log_wrapper.h" +#include "common.h" +#include "js_runtime.h" +#include "js_runtime_utils.h" +#include "js_notification_subscriber_extension_context.h" +#include "napi_common_want.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "napi_remote_object.h" + +namespace OHOS { +namespace NotificationNapi { +namespace { +constexpr size_t ARGC_ZERO = 0; +constexpr size_t ARGC_ONE = 1; +} + +using namespace OHOS::AppExecFwk; + +napi_value AttachNotificationSubscriberExtensionContext(napi_env env, void* value, void*) +{ + ANS_LOGD("AttachNotificationSubscriberExtensionContext"); + if (value == nullptr) { + ANS_LOGE("invalid parameter."); + return nullptr; + } + + auto ptr = reinterpret_cast*>(value)->lock(); + if (ptr == nullptr) { + ANS_LOGE("invalid context."); + return nullptr; + } + + napi_value object = CreateJsNotificationSubscriberExtensionContext(env, ptr); + auto napiContextObj = AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(env, + "application.NotificationSubscriberExtensionContext", &object, 1)->GetNapiValue(); + if (napiContextObj == nullptr) { + ANS_LOGE("load context failed."); + return nullptr; + } + napi_coerce_to_native_binding_object(env, napiContextObj, AbilityRuntime::DetachCallbackFunc, + AttachNotificationSubscriberExtensionContext, value, nullptr); + auto workContext = new (std::nothrow) std::weak_ptr(ptr); + if (workContext == nullptr) { + ANS_LOGE("invalid NotificationSubscriberExtensionContext."); + return nullptr; + } + napi_wrap(env, napiContextObj, workContext, + [](napi_env, void* data, void*) { + ANS_LOGI("Finalizer for weak_ptr notification subscriber extension context is called"); + delete static_cast*>(data); + }, nullptr, nullptr); + return napiContextObj; +} + +JsNotificationSubscriberExtension* JsNotificationSubscriberExtension::Create( + const std::unique_ptr& runtime) +{ + return new (std::nothrow) JsNotificationSubscriberExtension(static_cast(*runtime)); +} + +JsNotificationSubscriberExtension::JsNotificationSubscriberExtension(AbilityRuntime::JsRuntime& jsRuntime) + : jsRuntime_(jsRuntime) {} +JsNotificationSubscriberExtension::~JsNotificationSubscriberExtension() +{ + ANS_LOGD("Js notification subscriber extension destructor."); + auto context = GetContext(); + if (context) { + context->Unbind(); + } + + jsRuntime_.FreeNativeReference(std::move(jsObj_)); +} + +void JsNotificationSubscriberExtension::Init(const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) +{ + NotificationSubscriberExtension::Init(record, application, handler, token); + if (Extension::abilityInfo_->srcEntrance.empty()) { + ANS_LOGE("srcEntrance of abilityInfo is empty"); + return; + } + + std::string srcPath(Extension::abilityInfo_->moduleName + "/"); + srcPath.append(Extension::abilityInfo_->srcEntrance); + srcPath.erase(srcPath.rfind('.')); + srcPath.append(".abc"); + + std::string moduleName(Extension::abilityInfo_->moduleName); + moduleName.append("::").append(abilityInfo_->name); + ANS_LOGD("moduleName: %{public}s, srcPath: %{public}s.", moduleName.c_str(), srcPath.c_str()); + AbilityRuntime::HandleScope handleScope(jsRuntime_); + napi_env env = jsRuntime_.GetNapiEnv(); + + jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath, + abilityInfo_->compileMode == CompileMode::ES_MODULE); + if (jsObj_ == nullptr) { + ANS_LOGE("Failed to load module"); + return; + } + napi_value obj = jsObj_->GetNapiValue(); + if (obj == nullptr) { + ANS_LOGE("Failed to get notification subscriber extension object"); + return; + } + ExecNapiWrap(env, obj); +} + +void JsNotificationSubscriberExtension::ExecNapiWrap(napi_env env, napi_value obj) +{ + auto context = GetContext(); + if (context == nullptr) { + ANS_LOGE("Failed to get context"); + return; + } + + napi_value contextObj = CreateJsNotificationSubscriberExtensionContext(env, context); + auto shellContextRef = AbilityRuntime::JsRuntime::LoadSystemModuleByEngine( + env, "application.NotificationSubscriberExtensionContext", &contextObj, ARGC_ONE); + if (shellContextRef == nullptr) { + ANS_LOGE("Failed to get shell context reference"); + return; + } + napi_value nativeObj = shellContextRef->GetNapiValue(); + if (nativeObj == nullptr) { + ANS_LOGE("Failed to get context native object"); + return; + } + + auto workContext = new (std::nothrow) std::weak_ptr(context); + if (workContext == nullptr) { + ANS_LOGE("invalid NotificationSubscriberExtensionContext."); + return; + } + napi_coerce_to_native_binding_object(env, nativeObj, AbilityRuntime::DetachCallbackFunc, + AttachNotificationSubscriberExtensionContext, workContext, nullptr); + context->Bind(jsRuntime_, shellContextRef.release()); + napi_set_named_property(env, obj, "context", nativeObj); + + ANS_LOGD("Set notification subscriber extension context"); + napi_wrap(env, nativeObj, workContext, + [](napi_env, void* data, void*) { + ANS_LOGI("Finalizer for weak_ptr notification subscriber extension context is called"); + delete static_cast*>(data); + }, nullptr, nullptr); + + ANS_LOGI("Init end."); +} + +void JsNotificationSubscriberExtension::OnStart(const AAFwk::Want& want) +{ + ANS_LOGD("called"); + Extension::OnStart(want); +} + +void JsNotificationSubscriberExtension::OnStop() +{ + ANS_LOGD("called"); + Extension::OnStop(); +} + +sptr JsNotificationSubscriberExtension::OnConnect(const AAFwk::Want& want) +{ + ANS_LOGD("called"); + Extension::OnConnect(want); + return nullptr; +} + +void JsNotificationSubscriberExtension::OnDisconnect(const AAFwk::Want& want) +{ + ANS_LOGD("called"); + Extension::OnDisconnect(want); +} + +std::weak_ptr JsNotificationSubscriberExtension::GetWeakPtr() +{ + return std::static_pointer_cast(shared_from_this()); +} + +void JsNotificationSubscriberExtension::OnDestroy() +{ + ANS_LOGD("called"); + if (handler_ == nullptr) { + ANS_LOGE("handler is invalid"); + return; + } + std::weak_ptr wThis = GetWeakPtr(); + + auto task = [wThis]() { + std::shared_ptr sThis = wThis.lock(); + if (sThis == nullptr) { + return; + } + if (!sThis->jsObj_) { + ANS_LOGE("Not found NotificationSubscriberExtension.js"); + return; + } + + AbilityRuntime::HandleScope handleScope(sThis->jsRuntime_); + napi_env env = sThis->jsRuntime_.GetNapiEnv(); + + napi_value argv[] = {}; + napi_value obj = sThis->jsObj_->GetNapiValue(); + if (obj == nullptr) { + ANS_LOGE("Failed to get NotificationSubscriberExtension object"); + return; + } + + napi_value method = nullptr; + napi_get_named_property(env, obj, "onDestroy", &method); + if (method == nullptr) { + ANS_LOGE("Failed to get onDestroy from NotificationSubscriberExtension object"); + return; + } + napi_call_function(env, obj, method, ARGC_ZERO, argv, nullptr); + ANS_LOGD("JsNotificationSubscriberExtension js receive event called."); + }; + handler_->PostTask(task, "OnDestroy"); +} + +void JsNotificationSubscriberExtension::OnReceiveMessage(const NotificationInfo& info) +{ + ANS_LOGD("called"); + if (handler_ == nullptr) { + ANS_LOGE("handler is invalid"); + return; + } + std::weak_ptr wThis = GetWeakPtr(); + + auto task = [wThis, info]() { + std::shared_ptr sThis = wThis.lock(); + if (sThis == nullptr) { + return; + } + if (!sThis->jsObj_) { + ANS_LOGE("Not found NotificationSubscriberExtension.js"); + return; + } + + AbilityRuntime::HandleScope handleScope(sThis->jsRuntime_); + napi_env env = sThis->jsRuntime_.GetNapiEnv(); + napi_value napiInfo = nullptr; + napi_create_object(env, &napiInfo); + + if (!Common::SetNotificationInfo(env, &info, napiInfo)) { + ANS_LOGE("Set NotificationInfo object failed."); + return; + } + + napi_value argv[] = {napiInfo}; + napi_value obj = sThis->jsObj_->GetNapiValue(); + if (obj == nullptr) { + ANS_LOGE("Failed to get NotificationSubscriberExtension object"); + return; + } + + napi_value method = nullptr; + napi_get_named_property(env, obj, "onReceiveMessage", &method); + if (method == nullptr) { + ANS_LOGE("Failed to get onReceiveMessage from NotificationSubscriberExtension object"); + return; + } + napi_call_function(env, obj, method, ARGC_ONE, argv, nullptr); + ANS_LOGD("JsNotificationSubscriberExtension js receive event called."); + }; + handler_->PostTask(task, "OnReceiveMessage"); +} + +void JsNotificationSubscriberExtension::OnCancelMessageList(const std::vector& hashCodes) +{ + ANS_LOGD("called"); + if (handler_ == nullptr) { + ANS_LOGE("handler is invalid"); + return; + } + std::weak_ptr wThis = GetWeakPtr(); + + auto task = [wThis, hashCodes]() { + std::shared_ptr sThis = wThis.lock(); + if (sThis == nullptr) { + return; + } + if (!sThis->jsObj_) { + ANS_LOGE("Not found NotificationSubscriberExtension.js"); + return; + } + + AbilityRuntime::HandleScope handleScope(sThis->jsRuntime_); + napi_env env = sThis->jsRuntime_.GetNapiEnv(); + napi_value result = nullptr; + napi_create_object(env, &result); + + uint32_t count = 0; + napi_value napiHashCodes = nullptr; + napi_create_array(env, &napiHashCodes); + for (auto vec : hashCodes) { + napi_value vecValue = nullptr; + ANS_LOGD("hashCodes = %{public}s", vec.c_str()); + napi_create_string_utf8(env, vec.c_str(), NAPI_AUTO_LENGTH, &vecValue); + napi_set_element(env, napiHashCodes, count, vecValue); + count++; + } + napi_set_named_property(env, result, "hashCodes", napiHashCodes); + + napi_value argv[] = {result}; + napi_value obj = sThis->jsObj_->GetNapiValue(); + if (obj == nullptr) { + ANS_LOGE("Failed to get NotificationSubscriberExtension object"); + return; + } + + napi_value method = nullptr; + napi_get_named_property(env, obj, "onCancelMessageList", &method); + if (method == nullptr) { + ANS_LOGE("Failed to get onCancelMessageList from NotificationSubscriberExtension object"); + return; + } + napi_call_function(env, obj, method, ARGC_ONE, argv, nullptr); + ANS_LOGD("JsNotificationSubscriberExtension js receive event called."); + }; + handler_->PostTask(task, "OnCancelMessageList"); +} + +} // namespace NotificationNapi +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/src/extension/js_notification_subscriber_extension_context.cpp b/frameworks/js/napi/src/extension/js_notification_subscriber_extension_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1e10ac1a5b67dc5e4b5baad7c707ef12fa185ed --- /dev/null +++ b/frameworks/js/napi/src/extension/js_notification_subscriber_extension_context.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js_notification_subscriber_extension_context.h" + +#include "ability_business_error.h" +#include "ans_inner_errors.h" +#include "ans_log_wrapper.h" +#include "js_error_utils.h" +#include "js_extension_context.h" +#include "js_runtime.h" +#include "js_runtime_utils.h" +#include "napi/native_api.h" +#include "napi_common_want.h" +#include "want.h" + +namespace OHOS { +namespace NotificationNapi { +std::shared_ptr JsNotificationSubscriberExtensionContext::GetAbilityContext() +{ + return context_.lock(); +} + +napi_value CreateJsNotificationSubscriberExtensionContext(napi_env env, + std::shared_ptr context) +{ + ANS_LOGD("Create js notification subscriber extension context"); + std::shared_ptr abilityInfo = nullptr; + if (context) { + abilityInfo = context->GetAbilityInfo(); + } + + napi_value objValue = CreateJsExtensionContext(env, context, abilityInfo); + std::unique_ptr jsContext = + std::make_unique(context); + napi_wrap( + env, objValue, jsContext.release(), JsNotificationSubscriberExtensionContext::Finalizer, nullptr, nullptr); + + return objValue; +} +} // namespace NotificationNapi +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/src/extension/loader/notification_subscriber_extension_module_loader.cpp b/frameworks/js/napi/src/extension/loader/notification_subscriber_extension_module_loader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5795e9b231b3458f378d75c911c6ae864108f9d8 --- /dev/null +++ b/frameworks/js/napi/src/extension/loader/notification_subscriber_extension_module_loader.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "notification_subscriber_extension_module_loader.h" + +#include "ans_log_wrapper.h" +#include "notification_subscriber_extension.h" +#include "js_notification_subscriber_extension.h" + +#include + +constexpr char STS_NOTIFICATION_SUBSCRIBER_EXT_LIB_NAME[] = "libnotification_subscriber_extension_ani.z.so"; +static constexpr char STS_NOTIFICATION_SUBSCRIBER_EXT_CREATE_FUNC[] = + "OHOS_STS_NotificationSubscriberExtension_Creation"; + +namespace OHOS { +namespace EventFwk { +using namespace Notification; +using namespace NotificationNapi; +typedef NotificationSubscriberExtension* (*CREATE_FUNC)(const std::unique_ptr& runtime); + +__attribute__((no_sanitize("cfi"))) NotificationSubscriberExtension* CreateStsExtension( + const std::unique_ptr& runtime) +{ + void *handle = dlopen(STS_NOTIFICATION_SUBSCRIBER_EXT_LIB_NAME, RTLD_LAZY); + if (handle == nullptr) { + ANS_LOGE("open sts_notification_subscriber_extension library %{public}s failed, reason: %{public}sn", + STS_NOTIFICATION_SUBSCRIBER_EXT_LIB_NAME, dlerror()); + return new (std::nothrow) NotificationSubscriberExtension(); + } + + auto func = reinterpret_cast(dlsym(handle, STS_NOTIFICATION_SUBSCRIBER_EXT_CREATE_FUNC)); + if (func == nullptr) { + dlclose(handle); + ANS_LOGE("get sts_notification_subscriber_extension symbol %{public}s in %{public}s failed", + STS_NOTIFICATION_SUBSCRIBER_EXT_CREATE_FUNC, STS_NOTIFICATION_SUBSCRIBER_EXT_LIB_NAME); + return new (std::nothrow) NotificationSubscriberExtension(); + } + + auto instance = func(runtime); + if (instance == nullptr) { + dlclose(handle); + ANS_LOGE("get sts_notification_subscriber_extension instance in %{public}s failed", + STS_NOTIFICATION_SUBSCRIBER_EXT_CREATE_FUNC); + return new (std::nothrow) NotificationSubscriberExtension(); + } + return instance; +} + +NotificationSubscriberExtensionModuleLoader::NotificationSubscriberExtensionModuleLoader() = default; +NotificationSubscriberExtensionModuleLoader::~NotificationSubscriberExtensionModuleLoader() = default; + +AbilityRuntime::Extension* NotificationSubscriberExtensionModuleLoader::Create( + const std::unique_ptr& runtime) const +{ + ANS_LOGD("Create module loader."); + if (!runtime) { + return NotificationSubscriberExtension::Create(runtime); + } + + ANS_LOGI("Create runtime"); + switch (runtime->GetLanguage()) { + case AbilityRuntime::Runtime::Language::JS: + return JsNotificationSubscriberExtension::Create(runtime); + case AbilityRuntime::Runtime::Language::ETS: + return CreateStsExtension(runtime); + default: + return NotificationSubscriberExtension::Create(runtime); + } +} + +std::map NotificationSubscriberExtensionModuleLoader::GetParams() +{ + ANS_LOGD("Get params."); + std::map params; + // type means extension type in ExtensionAbilityType of extension_ability_info.h, 31 means notification_subscriber. + params.insert(std::pair("type", "31")); + // extension name + params.insert(std::pair("name", "NotificationSubscriberExtension")); + return params; +} + +extern "C" __attribute__((visibility("default"))) void* OHOS_EXTENSION_GetExtensionModule() +{ + return &NotificationSubscriberExtensionModuleLoader::GetInstance(); +} +} // namespace EventFwk +} // namespace OHOS + \ No newline at end of file diff --git a/interfaces/inner_api/notification_extension_content.h b/interfaces/inner_api/notification_extension_content.h new file mode 100644 index 0000000000000000000000000000000000000000..bf50f4be49fbfa791c6b4833ec293a429191eb08 --- /dev/null +++ b/interfaces/inner_api/notification_extension_content.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_NOTIFICATION_EXTENSION_CONTENT_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_NOTIFICATION_EXTENSION_CONTENT_H + +#include "notification_json_convert.h" +#include "parcel.h" + +namespace OHOS { +namespace Notification { +class NotificationExtensionContent : public Parcelable, public NotificationJsonConvertionBase { +public: + void SetTitle(const std::string& title); + std::string GetTitle() const; + + void SetText(const std::string& text); + std::string GetText() const; + + /** + * @brief Returns a string representation of the object. + * + * @return Returns a string representation of the object. + */ + virtual std::string Dump(); + + /** + * @brief Converts a NotificationExtensionContent object into a Json. + * + * @param jsonObject Indicates the Json object. + * @return Returns true if succeed; returns false otherwise. + */ + bool ToJson(nlohmann::json &jsonObject) const override; + + /** + * @brief Marshal a object into a Parcel. + * + * @param parcel the object into the parcel. + * @return Returns true if succeed; returns false otherwise. + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /** + * Unmarshal object from a Parcel. + * @return the NotificationExtensionContent + */ + static NotificationExtensionContent *Unmarshalling(Parcel &parcel); + + /** + * @brief Creates a NotificationExtensionContent object from a Json. + * + * @param jsonObject Indicates the Json object. + * @return Returns the NotificationExtensionContent object. + */ + static NotificationExtensionContent *FromJson(const nlohmann::json &jsonObject); + +private: + NotificationExtensionContent() = default; + + /** + * @brief Read a NotificationExtensionContent object from a Parcel. + * + * @param parcel Indicates the parcel object. + * @return Returns true if succeed; returns false otherwise. + */ + bool ReadFromParcel(Parcel &parcel); + +private: + std::string title_ {}; + std::string text_ {}; +}; +} // namespace Notification +} // namespace OHOS + +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_NOTIFICATION_EXTENSION_CONTENT_H \ No newline at end of file diff --git a/interfaces/inner_api/notification_info.h b/interfaces/inner_api/notification_info.h new file mode 100644 index 0000000000000000000000000000000000000000..50b213e5c36b2abec637eeb1923850578c3416f4 --- /dev/null +++ b/interfaces/inner_api/notification_info.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_NOTIFICATION_INFO_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_NOTIFICATION_INFO_H + +#include "notification_constant.h" +#include "notification_extension_content.h" +#include "notification_json_convert.h" +#include "parcel.h" + +namespace OHOS { +namespace Notification { +class NotificationInfo : public Parcelable, public NotificationJsonConvertionBase { +public: + void SetHashCode(const std::string& hashCode); + std::string GetHashCode() const; + + void SetNotificationSlotType(NotificationConstant::SlotType notificationSlotType); + NotificationConstant::SlotType GetNotificationSlotType() const; + + void SetNotificationExtensionContent(std::shared_ptr content); + std::shared_ptr GetNotificationExtensionContent() const; + + void SetBundleName(const std::string& bundleName); + std::string GetBundleName() const; + + void SetDeliveryTime(uint32_t deliveryTime); + uint32_t GetDeliveryTime() const; + + void SetGroupName(const std::string& groupName); + std::string GetGroupName() const; + + /** + * @brief Returns a string representation of the object. + * + * @return Returns a string representation of the object. + */ + virtual std::string Dump(); + + /** + * @brief Converts a NotificationInfo object into a Json. + * + * @param jsonObject Indicates the Json object. + * @return Returns true if succeed; returns false otherwise. + */ + bool ToJson(nlohmann::json &jsonObject) const override; + + /** + * @brief Marshal a object into a Parcel. + * + * @param parcel the object into the parcel. + * @return Returns true if succeed; returns false otherwise. + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /** + * Unmarshal object from a Parcel. + * @return the NotificationInfo + */ + static NotificationInfo *Unmarshalling(Parcel &parcel); + + /** + * @brief Creates a NotificationInfo object from a Json. + * + * @param jsonObject Indicates the Json object. + * @return Returns the NotificationInfo object. + */ + static NotificationInfo *FromJson(const nlohmann::json &jsonObject); + +private: + NotificationInfo() = default; + + /** + * @brief Read a NotificationInfo object from a Parcel. + * + * @param parcel Indicates the parcel object. + * @return Returns true if succeed; returns false otherwise. + */ + bool ReadFromParcel(Parcel &parcel); + +private: + std::string hashCode_ {}; + NotificationConstant::SlotType notificationSlotType_ {NotificationConstant::SlotType::ILLEGAL_TYPE}; + std::shared_ptr content_ {}; + std::string bundleName_ {}; + uint32_t deliveryTime_ = 0; + std::string groupName_ {}; +}; +} // namespace Notification +} // namespace OHOS + +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_NOTIFICATION_INFO_H \ No newline at end of file diff --git a/interfaces/inner_api/notification_subscriber_extension.h b/interfaces/inner_api/notification_subscriber_extension.h new file mode 100644 index 0000000000000000000000000000000000000000..5dde761f6f417457c22d413176b94b175a37b77b --- /dev/null +++ b/interfaces/inner_api/notification_subscriber_extension.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_NOTIFICATION_SUBSCRIBER_EXTENSION_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_NOTIFICATION_SUBSCRIBER_EXTENSION_H + +#include "common_event_data.h" +#include "extension_base.h" +#include "runtime.h" +#include "notification_info.h" +#include "notification_subscriber_extension_context.h" + +namespace OHOS { +namespace Notification { +class NotificationSubscriberExtension : public AbilityRuntime::ExtensionBase { +public: + NotificationSubscriberExtension() = default; + virtual ~NotificationSubscriberExtension() = default; + + std::shared_ptr CreateAndInitContext( + const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) override; + + void Init(const std::shared_ptr& record, + const std::shared_ptr& application, + std::shared_ptr& handler, + const sptr& token) override; + + static NotificationSubscriberExtension* Create(const std::unique_ptr& runtime); + + virtual void OnDestroy(); + virtual void OnReceiveMessage(const NotificationInfo& info); + virtual void OnCancelMessageList(const std::vector& hashCodes); +}; +} // namespace Notification +} // namespace OHOS + +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_NOTIFICATION_SUBSCRIBER_EXTENSION_H \ No newline at end of file diff --git a/interfaces/inner_api/notification_subscriber_extension_context.h b/interfaces/inner_api/notification_subscriber_extension_context.h new file mode 100644 index 0000000000000000000000000000000000000000..75dbf357e84301732f8546689a1c5d76182c00da --- /dev/null +++ b/interfaces/inner_api/notification_subscriber_extension_context.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_SUBSCRIBER_EXTENSION_CONTEXT_H +#define BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_SUBSCRIBER_EXTENSION_CONTEXT_H + +#include "extension_context.h" +#include "want.h" + +namespace OHOS { +namespace Notification { +class NotificationSubscriberExtensionContext : public AbilityRuntime::ExtensionContext { +public: + NotificationSubscriberExtensionContext(); + + virtual ~NotificationSubscriberExtensionContext(); + + using SelfType = NotificationSubscriberExtensionContext; + static const size_t CONTEXT_TYPE_ID; + +protected: + bool IsContext(size_t contextTypeId) override + { + return contextTypeId == CONTEXT_TYPE_ID || ExtensionContext::IsContext(contextTypeId); + } + + bool CheckCallerIsSystemApp(); + bool VerifyCallingPermission(const std::string& permissionName) const; +}; +} // namespace Notification +} // namespace OHOS + +#endif // BASE_NOTIFICATION_DISTRIBUTED_NOTIFICATION_SERVICE_INTERFACES_INNER_API_SUBSCRIBER_EXTENSION_CONTEXT_H \ No newline at end of file diff --git a/interfaces/kits/napi/BUILD.gn b/interfaces/kits/napi/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d78ab39db6c78e4687ea601ea0e97ef2f6dcbf2d --- /dev/null +++ b/interfaces/kits/napi/BUILD.gn @@ -0,0 +1,25 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/notification/distributed_notification_service/notification.gni") +import("//build/ohos.gni") + +group("napi_packages") { + deps = [] + if (support_jsapi) { + deps += [ + "${interfaces_path}/kits/napi/notification_subscriber_extension:notificationsubscriberextension_napi", + "${interfaces_path}/kits/napi/notification_subscriber_extension_context:notificationsubscriberextensioncontext_napi", + ] + } +} diff --git a/interfaces/kits/napi/notification_subscriber_extension/BUILD.gn b/interfaces/kits/napi/notification_subscriber_extension/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1873aa8ca7b4fcec0863d92db17ca2e205d57484 --- /dev/null +++ b/interfaces/kits/napi/notification_subscriber_extension/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/components/ets_frontend/es2abc_config.gni") +import("//build/ohos.gni") +import("//base/notification/distributed_notification_service/notification.gni") + +es2abc_gen_abc("gen_notification_subscriber_extension_ability_abc") { + src_js = rebase_path("notification_subscriber_extension_ability.js") + dst_file = + rebase_path(target_out_dir + "/notification_subscriber_extension_ability.abc") + in_puts = [ "notification_subscriber_extension_ability.js" ] + out_puts = [ target_out_dir + "/notification_subscriber_extension_ability.abc" ] + extra_args = [ "--module" ] +} + +gen_js_obj("notification_subscriber_extension_ability_js") { + input = "notification_subscriber_extension_ability.js" + output = target_out_dir + "/notification_subscriber_extension_ability.o" +} + +gen_js_obj("notification_subscriber_extension_ability_abc") { + input = get_label_info(":gen_notification_subscriber_extension_ability_abc", + "target_out_dir") + + "/notification_subscriber_extension_ability.abc" + output = target_out_dir + "/notification_subscriber_extension_ability_abc.o" + dep = ":gen_notification_subscriber_extension_ability_abc" +} + +ohos_shared_library("notificationsubscriberextension_napi") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + branch_protector_ret = "pac_ret" + + sources = [ "notification_subscriber_extension_ability_module.cpp" ] + + deps = [ + ":notification_subscriber_extension_ability_abc", + ":notification_subscriber_extension_ability_js", + ] + + external_deps = [ "napi:ace_napi" ] + + relative_install_dir = "module/application" + subsystem_name = "${subsystem_name}" + part_name = "${component_name}" +} diff --git a/interfaces/kits/napi/notification_subscriber_extension/notification_subscriber_extension_ability.js b/interfaces/kits/napi/notification_subscriber_extension/notification_subscriber_extension_ability.js new file mode 100644 index 0000000000000000000000000000000000000000..4f3b50294f577aa147c95e4b6ed5562fa837e2b8 --- /dev/null +++ b/interfaces/kits/napi/notification_subscriber_extension/notification_subscriber_extension_ability.js @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class NotificationSubscriberExtensionAbility { + onReceiveEvent(event) { + console.log('onReceiveEvent, event:' + event.code); + } + onDestroy() {} + onReceiveMessage(notificationinfo) { + console.log('onReceiveMessage, notificationinfo:' + notificationinfo.hashCode); + } + onCancelMessageList(hashCodes) { + console.log('onReceiveMessage, hashCodes:' + hashCodes); + }; +} + +export default NotificationSubscriberExtensionAbility; \ No newline at end of file diff --git a/interfaces/kits/napi/notification_subscriber_extension/notification_subscriber_extension_ability_module.cpp b/interfaces/kits/napi/notification_subscriber_extension/notification_subscriber_extension_ability_module.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5d5a04e874b5b536766b808934b2321944eb749 --- /dev/null +++ b/interfaces/kits/napi/notification_subscriber_extension/notification_subscriber_extension_ability_module.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "native_engine/native_engine.h" + +extern const char _binary_notification_subscriber_extension_ability_js_start[]; +extern const char _binary_notification_subscriber_extension_ability_js_end[]; +extern const char _binary_notification_subscriber_extension_ability_abc_start[]; +extern const char _binary_notification_subscriber_extension_ability_abc_end[]; + +extern "C" __attribute__((constructor)) +void NAPI_application_NotificationSubscriberExtensionAbility_AutoRegister() +{ + auto moduleManager = NativeModuleManager::GetInstance(); + NativeModule newModuleInfo = { + .name = "application.NotificationSubscriberExtensionAbility", + .fileName = "application/libnotificationsubscriberextension_napi.so/NotificationSubscriberExtensionAbility.js", + }; + + moduleManager->Register(&newModuleInfo); +} + +extern "C" __attribute__((visibility("default"))) +void NAPI_application_NotificationSubscriberExtensionAbility_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_notification_subscriber_extension_ability_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_notification_subscriber_extension_ability_js_end - + _binary_notification_subscriber_extension_ability_js_start; + } +} + +// NotificationSubscriberExtensionAbility JS register +extern "C" __attribute__((visibility("default"))) +void NAPI_application_NotificationSubscriberExtensionAbility_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_notification_subscriber_extension_ability_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_notification_subscriber_extension_ability_abc_end - + _binary_notification_subscriber_extension_ability_abc_start; + } +} + \ No newline at end of file diff --git a/interfaces/kits/napi/notification_subscriber_extension_context/BUILD.gn b/interfaces/kits/napi/notification_subscriber_extension_context/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..0136007474c6f55a462f8774f688d627ab24fac7 --- /dev/null +++ b/interfaces/kits/napi/notification_subscriber_extension_context/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/components/ets_frontend/es2abc_config.gni") +import("//build/ohos.gni") +import("//base/notification/distributed_notification_service/notification.gni") + +es2abc_gen_abc("gen_notification_subscriber_extension_context_abc") { + src_js = rebase_path("notification_subscriber_extension_context.js") + dst_file = + rebase_path(target_out_dir + "/notification_subscriber_extension_context.abc") + in_puts = [ "notification_subscriber_extension_context.js" ] + out_puts = [ target_out_dir + "/notification_subscriber_extension_context.abc" ] + extra_args = [ "--module" ] +} + +gen_js_obj("notification_subscriber_extension_context_js") { + input = "notification_subscriber_extension_context.js" + output = target_out_dir + "/notification_subscriber_extension_context.o" +} + +gen_js_obj("notification_subscriber_extension_context_abc") { + input = get_label_info(":gen_notification_subscriber_extension_context_abc", + "target_out_dir") + + "/notification_subscriber_extension_context.abc" + output = target_out_dir + "/notification_subscriber_extension_context_abc.o" + dep = ":gen_notification_subscriber_extension_context_abc" +} + +ohos_shared_library("notificationsubscriberextensioncontext_napi") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + branch_protector_ret = "pac_ret" + + sources = [ "notification_subscriber_extension_context_module.cpp" ] + + deps = [ + ":notification_subscriber_extension_context_abc", + ":notification_subscriber_extension_context_js", + ] + + external_deps = [ "napi:ace_napi" ] + + relative_install_dir = "module/application" + subsystem_name = "${subsystem_name}" + part_name = "${component_name}" +} diff --git a/interfaces/kits/napi/notification_subscriber_extension_context/notification_subscriber_extension_context.js b/interfaces/kits/napi/notification_subscriber_extension_context/notification_subscriber_extension_context.js new file mode 100644 index 0000000000000000000000000000000000000000..6fe9e3090119254e23aaf0628d87ae4eb24e25ef --- /dev/null +++ b/interfaces/kits/napi/notification_subscriber_extension_context/notification_subscriber_extension_context.js @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let ExtensionContext = requireNapi('application.ExtensionContext'); + +class NotificationSubscriberExtensionContext extends ExtensionContext { + constructor(obj) { + super(obj); + } + + startAbility(want, callback) { + return this.__context_impl__.startAbility(want, callback); + } +} + +export default NotificationSubscriberExtensionContext; \ No newline at end of file diff --git a/interfaces/kits/napi/notification_subscriber_extension_context/notification_subscriber_extension_context_module.cpp b/interfaces/kits/napi/notification_subscriber_extension_context/notification_subscriber_extension_context_module.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e067ae271907c64ad64b2e6d365c0761d490384 --- /dev/null +++ b/interfaces/kits/napi/notification_subscriber_extension_context/notification_subscriber_extension_context_module.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "native_engine/native_engine.h" + +extern const char _binary_notification_subscriber_extension_context_js_start[]; +extern const char _binary_notification_subscriber_extension_context_js_end[]; +extern const char _binary_notification_subscriber_extension_context_abc_start[]; +extern const char _binary_notification_subscriber_extension_context_abc_end[]; + +extern "C" __attribute__((constructor)) +void NAPI_application_NotificationSubscriberExtensionContext_AutoRegister() +{ + auto moduleManager = NativeModuleManager::GetInstance(); + NativeModule newModuleInfo = { + .name = "application.NotificationSubscriberExtensionContext", + .fileName = + "application/libnotificationsubscriberextensioncontext_napi.so/NotificationSubscriberExtensionContext.js", + }; + + moduleManager->Register(&newModuleInfo); +} + +extern "C" __attribute__((visibility("default"))) +void NAPI_application_NotificationSubscriberExtensionContext_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_notification_subscriber_extension_context_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_notification_subscriber_extension_context_js_end - + _binary_notification_subscriber_extension_context_js_start; + } +} + +// NotificationSubscriberExtensionContext JS register +extern "C" __attribute__((visibility("default"))) +void NAPI_application_NotificationSubscriberExtensionContext_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_notification_subscriber_extension_context_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_notification_subscriber_extension_context_abc_end - + _binary_notification_subscriber_extension_context_abc_start; + } +} + \ No newline at end of file