1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "napi_settings_observer.h" 17 18 #include <map> 19 20 #include "napi_settings_log.h" 21 #include "abs_shared_result_set.h" 22 #include "values_bucket.h" 23 #include "uv.h" 24 25 #include "napi_base_context.h" 26 #include "os_account_manager.h" 27 28 29 using namespace OHOS::AppExecFwk; 30 using namespace OHOS::DataShare; 31 using namespace OHOS::AccountSA; 32 33 34 namespace OHOS { 35 namespace Settings { 36 37 std::map<std::string, sptr<SettingsObserver>> g_observerMap; 38 EnvObserver(void * arg)39 void SettingsObserver::EnvObserver(void* arg) 40 { 41 AsyncCallbackInfo* callBackInfo = reinterpret_cast<AsyncCallbackInfo*>(arg); 42 if (callBackInfo == nullptr || callBackInfo->env == nullptr) { 43 return; 44 } 45 callBackInfo->env = nullptr; 46 } 47 OnChangeAsync(uv_loop_s * loop,uv_work_t * work)48 int OnChangeAsync(uv_loop_s* loop, uv_work_t *work) 49 { 50 int ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, 51 [](uv_work_t *work, int status) { 52 AsyncCallbackInfo* cbInfo = reinterpret_cast<AsyncCallbackInfo*>(work->data); 53 if (cbInfo == nullptr) { 54 SETTING_LOG_ERROR("uv_work: cbInfo invalid."); 55 delete work; 56 return; 57 } 58 if (cbInfo->env == nullptr) { 59 delete work; 60 return; 61 } 62 napi_handle_scope scope = nullptr; 63 napi_open_handle_scope(cbInfo->env, &scope); 64 napi_value callback = nullptr; 65 napi_value undefined; 66 napi_get_undefined(cbInfo->env, &undefined); 67 napi_value error = nullptr; 68 napi_create_object(cbInfo->env, &error); 69 int unSupportCode = 802; 70 napi_value errCode = nullptr; 71 napi_create_int32(cbInfo->env, unSupportCode, &errCode); 72 napi_set_named_property(cbInfo->env, error, "code", errCode); 73 napi_value result[PARAM2] = {0}; 74 result[0] = error; 75 result[1] = wrap_bool_to_js(cbInfo->env, false); 76 napi_get_reference_value(cbInfo->env, cbInfo->callbackRef, &callback); 77 napi_value callResult; 78 napi_call_function(cbInfo->env, undefined, callback, PARAM2, result, &callResult); 79 napi_close_handle_scope(cbInfo->env, scope); 80 SETTING_LOG_INFO("%{public}s, uv_work success.", __func__); 81 napi_remove_env_cleanup_hook(cbInfo->env, SettingsObserver::EnvObserver, cbInfo); 82 delete work; 83 }); 84 return ret; 85 } 86 OnChange()87 void SettingsObserver::OnChange() 88 { 89 uv_loop_s* loop = nullptr; 90 napi_get_uv_event_loop(cbInfo->env, &loop); 91 if (loop == nullptr) { 92 SETTING_LOG_ERROR("%{public}s, fail to get uv loop.", __func__); 93 return; 94 } 95 auto work = new (std::nothrow) uv_work_t; 96 if (work == nullptr) { 97 SETTING_LOG_ERROR("%{public}s, fail to get uv work.", __func__); 98 return; 99 } 100 napi_add_env_cleanup_hook(cbInfo->env, SettingsObserver::EnvObserver, cbInfo); 101 work->data = reinterpret_cast<void*>(cbInfo); 102 103 int ret = OnChangeAsync(loop, work); 104 if (ret != 0) { 105 SETTING_LOG_ERROR("%{public}s, uv_queue_work failed.", __func__); 106 if (work != nullptr) { 107 delete work; 108 work = nullptr; 109 } 110 } 111 } 112 GetObserverIdStr()113 std::string GetObserverIdStr() 114 { 115 std::vector<int> tmpId; 116 OHOS::AccountSA::OsAccountManager::QueryActiveOsAccountIds(tmpId); 117 std::string tmpIdStr = "100"; 118 if (tmpId.size() > 0) { 119 tmpIdStr = std::to_string(tmpId[0]); 120 } else { 121 SETTING_LOG_INFO("%{public}s, user id 100.", __func__); 122 } 123 return tmpIdStr; 124 } 125 npai_settings_register_observer(napi_env env,napi_callback_info info)126 napi_value npai_settings_register_observer(napi_env env, napi_callback_info info) 127 { 128 SETTING_LOG_INFO("n_s_r_o"); 129 // Check the number of the arguments 130 size_t argc = ARGS_FOUR; 131 napi_value args[ARGS_FOUR] = {nullptr}; 132 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); 133 if (argc != ARGS_FOUR) { 134 SETTING_LOG_ERROR("%{public}s, wrong number of arguments.", __func__); 135 return wrap_bool_to_js(env, false); 136 } 137 138 // Check the value type of the arguments 139 napi_valuetype valueType; 140 NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valueType)); 141 NAPI_ASSERT(env, valueType == napi_object, "Wrong argument[0] type. Object expected."); 142 NAPI_CALL(env, napi_typeof(env, args[PARAM1], &valueType)); 143 NAPI_ASSERT(env, valueType == napi_string, "Wrong argument[1] type. String expected."); 144 NAPI_CALL(env, napi_typeof(env, args[PARAM2], &valueType)); 145 NAPI_ASSERT(env, valueType == napi_string, "Wrong argument[2] type. String expected."); 146 147 bool stageMode = false; 148 napi_status status = OHOS::AbilityRuntime::IsStageContext(env, args[PARAM0], stageMode); 149 if (status != napi_ok) { 150 SETTING_LOG_ERROR("%{public}s, not stage mode.", __func__); 151 return wrap_bool_to_js(env, false); 152 } 153 AsyncCallbackInfo *callbackInfo = new AsyncCallbackInfo(); 154 155 callbackInfo->env = env; 156 callbackInfo->key = unwrap_string_from_js(env, args[PARAM1]); 157 callbackInfo->tableName = unwrap_string_from_js(env, args[PARAM2]); 158 napi_create_reference(env, args[PARAM3], 1, &(callbackInfo->callbackRef)); 159 160 if (g_observerMap.find(callbackInfo->key) != g_observerMap.end() && 161 g_observerMap[callbackInfo->key] != nullptr) { 162 SETTING_LOG_INFO("%{public}s, already registered.", __func__); 163 delete callbackInfo; 164 return wrap_bool_to_js(env, false); 165 } 166 167 auto dataShareHelper = getDataShareHelper(env, args[PARAM0], stageMode, callbackInfo->tableName); 168 if (dataShareHelper == nullptr) { 169 delete callbackInfo; 170 return wrap_bool_to_js(env, false); 171 } 172 173 std::string strUri = GetStageUriStr(callbackInfo->tableName, GetObserverIdStr(), callbackInfo->key); 174 OHOS::Uri uri(strUri); 175 sptr<SettingsObserver> settingsObserver = sptr<SettingsObserver> 176 (new (std::nothrow)SettingsObserver(callbackInfo)); 177 g_observerMap[callbackInfo->key] = settingsObserver; 178 dataShareHelper->RegisterObserver(uri, settingsObserver); 179 dataShareHelper->Release(); 180 181 return wrap_bool_to_js(env, true); 182 } 183 npai_settings_unregister_observer(napi_env env,napi_callback_info info)184 napi_value npai_settings_unregister_observer(napi_env env, napi_callback_info info) 185 { 186 SETTING_LOG_INFO("n_s_u_o"); 187 // Check the number of the arguments 188 size_t argc = ARGS_THREE; 189 napi_value args[ARGS_THREE] = {nullptr}; 190 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)); 191 if (argc != ARGS_THREE) { 192 SETTING_LOG_ERROR("%{public}s, wrong number of arguments.", __func__); 193 return wrap_bool_to_js(env, false); 194 } 195 // Check the value type of the arguments 196 napi_valuetype valueType; 197 NAPI_CALL(env, napi_typeof(env, args[PARAM0], &valueType)); 198 NAPI_ASSERT(env, valueType == napi_object, "Wrong argument[0] type. Object expected."); 199 NAPI_CALL(env, napi_typeof(env, args[PARAM1], &valueType)); 200 NAPI_ASSERT(env, valueType == napi_string, "Wrong argument[1] type. String expected."); 201 NAPI_CALL(env, napi_typeof(env, args[PARAM2], &valueType)); 202 NAPI_ASSERT(env, valueType == napi_string, "Wrong argument[2] type. String expected."); 203 204 bool stageMode = false; 205 napi_status status = OHOS::AbilityRuntime::IsStageContext(env, args[PARAM0], stageMode); 206 if (status != napi_ok) { 207 SETTING_LOG_ERROR("%{public}s, not stage mode.", __func__); 208 return wrap_bool_to_js(env, false); 209 } 210 211 std::string key = unwrap_string_from_js(env, args[PARAM1]); 212 std::string tableName = unwrap_string_from_js(env, args[PARAM2]); 213 214 if (g_observerMap.find(key) == g_observerMap.end()) { 215 SETTING_LOG_ERROR("%{public}s, null.", __func__); 216 return wrap_bool_to_js(env, false); 217 } 218 219 if (g_observerMap[key] == nullptr) { 220 g_observerMap.erase(key); 221 return wrap_bool_to_js(env, false); 222 } 223 224 auto dataShareHelper = getDataShareHelper(env, args[PARAM0], stageMode, tableName); 225 if (dataShareHelper == nullptr) { 226 SETTING_LOG_ERROR("%{public}s, data share is null.", __func__); 227 return wrap_bool_to_js(env, false); 228 } 229 std::string strUri = GetStageUriStr(tableName, GetObserverIdStr(), key); 230 OHOS::Uri uri(strUri); 231 232 napi_delete_reference(g_observerMap[key]->cbInfo->env, g_observerMap[key]->cbInfo->callbackRef); 233 dataShareHelper->UnregisterObserver(uri, g_observerMap[key]); 234 dataShareHelper->Release(); 235 delete g_observerMap[key]->cbInfo; 236 g_observerMap[key]->cbInfo = nullptr; 237 g_observerMap[key] = nullptr; 238 g_observerMap.erase(key); 239 240 return wrap_bool_to_js(env, true); 241 } 242 } 243 }