• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }