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