1 /*
2 * Copyright (c) 2022 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 "bridge/declarative_frontend/jsview/js_distributed.h"
17
18 #include "base/memory/referenced.h"
19 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
20 #include "core/common/ace_engine.h"
21 #include "core/common/container.h"
22 #include "core/common/container_scope.h"
23 #include "frameworks/bridge/declarative_frontend/engine/js_ref_ptr.h"
24 #include "frameworks/bridge/declarative_frontend/jsview/js_container_base.h"
25
26 namespace OHOS::Ace::Framework {
27
JSBind(BindingTarget globalObj)28 void JSDistributed::JSBind(BindingTarget globalObj)
29 {
30 JSClass<JSDistributed>::Declare("DistributedObject");
31 JSClass<JSDistributed>::CustomMethod("set", &JSDistributed::Set);
32 JSClass<JSDistributed>::CustomMethod("get", &JSDistributed::Get);
33 JSClass<JSDistributed>::CustomMethod("delete", &JSDistributed::Delete);
34 JSClass<JSDistributed>::Bind(globalObj, JSDistributed::ConstructorCallback, JSDistributed::DestructorCallback);
35 }
36
ConstructorCallback(const JSCallbackInfo & args)37 void JSDistributed::ConstructorCallback(const JSCallbackInfo& args)
38 {
39 std::string sessionId;
40 if (args.Length() > 1 && args[0]->IsString() && args[1]->IsObject()) {
41 sessionId = args[0]->ToString();
42 LOGI("sessionId %{public}s", sessionId.c_str());
43 auto distributed = Referenced::MakeRefPtr<JSDistributed>(sessionId);
44 distributed->IncRefCount();
45 distributed->Init(JSRef<JSObject>::Cast(args[1]), sessionId);
46 args.SetReturnValue(Referenced::RawPtr(distributed));
47 }
48 }
49
DestructorCallback(JSDistributed * distributed)50 void JSDistributed::DestructorCallback(JSDistributed* distributed)
51 {
52 if (distributed != nullptr) {
53 distributed->DecRefCount();
54 }
55 }
56
Set(const JSCallbackInfo & args)57 void JSDistributed::Set(const JSCallbackInfo& args)
58 {
59 #if defined(PREVIEW)
60 LOGW("[Engine Log] Unable to use the DistributedStorage in the Previewer. Perform this operation on the "
61 "emulator or a real device instead.");
62 return;
63 #endif
64
65 if (args.Length() < 2) {
66 LOGW("fail to set distributed data");
67 return;
68 }
69 if (!storage_) {
70 LOGW("distributed storage is null, failed to set distributed data");
71 return;
72 }
73 std::string key = args[0]->ToString();
74 if (args[1]->IsBoolean()) {
75 auto val = args[1]->ToBoolean();
76 LOGW("JSDistributed::Set [%{public}s--%{public}d]", key.c_str(), val);
77 storage_->SetBoolean(key, val);
78 return;
79 }
80
81 if (args[1]->IsNumber()) {
82 auto val = args[1]->ToNumber<double>();
83 LOGW("JSDistributed::Set [%{public}s--%{public}lf]", key.c_str(), val);
84 storage_->SetDouble(key, val);
85 return;
86 }
87
88 if (args[1]->IsString()) {
89 auto val = args[1]->ToString();
90 LOGW("JSDistributed::Set [%{public}s--%{public}s]", key.c_str(), val.c_str());
91 storage_->SetString(key, val);
92 return;
93 }
94 LOGW("JSDistributed::Set type not support [%{public}s]", key.c_str());
95 }
96
Get(const JSCallbackInfo & args)97 void JSDistributed::Get(const JSCallbackInfo& args)
98 {
99 #if defined(PREVIEW)
100 LOGW("[Engine Log] Unable to use the DistributedStorage in the Previewer. Perform this operation on the "
101 "emulator or a real device instead.");
102 return;
103 #endif
104 if (args.Length() < 1) {
105 LOGW("fail to Get distributed data");
106 return;
107 }
108 std::string key = args[0]->ToString();
109 LOGW("JSDistributed::Get [%{public}s]", key.c_str());
110
111 if (!storage_) {
112 LOGW("distributed storage is null, failed to set distributed data");
113 return;
114 }
115
116 auto dataType = storage_->GetDataType(key);
117 JSVal returnValue = JSVal();
118
119 switch (dataType) {
120 case Storage::DataType::STRING: {
121 auto value = storage_->GetString(key);
122 if (!value.empty()) {
123 returnValue = JSVal(ToJSValue(value));
124 LOGE("Get distributed data success, key = [%{public}s] value = [%{public}s]", key.c_str(),
125 value.c_str());
126 }
127 break;
128 }
129 case Storage::DataType::DOUBLE: {
130 double value = 0.0;
131 if (storage_->GetDouble(key, value)) {
132 returnValue = JSVal(ToJSValue(value));
133 LOGE("Get distributed data success, key = [%{public}s] value = [%{public}lf]", key.c_str(), value);
134 }
135 break;
136 }
137 case Storage::DataType::BOOLEAN: {
138 bool value = false;
139 if (storage_->GetBoolean(key, value)) {
140 returnValue = JSVal(ToJSValue(value));
141 LOGE("Get distributed data success, key = [%{public}s] value = [%{public}d]", key.c_str(), value);
142 }
143 break;
144 }
145 default:
146 break;
147 }
148 if (returnValue.IsEmpty()) {
149 LOGE("fail to Get distributed data, key = [%{public}s]", key.c_str());
150 return;
151 }
152 auto returnPtr = JSRef<JSVal>::Make(returnValue);
153 args.SetReturnValue(returnPtr);
154 }
155
Delete(const JSCallbackInfo & args)156 void JSDistributed::Delete(const JSCallbackInfo& args)
157 {
158 #if defined(PREVIEW)
159 LOGW("[Engine Log] Unable to use the DistributedStorage in the Previewer. Perform this operation on the "
160 "emulator or a real device instead.");
161 return;
162 #endif
163 if (args.Length() < 1) {
164 LOGW("fail to Delete distributed data");
165 return;
166 }
167 std::string key = args[0]->ToString();
168 storage_->Delete(key);
169 }
170
Init(const JSRef<JSObject> & object,const std::string & sessionId)171 void JSDistributed::Init(const JSRef<JSObject>& object, const std::string& sessionId)
172 {
173 JSRef<JSVal> jsVal = object->GetProperty("onDataOnChange");
174 if (!jsVal->IsFunction()) {
175 LOGE("JSDistributed, get func onDataOnChange failed.");
176 return;
177 }
178 onDataOnChange_ = JSRef<JSFunc>::Cast(jsVal);
179
180 jsVal = object->GetProperty("onConnected");
181 if (!jsVal->IsFunction()) {
182 LOGE("JSDistributed, get func onConnected failed.");
183 return;
184 }
185 onConnected_ = JSRef<JSFunc>::Cast(jsVal);
186
187 object_ = object;
188 auto instanceId = ContainerScope::CurrentId();
189 auto notifier = [weak = WeakClaim(this), instanceId](const std::string& onlineStatus) {
190 ContainerScope scope(instanceId);
191 auto distributed = weak.Upgrade();
192 distributed->OnStatusNotify(onlineStatus);
193 };
194
195 auto container = Container::Current();
196 if (!container) {
197 LOGW("container is null");
198 return;
199 }
200 auto executor = container->GetTaskExecutor();
201
202 storage_ = StorageProxy::GetInstance()->GetStorage(sessionId, notifier, executor);
203
204 auto onChangeCallback = [weak = WeakClaim(this), weakExecutor = WeakPtr<TaskExecutor>(executor), instanceId](
205 const std::string& key) {
206 auto taskExecutor_ = weakExecutor.Upgrade();
207 if (!taskExecutor_) {
208 return;
209 }
210 taskExecutor_->PostTask(
211 [weak, key, instanceId] {
212 ContainerScope scope(instanceId);
213 auto distributed = weak.Upgrade();
214 if (distributed) {
215 distributed->OnDataOnChanged(key);
216 }
217 },
218 TaskExecutor::TaskType::JS);
219 };
220
221 storage_->SetDataOnChangeCallback(std::move(onChangeCallback));
222 }
223
OnDataOnChanged(const std::string & key)224 void JSDistributed::OnDataOnChanged(const std::string& key)
225 {
226 LOGI("distributed date on change key = [%{public}s]", key.c_str());
227
228 auto params = ConvertToJSValues(key);
229 onDataOnChange_->Call(object_, params.size(), params.data());
230 }
231
OnStatusNotify(const std::string & onlineStatus)232 void JSDistributed::OnStatusNotify(const std::string& onlineStatus)
233 {
234 LOGI("distributed OnStatusNotify = [%{public}s]", onlineStatus.c_str());
235 auto params = ConvertToJSValues(onlineStatus);
236 onConnected_->Call(object_, params.size(), params.data());
237 }
238
239 } // namespace OHOS::Ace::Framework