!18431 merge dev_0214 into master

Set JsEnvironmentCallback::OnConfigurationUpdated callback to barrier

Created-by: whezzz
Commit-by: whezzz
Merged-by: openharmony_ci
Description: **IssueNo**:
https://gitcode.com/openharmony/ability_ability_runtime/issues/14546
**Description**:

**稳定性自检:**
| 自检项                                                       | 自检结果  |
| ------------------------------------------------------------ | -------- |
| 涉及跨进程调用的相关操作需要抛至主线程或加锁防止并发              |          |
| 成员变量进行赋值或创建需要排查并发                               |          |
| 谨慎在lambda表达式中使用引用捕获                                |          |
| 谨慎在未经拷贝的情况下使用外部传入的string、C字符串               |          |
| map\vector\list\set等stl模板类使用时需要排查并发                |          |
| 谨慎考虑加锁范围                                               |          |
| 在IPC通信中谨慎使用同步通信方式                                 |          |
| 禁止传递this指针至其他模块或线程(特别是eventhandler任务)        |          |
| 禁止将外部传入的裸指针在内部直接构造智能指针                      |          |
| 禁止多个独立创建的智能指针管理同一地址                           |          |
| 禁止在析构函数中抛异步任务                                      |          |
| 禁止js对象在非js线程(例如在IPC线程)创建、使用或销毁             |          |
| 禁止在对外接口中未经判空直接使用外部传入的指针                    |          |
| 禁止接口返回局部变量引用                                        |          |
| 禁止在信号函数中加锁                                            |          |
| 禁止在关键流程(SA启动、应用启动等主流程)执行耗时的操作           |          |
| 禁止将同一个cpp编译在不同的so中                                 |          |

**安全编码自检:**
| 自检项                                                          | 自检结果 |
| -------------------------------------------------------------- | -------- |
| 裸指针避免通过隐式转换构造为sptr                                 |          |
| json对象在取值之前必须先判断类型,避免类型不匹配                   |          |
| 序列化时必须对传入的数组大小进行校验,避免出现超大数组              |          |
| 避免使用未明确位宽的整型,选择使用int8_t、uint8_t等类型            |          |
| 外部传入的路径要做规范化校验,对路径中的.、..、../等特殊字符严格校验 |          |
| 指针变量、表示资源描述符的变量、bool变量必须赋初值                  |          |
| readParcelable获取的对象使用前需要判空                            |          |
| 分配和释放内存的函数需要成对出现                                   |          |
| 申请内存后异常退出前需要及时进行内存释放                            |          |
| 内存申请前必须对内存大小进行合法性校验                              |          |
| 内存分配后必须判断是否成功                                         |          |
| 禁止使用realloc、alloca函数                                       |          |
| 禁止打印文件路径、口令等敏感信息,如有需要,使用private修饰          |          |
| 禁止打印内存地址                                                  |          |
| 整数之间运算时必须严格检查,确保不会出现溢出、反转、除0               |          |
| 禁止对有符号整数进行位操作符运算                                    |          |
| 禁止对指针进行逻辑或位运算                                         |          |
| 循环次数如果收外部数据控制,需要检验其合法性                         |          |
| 禁止使用内存操作类危险函数,需要使用安全函数                         |          |
| 谨慎使用不可重入函数                                               |          |
| 必须检查安全函数的返回值,并进行正确处理                             |          |
| 禁止仅通过TokenType类型判断绕过权限校验                             |          |

**TDD Result**:

**XTS Result**:

### 是否已执行L0用例
- [ ] 已验证
- [ ] 不涉及。如不涉及,请写明理由


See merge request: openharmony/ability_ability_runtime!18431
This commit is contained in:
openharmony_ci
2026-02-25 16:17:40 +08:00
3 changed files with 233 additions and 13 deletions
@@ -61,20 +61,17 @@ void JsEnvironmentCallback::CallConfigurationUpdatedInner(const std::string &met
void JsEnvironmentCallback::OnConfigurationUpdated(const AppExecFwk::Configuration &config)
{
std::weak_ptr<JsEnvironmentCallback> thisWeakPtr(shared_from_this());
std::unique_ptr<NapiAsyncTask::CompleteCallback> complete = std::make_unique<NapiAsyncTask::CompleteCallback>(
[thisWeakPtr, config, callbacks = callbacks_, callbacksSync = callbacksSync_]
(napi_env env, NapiAsyncTask &task, int32_t status) {
std::shared_ptr<JsEnvironmentCallback> jsEnvCallback = thisWeakPtr.lock();
if (jsEnvCallback) {
jsEnvCallback->CallConfigurationUpdatedInner("onConfigurationUpdated", config, callbacks);
jsEnvCallback->CallConfigurationUpdatedInner("onConfigurationUpdated", config, callbacksSync);
}
auto callbacks = callbacks_;
auto callbacksSync = callbacksSync_;
// When vsync_first is enabled, events marked with napi_barrier_need are
// treated as barriers and will execute *before* the next vsync.
napi_send_event(env_, [thisWeakPtr, config, callbacks, callbacksSync]() {
std::shared_ptr<JsEnvironmentCallback> jsEnvCallback = thisWeakPtr.lock();
if (jsEnvCallback) {
jsEnvCallback->CallConfigurationUpdatedInner("onConfigurationUpdated", config, callbacks);
jsEnvCallback->CallConfigurationUpdatedInner("onConfigurationUpdated", config, callbacksSync);
}
);
napi_ref callback = nullptr;
std::unique_ptr<NapiAsyncTask::ExecuteCallback> execute = nullptr;
NapiAsyncTask::ScheduleLowQos("JsEnvironmentCallback::OnConfigurationUpdated",
env_, std::make_unique<NapiAsyncTask>(callback, std::move(execute), std::move(complete)));
}, napi_eprio_low, "JsEnvironmentCallback::OnConfigurationUpdated", napi_barrier_need);
}
void JsEnvironmentCallback::CallMemoryLevelInner(const std::string &methodName, const int level,
@@ -1270,6 +1270,61 @@ ohos_unittest("startup_manager_mock_test") {
]
}
ohos_unittest("js_environment_callback_test") {
module_out_path = module_output_path
include_dirs = [
"${ability_runtime_services_path}/common/include",
"${ability_runtime_test_path}/mock/common/include",
]
sources = [
"js_environment_callback_test.cpp",
]
configs = [ ":module_private_config" ]
deps = [
"${ability_runtime_innerkits_path}/ability_manager:ability_manager",
"${ability_runtime_innerkits_path}/app_manager:app_manager",
"${ability_runtime_innerkits_path}/deps_wrapper:ability_deps_wrapper",
"${ability_runtime_innerkits_path}/runtime:runtime",
"${ability_runtime_native_path}/ability/native:ability_thread",
"${ability_runtime_native_path}/ability/native:abilitykit_native",
"${ability_runtime_native_path}/ability/native:abilitykit_utils",
"${ability_runtime_native_path}/ability/native:configuration_helper",
"${ability_runtime_native_path}/ability/native:uiabilitykit_native",
"${ability_runtime_native_path}/appkit:app_context",
"${ability_runtime_native_path}/appkit:appkit_manager_helper",
"${ability_runtime_native_path}/appkit:appkit_native",
"${ability_runtime_path}/js_environment/frameworks/js_environment:js_environment",
]
external_deps = [
"ability_base:base",
"ability_base:configuration",
"ability_base:extractortool",
"ability_base:want",
"bundle_framework:appexecfwk_base",
"bundle_framework:appexecfwk_core",
"c_utils:utils",
"common_event_service:cesfwk_innerkits",
"eventhandler:libeventhandler",
"ffrt:libffrt",
"form_fwk:fmskit_native",
"googletest:gtest_main",
"hilog:libhilog",
"hitrace:hitrace_meter",
"init:libbegetutil",
"ipc:ipc_core",
"napi:ace_napi",
"resource_management:global_resmgr",
"resource_management:librawfile",
"samgr:samgr_proxy",
"runtime_core:ani",
]
}
###############################################################################
group("unittest") {
@@ -1297,6 +1352,7 @@ group("unittest") {
":extension_plugin_info_test",
":form_extension_context_test",
":idle_time_test",
":js_environment_callback_test",
":native_lib_util_test",
":overlay_event_subscriber_test",
":startup_manager_mock_test",
@@ -0,0 +1,167 @@
/*
* Copyright (c) 2026 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 <gtest/gtest.h>
#include "configuration.h"
#include "environment_callback.h"
#include "global_configuration_key.h"
#include "hilog_tag_wrapper.h"
#include "js_runtime.h"
#include "js_runtime_utils.h"
#include "napi/native_api.h"
#include "napi/native_common.h"
#include "native_engine/native_engine.h"
using namespace testing::ext;
using namespace OHOS;
using namespace OHOS::AbilityRuntime;
using namespace AAFwk;
namespace {
constexpr int32_t TEST_MEMORY_LEVEL = 1;
}
class JsEnvironmentCallbackTest : public testing::Test {
public:
static void SetUpTestCase() {}
static void TearDownTestCase() {}
void SetUp() override;
void TearDown() override;
protected:
std::unique_ptr<JsRuntime> jsRuntime_ = nullptr;
napi_env env_ = nullptr;
std::shared_ptr<JsEnvironmentCallback> jsEnvCallback_ = nullptr;
};
void JsEnvironmentCallbackTest::SetUp()
{
JsRuntime::Options options;
jsRuntime_ = JsRuntime::Create(options);
ASSERT_NE(jsRuntime_, nullptr);
env_ = jsRuntime_->GetNapiEnv();
ASSERT_NE(env_, nullptr);
jsEnvCallback_ = std::make_shared<JsEnvironmentCallback>(env_);
ASSERT_NE(jsEnvCallback_, nullptr);
}
void JsEnvironmentCallbackTest::TearDown()
{
jsEnvCallback_ = nullptr;
jsRuntime_.reset();
}
napi_value TestCallback(napi_env env, napi_callback_info info)
{
return nullptr;
}
/**
* @tc.name: JsEnvironmentCallback_OnConfigurationUpdated_001
* @tc.desc: Test OnConfigurationUpdated with valid config and registered callback
* @tc.type: FUNC
*/
HWTEST_F(JsEnvironmentCallbackTest, JsEnvironmentCallback_OnConfigurationUpdated_001, Function | MediumTest | Level1)
{
TAG_LOGI(AAFwkTag::APPKIT, "JsEnvironmentCallback_OnConfigurationUpdated_001 start");
napi_value callback = nullptr;
napi_create_function(env_, "testCallback", NAPI_AUTO_LENGTH, TestCallback, nullptr, &callback);
ASSERT_NE(callback, nullptr);
int32_t callbackId = jsEnvCallback_->Register(callback, false);
EXPECT_GE(callbackId, 0);
AppExecFwk::Configuration config;
config.AddItem(0, GlobalConfigurationKey::SYSTEM_LANGUAGE, "zh-CN");
jsEnvCallback_->OnConfigurationUpdated(config);
EXPECT_FALSE(jsEnvCallback_->IsEmpty());
TAG_LOGI(AAFwkTag::APPKIT, "JsEnvironmentCallback_OnConfigurationUpdated_001 end");
}
/**
* @tc.name: JsEnvironmentCallback_OnConfigurationUpdated_002
* @tc.desc: Test OnConfigurationUpdated with sync callback
* @tc.type: FUNC
*/
HWTEST_F(JsEnvironmentCallbackTest, JsEnvironmentCallback_OnConfigurationUpdated_002, Function | MediumTest | Level1)
{
TAG_LOGI(AAFwkTag::APPKIT, "JsEnvironmentCallback_OnConfigurationUpdated_002 start");
napi_value callback = nullptr;
napi_create_function(env_, "testCallback", NAPI_AUTO_LENGTH, TestCallback, nullptr, &callback);
ASSERT_NE(callback, nullptr);
int32_t callbackId = jsEnvCallback_->Register(callback, true);
EXPECT_GE(callbackId, 0);
AppExecFwk::Configuration config;
config.AddItem(0, GlobalConfigurationKey::SYSTEM_LANGUAGE, "en-US");
jsEnvCallback_->OnConfigurationUpdated(config);
EXPECT_FALSE(jsEnvCallback_->IsEmpty());
TAG_LOGI(AAFwkTag::APPKIT, "JsEnvironmentCallback_OnConfigurationUpdated_002 end");
}
/**
* @tc.name: JsEnvironmentCallback_OnConfigurationUpdated_003
* @tc.desc: Test OnConfigurationUpdated with both sync and async callbacks
* @tc.type: FUNC
*/
HWTEST_F(JsEnvironmentCallbackTest, JsEnvironmentCallback_OnConfigurationUpdated_003, Function | MediumTest | Level1)
{
TAG_LOGI(AAFwkTag::APPKIT, "JsEnvironmentCallback_OnConfigurationUpdated_003 start");
napi_value callback = nullptr;
napi_create_function(env_, "testCallback", NAPI_AUTO_LENGTH, TestCallback, nullptr, &callback);
ASSERT_NE(callback, nullptr);
int32_t asyncCallbackId = jsEnvCallback_->Register(callback, false);
EXPECT_GE(asyncCallbackId, 0);
int32_t syncCallbackId = jsEnvCallback_->Register(callback, true);
EXPECT_GE(syncCallbackId, 0);
AppExecFwk::Configuration config;
config.AddItem(0, "ohos.application.direction", "1");
jsEnvCallback_->OnConfigurationUpdated(config);
EXPECT_FALSE(jsEnvCallback_->IsEmpty());
TAG_LOGI(AAFwkTag::APPKIT, "JsEnvironmentCallback_OnConfigurationUpdated_003 end");
}
/**
* @tc.name: JsEnvironmentCallback_OnConfigurationUpdated_004
* @tc.desc: Test OnConfigurationUpdated when callback is destroyed (weak_ptr lock fails)
* @tc.type: FUNC
*/
HWTEST_F(JsEnvironmentCallbackTest, JsEnvironmentCallback_OnConfigurationUpdated_004, Function | MediumTest | Level1)
{
TAG_LOGI(AAFwkTag::APPKIT, "JsEnvironmentCallback_OnConfigurationUpdated_004 start");
auto testCallback = std::make_shared<JsEnvironmentCallback>(env_);
ASSERT_NE(testCallback, nullptr);
napi_value callback = nullptr;
napi_create_function(env_, "testCallback", NAPI_AUTO_LENGTH, TestCallback, nullptr, &callback);
ASSERT_NE(callback, nullptr);
int32_t callbackId = testCallback->Register(callback, false);
EXPECT_GE(callbackId, 0);
AppExecFwk::Configuration config;
testCallback->OnConfigurationUpdated(config);
testCallback = nullptr;
TAG_LOGI(AAFwkTag::APPKIT, "JsEnvironmentCallback_OnConfigurationUpdated_004 end");
}