diff --git a/adapter/ohos/capability/BUILD.gn b/adapter/ohos/capability/BUILD.gn index 6dea33c1..0becc878 100644 --- a/adapter/ohos/capability/BUILD.gn +++ b/adapter/ohos/capability/BUILD.gn @@ -26,11 +26,13 @@ template("ace_capability_ohos_source_set") { sources = [ "clipboard/clipboard_impl.cpp", + "distributed/storage/distributed_storage.cpp", "preference/storage_impl.cpp", ] include_dirs = [ "//foundation/distributeddatamgr/appdatamgr/interfaces/innerkits/native_preferences/include/" ] external_deps = [ "ability_base:want", + "distributeddataobject:distributeddataobject_impl", "ipc:ipc_core", "native_appdatamgr:native_preferences", ] diff --git a/adapter/ohos/capability/distributed/storage/distributed_storage.cpp b/adapter/ohos/capability/distributed/storage/distributed_storage.cpp new file mode 100644 index 00000000..d17442c3 --- /dev/null +++ b/adapter/ohos/capability/distributed/storage/distributed_storage.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2022 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 "adapter/ohos/capability/distributed/storage/distributed_storage.h" + +#include "distributed_object.h" +#include "distributed_objectstore.h" +#include "objectstore_errors.h" + +#include "base/log/log.h" +#include "core/common/ace_application_info.h" + +namespace OHOS::Ace { + +class DistributedObjectWatch final : public OHOS::ObjectStore::ObjectWatcher { +public: + DistributedObjectWatch(const std::string& sessionId, OnDataChangeCallback&& onChange) + { + onChange_ = std::move(onChange); + } + + void OnChanged(const std::string& sessionid, const std::vector& changedData) override + { + if (onChange_) { + onChange_(sessionid, changedData); + } + } + +private: + OnDataChangeCallback onChange_; +}; + +class DistributedObjectStatusNotifier final : public OHOS::ObjectStore::StatusNotifier { +public: + explicit DistributedObjectStatusNotifier(ObjectStatusNotifyCallback&& onNotify) + { + onNotify_ = std::move(onNotify); + } + void OnChanged(const std::string& sessionId, const std::string& networkId, const std::string& onlineStatus) override + { + LOGI("DistributedObjectStatusNotifier [%{public}s-%{public}s]", sessionId.c_str(), onlineStatus.c_str()); + if (onNotify_) { + onNotify_(sessionId, onlineStatus); + } + } + +private: + ObjectStatusNotifyCallback onNotify_; +}; + +DistributedObjectPtr::DistributedObjectPtr(const std::string& sessionId, OnDataChangeCallback&& onChange) +{ + std::string bundleName = AceApplicationInfo::GetInstance().GetProcessName(); + if (bundleName.empty()) { + LOGE("DistributedObjectStore bundleName is empty!"); + return; + } + OHOS::ObjectStore::DistributedObjectStore* store = + OHOS::ObjectStore::DistributedObjectStore::GetInstance(bundleName); + if (store == nullptr) { + LOGE("DistributedObjectStore GetInstance failed!"); + return; + } + + static std::once_flag onceFlag; + std::call_once(onceFlag, [store]() { + auto callback = [](const std::string& sessionId, const std::string& onlineStatus) { + DistributedStorage::OnStatusNotify(sessionId, onlineStatus); + }; + store->SetStatusNotifier(std::make_shared(callback)); + }); + + uint32_t ret = store->Get(sessionId, object_); + if (ret != OHOS::ObjectStore::SUCCESS) { + LOGW("DistributedObjectStore get object[%{private}s] failed, try to create", sessionId.c_str()); + object_ = store->CreateObject(sessionId); + if (object_ == nullptr) { + LOGE("DistributedObjectStore CreateObject failed!"); + return; + } + } + + sessionId_ = sessionId; + watcher_ = std::make_shared(sessionId, std::move(onChange)); + ret = store->Watch(object_, watcher_); + if (ret != OHOS::ObjectStore::SUCCESS) { + LOGE("DistributedObjectStore Watch failed!, err=[%{private}u", ret); + } + LOGI("DistributedObjectPtr init success[%{public}s]", sessionId_.c_str()); +} + +DistributedObjectPtr::~DistributedObjectPtr() +{ + if (object_ != nullptr) { + std::string bundleName = AceApplicationInfo::GetInstance().GetProcessName(); + OHOS::ObjectStore::DistributedObjectStore* store = + OHOS::ObjectStore::DistributedObjectStore::GetInstance(bundleName); + if (store == nullptr) { + LOGE("DistributedObjectStore GetInstance failed!"); + return; + } + uint32_t ret = store->UnWatch(object_); + if (ret != OHOS::ObjectStore::SUCCESS) { + LOGE("DistributedObjectStore UnWatch failed!, err=[%{private}u", ret); + } + ret = OHOS::ObjectStore::SUCCESS; + ret = store->DeleteObject(sessionId_); + if (ret != OHOS::ObjectStore::SUCCESS) { + LOGE("DistributedObjectStore DeleteObject failed!, err=[%{private}u", ret); + } + } +} + +OHOS::ObjectStore::DistributedObject* DistributedObjectPtr::GetRawPtr() +{ + return object_; +} + +std::map> DistributedStorage::storageMap_; + +void DistributedStorage::AddStorage(const std::string& sessionId, RefPtr storage) +{ + storageMap_.try_emplace(sessionId, storage); +} + +void DistributedStorage::DeleteStorage(const std::string& sessionId) +{ + storageMap_.erase(sessionId); +} + +void DistributedStorage::OnStatusNotify(const std::string& sessionId, const std::string& status) +{ + auto storage = storageMap_.find(sessionId); + if (storage != storageMap_.end()) { + storage->second->NotifyStatus(status); + } +} + +bool DistributedStorage::Init(std::function&& notifyCallback) +{ + notifyCallback_ = std::move(notifyCallback); + auto onChangeCallback = [weak = WeakClaim(this)]( + const std::string& sessionid, const std::vector& changedData) { + auto storage = weak.Upgrade(); + for (auto& key : changedData) { + storage->OnDataChange(key); + } + }; + objectPtr_ = std::make_unique(sessionId_, std::move(onChangeCallback)); + + return true; +} + +void DistributedStorage::SetString(const std::string& key, const std::string& value) +{ + auto ret = objectPtr_->GetRawPtr()->PutString(key, value); + if (ret != OHOS::ObjectStore::SUCCESS) { + LOGE("Set string failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u", sessionId_.c_str(), + key.c_str(), ret); + } +} + +std::string DistributedStorage::GetString(const std::string& key) +{ + std::string value; + auto ret = objectPtr_->GetRawPtr()->GetString(key, value); + if (ret != OHOS::ObjectStore::SUCCESS) { + LOGE("Get string failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u", sessionId_.c_str(), + key.c_str(), ret); + } + return value; +} + +void DistributedStorage::SetDouble(const std::string& key, const double value) +{ + auto ret = objectPtr_->GetRawPtr()->PutDouble(key, value); + if (ret != OHOS::ObjectStore::SUCCESS) { + LOGE("Set Double failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u", sessionId_.c_str(), + key.c_str(), ret); + } +} + +bool DistributedStorage::GetDouble(const std::string& key, double& value) +{ + auto ret = objectPtr_->GetRawPtr()->GetDouble(key, value); + if (ret != OHOS::ObjectStore::SUCCESS) { + LOGE("Get double failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u", sessionId_.c_str(), + key.c_str(), ret); + return false; + } + return true; +} + +void DistributedStorage::SetBoolean(const std::string& key, const bool value) +{ + auto ret = objectPtr_->GetRawPtr()->PutBoolean(key, value); + if (ret != OHOS::ObjectStore::SUCCESS) { + LOGE("Set Boolean failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u", sessionId_.c_str(), + key.c_str(), ret); + } +} + +bool DistributedStorage::GetBoolean(const std::string& key, bool& value) +{ + auto ret = objectPtr_->GetRawPtr()->GetBoolean(key, value); + if (ret != OHOS::ObjectStore::SUCCESS) { + LOGE("Get Boolean failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u", sessionId_.c_str(), + key.c_str(), ret); + return false; + } + return true; +} + +Storage::DataType DistributedStorage::GetDataType(const std::string& key) +{ + OHOS::ObjectStore::Type type = OHOS::ObjectStore::Type::TYPE_STRING; + auto ret = objectPtr_->GetRawPtr()->GetType(key, type); + + if (ret != OHOS::ObjectStore::SUCCESS) { + LOGE("Get type failed! sessionId=[%{private}s], key=[%{private}s], err=[%{private}u", sessionId_.c_str(), + key.c_str(), ret); + return Storage::DataType::NONE; + } + + Storage::DataType dataType = Storage::DataType::NONE; + switch (type) { + case OHOS::ObjectStore::Type::TYPE_STRING: + dataType = Storage::DataType::STRING; + break; + case OHOS::ObjectStore::Type::TYPE_BOOLEAN: + dataType = Storage::DataType::BOOLEAN; + break; + case OHOS::ObjectStore::Type::TYPE_DOUBLE: + dataType = Storage::DataType::DOUBLE; + break; + default: + break; + } + return dataType; +} + +void DistributedStorage::NotifyStatus(const std::string& status) +{ + if (!taskExecutor_) { + return; + } + LOGI("DistributedStorage::NotifyStatus [%{public}s-%{public}s]", sessionId_.c_str(), status.c_str()); + taskExecutor_->PostTask( + [weak = WeakClaim(this), status] { + auto storage = weak.Upgrade(); + if (storage && storage->notifyCallback_) { + storage->notifyCallback_(status); + } + }, + TaskExecutor::TaskType::JS); +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/adapter/ohos/capability/distributed/storage/distributed_storage.h b/adapter/ohos/capability/distributed/storage/distributed_storage.h new file mode 100644 index 00000000..9b5d2b83 --- /dev/null +++ b/adapter/ohos/capability/distributed/storage/distributed_storage.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef FOUNDATION_ACE_ADAPTER_OHOS_CAPABILITY_DISTRIBUTED_STORAGE_DISTRIBUTED_STORAGE_H +#define FOUNDATION_ACE_ADAPTER_OHOS_CAPABILITY_DISTRIBUTED_STORAGE_DISTRIBUTED_STORAGE_H + +#include + +#include "core/common/storage/storage.h" + +namespace OHOS::ObjectStore { +class DistributedObject; +class ObjectWatcher; +} // namespace OHOS::ObjectStore + +namespace OHOS::Ace { + +using OnDataChangeCallback = std::function&)>; +using ObjectStatusNotifyCallback = std::function; + +class DistributedObjectPtr final { +public: + DistributedObjectPtr(const std::string& sessionId, OnDataChangeCallback&& onChange); + ~DistributedObjectPtr(); + + OHOS::ObjectStore::DistributedObject* GetRawPtr(); + +private: + std::string sessionId_; + OHOS::ObjectStore::DistributedObject* object_ = nullptr; + std::shared_ptr watcher_; +}; + +class DistributedStorage final : public Storage { + DECLARE_ACE_TYPE(DistributedStorage, Storage); + +public: + explicit DistributedStorage(const std::string& sessionId, const RefPtr& taskExecutor) + : Storage(taskExecutor), sessionId_(sessionId) + {} + ~DistributedStorage() override = default; + + bool Init(std::function&& notifier); + + void SetString(const std::string& key, const std::string& value) override; + std::string GetString(const std::string& key) override; + void SetDouble(const std::string& key, const double value) override; + bool GetDouble(const std::string& key, double& value) override; + void SetBoolean(const std::string& key, const bool value) override; + bool GetBoolean(const std::string& key, bool& value) override; + DataType GetDataType(const std::string& key) override; + void Clear() override {} + void Delete(const std::string& key) override {} + void NotifyStatus(const std::string& status); + + static void AddStorage(const std::string& sessionId, RefPtr storage); + static void DeleteStorage(const std::string& sessionId); + static void OnStatusNotify(const std::string& sessionId, const std::string& status); + +private: + std::unique_ptr objectPtr_; + std::string sessionId_; + std::function notifyCallback_; + + static std::map> storageMap_; +}; + +} // namespace OHOS::Ace + +#endif // FOUNDATION_ACE_ADAPTER_OHOS_CAPABILITY_DISTRIBUTED_STORAGE_DISTRIBUTED_STORAGE_H \ No newline at end of file diff --git a/adapter/ohos/capability/distributed/storage/distributed_storage_interface.h b/adapter/ohos/capability/distributed/storage/distributed_storage_interface.h new file mode 100644 index 00000000..626eca58 --- /dev/null +++ b/adapter/ohos/capability/distributed/storage/distributed_storage_interface.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef FOUNDATION_ACE_ADAPTER_OHOS_CAPABILITY_DISTRIBUTED_STORAGE_DISTRIBUTED_STORAGE_INTERFACE_H +#define FOUNDATION_ACE_ADAPTER_OHOS_CAPABILITY_DISTRIBUTED_STORAGE_DISTRIBUTED_STORAGE_INTERFACE_H + +#include "adapter/ohos/capability/distributed/storage/distributed_storage.h" +#include "base/memory/referenced.h" +#include "core/common/storage/storage_interface.h" + +namespace OHOS::Ace { + +class DistributedStorageInterface final : public StorageInterface { +public: + ~DistributedStorageInterface() override = default; + + RefPtr GetStorage(const std::string& sessionId, std::function&& notifier, + const RefPtr& taskExecutor) const override + { + auto storage = Referenced::MakeRefPtr(sessionId, taskExecutor); + if (!storage->Init(std::move(notifier))) { + return nullptr; + } + DistributedStorage::AddStorage(sessionId, storage); + return storage; + } +}; + +} // namespace OHOS::Ace + +#endif // FOUNDATION_ACE_ADAPTER_OHOS_CAPABILITY_DISTRIBUTED_STORAGE_DISTRIBUTED_STORAGE_INTERFACE_H diff --git a/adapter/ohos/capability/preference/storage_impl.cpp b/adapter/ohos/capability/preference/storage_impl.cpp index 19b007ba..85a793ed 100644 --- a/adapter/ohos/capability/preference/storage_impl.cpp +++ b/adapter/ohos/capability/preference/storage_impl.cpp @@ -22,7 +22,7 @@ std::shared_ptr StorageImpl::GetPreference(const return NativePreferences::PreferencesHelper::GetPreferences(fileName, errCode_); } -void StorageImpl::Set(const std::string& key, const std::string& value) +void StorageImpl::SetString(const std::string& key, const std::string& value) { std::shared_ptr pref = GetPreference(fileName_); if (!pref) { @@ -34,7 +34,7 @@ void StorageImpl::Set(const std::string& key, const std::string& value) pref->Flush(); } -std::string StorageImpl::Get(const std::string& key) +std::string StorageImpl::GetString(const std::string& key) { std::shared_ptr pref = GetPreference(fileName_); if (!pref) { diff --git a/adapter/ohos/capability/preference/storage_impl.h b/adapter/ohos/capability/preference/storage_impl.h index 24714e76..a047785a 100644 --- a/adapter/ohos/capability/preference/storage_impl.h +++ b/adapter/ohos/capability/preference/storage_impl.h @@ -37,8 +37,20 @@ public: }; ~StorageImpl() override = default; - void Set(const std::string& key, const std::string& value) override; - std::string Get(const std::string& key) override; + void SetString(const std::string& key, const std::string& value) override; + std::string GetString(const std::string& key) override; + void SetDouble(const std::string& key, const double value) override + {} + bool GetDouble(const std::string& key, double& value) override + { + return false; + } + void SetBoolean(const std::string& key, const bool value) override + {} + bool GetBoolean(const std::string& key, bool& value) override + { + return false; + } void Clear() override; void Delete(const std::string& key) override; diff --git a/adapter/ohos/entrance/capability_registry.cpp b/adapter/ohos/entrance/capability_registry.cpp index 8352641b..d48f43e9 100644 --- a/adapter/ohos/entrance/capability_registry.cpp +++ b/adapter/ohos/entrance/capability_registry.cpp @@ -16,9 +16,10 @@ #include "adapter/ohos/entrance/capability_registry.h" #include "adapter/ohos/capability/clipboard/clipboard_impl.h" +#include "adapter/ohos/capability/distributed/storage/distributed_storage_interface.h" +#include "adapter/ohos/capability/preference/storage_impl.h" #include "core/common/clipboard/clipboard_proxy.h" #include "core/common/storage/storage_proxy.h" -#include "adapter/ohos/capability/preference/storage_impl.h" namespace OHOS::Ace { @@ -26,6 +27,7 @@ void CapabilityRegistry::Register() { ClipboardProxy::GetInstance()->SetDelegate(std::make_unique()); StorageProxy::GetInstance()->SetDelegate(std::make_unique()); + StorageProxy::GetInstance()->SetDistributedDelegate(std::make_unique()); } } // namespace OHOS::Ace diff --git a/frameworks/bridge/declarative_frontend/BUILD.gn b/frameworks/bridge/declarative_frontend/BUILD.gn index ba4d60d0..a7da4790 100644 --- a/frameworks/bridge/declarative_frontend/BUILD.gn +++ b/frameworks/bridge/declarative_frontend/BUILD.gn @@ -145,6 +145,7 @@ template("declarative_js_engine") { "jsview/js_counter.cpp", "jsview/js_data_panel.cpp", "jsview/js_datepicker.cpp", + "jsview/js_distributed.cpp", "jsview/js_divider.cpp", "jsview/js_ellipse.cpp", "jsview/js_environment.cpp", diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register.cpp b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register.cpp index fc7619e8..b6075092 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register.cpp +++ b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_view_register.cpp @@ -49,6 +49,7 @@ #include "frameworks/bridge/declarative_frontend/jsview/js_counter.h" #include "frameworks/bridge/declarative_frontend/jsview/js_data_panel.h" #include "frameworks/bridge/declarative_frontend/jsview/js_datepicker.h" +#include "frameworks/bridge/declarative_frontend/jsview/js_distributed.h" #include "frameworks/bridge/declarative_frontend/jsview/js_divider.h" #include "frameworks/bridge/declarative_frontend/jsview/js_ellipse.h" #include "frameworks/bridge/declarative_frontend/jsview/js_environment.h" @@ -1082,6 +1083,7 @@ void JsRegisterViews(BindingTarget globalObj) JSCustomDialogController::JSBind(globalObj); JSShareData::JSBind(globalObj); JSPersistent::JSBind(globalObj); + JSDistributed::JSBind(globalObj); JSScroller::JSBind(globalObj); JSProfiler::JSBind(globalObj); diff --git a/frameworks/bridge/declarative_frontend/engine/quickjs/qjs_view_register.cpp b/frameworks/bridge/declarative_frontend/engine/quickjs/qjs_view_register.cpp index 716a4957..7f70366d 100644 --- a/frameworks/bridge/declarative_frontend/engine/quickjs/qjs_view_register.cpp +++ b/frameworks/bridge/declarative_frontend/engine/quickjs/qjs_view_register.cpp @@ -56,6 +56,7 @@ #include "frameworks/bridge/declarative_frontend/jsview/js_counter.h" #include "frameworks/bridge/declarative_frontend/jsview/js_data_panel.h" #include "frameworks/bridge/declarative_frontend/jsview/js_datepicker.h" +#include "frameworks/bridge/declarative_frontend/jsview/js_distributed.h" #include "frameworks/bridge/declarative_frontend/jsview/js_divider.h" #include "frameworks/bridge/declarative_frontend/jsview/js_ellipse.h" #include "frameworks/bridge/declarative_frontend/jsview/js_environment.h" @@ -876,6 +877,7 @@ void JsRegisterViews(BindingTarget globalObj) JSBlank::JSBind(globalObj); JSCalendar::JSBind(globalObj); JSPersistent::JSBind(globalObj); + JSDistributed::JSBind(globalObj); JSRadio::JSBind(globalObj); JSCalendarController::JSBind(globalObj); JSRenderingContext::JSBind(globalObj); diff --git a/frameworks/bridge/declarative_frontend/engine/stateMgmt.js b/frameworks/bridge/declarative_frontend/engine/stateMgmt.js index fcf7cf06..4b7a9f42 100644 --- a/frameworks/bridge/declarative_frontend/engine/stateMgmt.js +++ b/frameworks/bridge/declarative_frontend/engine/stateMgmt.js @@ -1991,6 +1991,157 @@ class PersistentStorage { } } PersistentStorage.Instance_ = undefined; + +class DistributedStorage { + constructor(sessionId, statusNotifier) { + this.links_ = new Map(); + this.id_ = SubscriberManager.Get().MakeId(); + SubscriberManager.Get().add(this); + this.aviliable_ = false; + this.storage_ = new DistributedObject(sessionId, this); + this.notifier_ = statusNotifier; + } + keys() { + let result = []; + const it = this.links_.keys(); + let val = it.next(); + while (!val.done) { + result.push(val.value); + val = it.next(); + } + return result; + } + distributeProp(propName, defaultValue) { + if (this.link(propName, defaultValue)) { + console.debug(`DistributedStorage: writing '${propName}' - '${this.links_.get(propName)}' to storage`); + } + } + distributeProps(properties) { + properties.forEach(property => this.link(property.key, property.defaultValue)); + } + link(propName, defaultValue) { + if (defaultValue == null || defaultValue == undefined) { + console.error(`DistributedStorage: linkProp for ${propName} called with 'null' or 'undefined' default value!`); + return false; + } + if (this.links_.get(propName)) { + console.warn(`DistributedStorage: linkProp: ${propName} is already exist`); + return false; + } + let link = AppStorage.GetOrCreate().link(propName, this); + if (link) { + console.debug(`DistributedStorage: linkProp ${propName} in AppStorage, using that`); + this.links_.set(propName, link); + this.setDistributedProp(propName, defaultValue); + } + else { + let returnValue = defaultValue; + if (this.aviliable_) { + let newValue = this.getDistributedProp(propName); + if (newValue == null) { + console.debug(`DistributedStorage: no entry for ${propName}, will initialize with default value`); + this.setDistributedProp(propName, defaultValue); + } + else { + returnValue = newValue; + } + } + link = AppStorage.GetOrCreate().setAndLink(propName, returnValue, this); + this.links_.set(propName, link); + console.debug(`DistributedStorage: created new linkProp prop for ${propName}`); + } + return true; + } + deleteProp(propName) { + let link = this.links_.get(propName); + if (link) { + link.aboutToBeDeleted(); + this.links_.delete(propName); + if (this.aviliable_) { + this.storage_.delete(propName); + } + } + else { + console.warn(`DistributedStorage: '${propName}' is not a distributed property warning.`); + } + } + write(key) { + let link = this.links_.get(key); + if (link) { + console.info(`DistributedStorage: write ${key}-${JSON.stringify(link.get())} `); + this.setDistributedProp(key, link.get()) + } + } + // public required by the interface, use the static method instead! + aboutToBeDeleted() { + console.debug("DistributedStorage: about to be deleted"); + this.links_.forEach((val, key, map) => { + console.debug(`DistributedStorage: removing ${key}`); + val.aboutToBeDeleted(); + }); + this.links_.clear(); + SubscriberManager.Get().delete(this.id()); + } + id__() { + return this.id_; + } + propertyHasChanged(info) { + console.info(`DistributedStorage: property changed info:${JSON.stringify(info)} `); + this.write(info); + } + onDataOnChange(propName) { + let link = this.links_.get(propName); + let newValue = this.getDistributedProp(propName); + if (link && newValue != null) { + console.info(`DistributedStorage: dataOnChange[${propName}-${newValue}]`); + link.set(newValue) + } + } + onConnected(status) { + console.info(`DistributedStorage onConnected: status = ${status}`); + if (!this.aviliable_) { + this.syncProp(); + this.aviliable_ = true; + } + if (this.notifier_ != null) { + this.notifier_(status); + } + } + syncProp() { + this.links_.forEach((val, key) => { + let newValue = this.getDistributedProp(key); + if (newValue == null) { + this.setDistributedProp(key, val.get()); + } else { + val.set(newValue); + } + }); + } + setDistributedProp(key, value) { + if (!this.aviliable_) { + console.warn(`DistributedStorage is not aviliable`); + return; + } + if (typeof value == 'object') { + this.storage_.set(key, JSON.stringify(value)); + return; + } + this.storage_.set(key, value); + } + getDistributedProp(key) { + let value = this.storage_.get(key); + if (typeof value == 'string') { + try { + let returnValue = JSON.parse(value); + return returnValue; + } + finally { + return value; + } + } + return value; + } +} /* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/frameworks/bridge/declarative_frontend/engine/v8/v8_view_register.cpp b/frameworks/bridge/declarative_frontend/engine/v8/v8_view_register.cpp index d55992e7..0f5bde1e 100644 --- a/frameworks/bridge/declarative_frontend/engine/v8/v8_view_register.cpp +++ b/frameworks/bridge/declarative_frontend/engine/v8/v8_view_register.cpp @@ -38,6 +38,7 @@ #include "frameworks/bridge/declarative_frontend/jsview/js_checkbox.h" #include "frameworks/bridge/declarative_frontend/jsview/js_checkboxgroup.h" #include "frameworks/bridge/declarative_frontend/jsview/js_clipboard.h" +#include "frameworks/bridge/declarative_frontend/jsview/js_distributed.h" #include "frameworks/bridge/declarative_frontend/jsview/js_hyperlink.h" #include "frameworks/bridge/declarative_frontend/jsview/js_offscreen_rendering_context.h" #include "frameworks/bridge/declarative_frontend/jsview/js_path2d.h" @@ -771,6 +772,7 @@ void JsRegisterViews(BindingTarget globalObj) JSPanHandler::JSBind(globalObj); JsDragFunction::JSBind(globalObj); JSPersistent::JSBind(globalObj); + JSDistributed::JSBind(globalObj); JSClipboard::JSBind(globalObj); JSProfiler::JSBind(globalObj); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_distributed.cpp b/frameworks/bridge/declarative_frontend/jsview/js_distributed.cpp new file mode 100644 index 00000000..69c20c26 --- /dev/null +++ b/frameworks/bridge/declarative_frontend/jsview/js_distributed.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2022 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 "bridge/declarative_frontend/jsview/js_distributed.h" + +#include "base/memory/referenced.h" +#include "bridge/declarative_frontend/jsview/js_view_common_def.h" +#include "core/common/ace_engine.h" +#include "core/common/container.h" +#include "core/common/container_scope.h" +#include "frameworks/bridge/declarative_frontend/engine/js_ref_ptr.h" +#include "frameworks/bridge/declarative_frontend/jsview/js_container_base.h" + +namespace OHOS::Ace::Framework { + +void JSDistributed::JSBind(BindingTarget globalObj) +{ + JSClass::Declare("DistributedObject"); + JSClass::CustomMethod("set", &JSDistributed::Set); + JSClass::CustomMethod("get", &JSDistributed::Get); + JSClass::CustomMethod("delete", &JSDistributed::Delete); + JSClass::Bind(globalObj, JSDistributed::ConstructorCallback, JSDistributed::DestructorCallback); +} + +void JSDistributed::ConstructorCallback(const JSCallbackInfo& args) +{ + std::string sessionId; + if (args.Length() > 0 && args[0]->IsString() && args[1]->IsObject()) { + sessionId = args[0]->ToString(); + LOGE("sessionId %{public}s", sessionId.c_str()); + auto distributed = Referenced::MakeRefPtr(sessionId); + distributed->IncRefCount(); + distributed->Init(JSRef::Cast(args[1]), sessionId); + args.SetReturnValue(Referenced::RawPtr(distributed)); + } +} + +void JSDistributed::DestructorCallback(JSDistributed* distributed) +{ + if (distributed != nullptr) { + distributed->DecRefCount(); + } +} + +void JSDistributed::Set(const JSCallbackInfo& args) +{ +#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) + LOGW("[Engine Log] Unable to use the DistributedStorage in the Previewer. Perform this operation on the " + "emulator or a real device instead."); + return; +#endif + + if (args.Length() < 2) { + LOGW("fail to set distributed data"); + return; + } + if (!stroage_) { + LOGW("distributed stroage is null, faid to set distributed data"); + return; + } + std::string key = args[0]->ToString(); + if (args[1]->IsBoolean()) { + auto val = args[1]->ToBoolean(); + LOGW("JSDistributed::Set [%{public}s--%{public}d]", key.c_str(), val); + stroage_->SetBoolean(key, val); + return; + } + + if (args[1]->IsNumber()) { + auto val = args[1]->ToNumber(); + LOGW("JSDistributed::Set [%{public}s--%{public}lf]", key.c_str(), val); + stroage_->SetDouble(key, val); + return; + } + + if (args[1]->IsString()) { + auto val = args[1]->ToString(); + LOGW("JSDistributed::Set [%{public}s--%{public}s]", key.c_str(), val.c_str()); + stroage_->SetString(key, val); + return; + } + LOGW("JSDistributed::Set type not support [%{public}s]", key.c_str()); +} + +void JSDistributed::Get(const JSCallbackInfo& args) +{ +#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) + LOGW("[Engine Log] Unable to use the DistributedStorage in the Previewer. Perform this operation on the " + "emulator or a real device instead."); + return; +#endif + if (args.Length() < 1) { + LOGW("fail to Get distributed data"); + return; + } + std::string key = args[0]->ToString(); + LOGW("JSDistributed::Get [%{public}s]", key.c_str()); + + if (!stroage_) { + LOGW("distributed stroage is null, faid to set distributed data"); + return; + } + + auto dataType = stroage_->GetDataType(key); + JSVal returnValue = JSVal(); + + switch (dataType) { + case Storage::DataType::STRING: { + auto value = stroage_->GetString(key); + if (!value.empty()) { + returnValue = JSVal(ToJSValue(value)); + LOGE("Get distributed data success, key = [%{public}s] value = [%{public}s]", key.c_str(), + value.c_str()); + } + break; + } + case Storage::DataType::DOUBLE: { + double value = 0.0; + if (stroage_->GetDouble(key, value)) { + returnValue = JSVal(ToJSValue(value)); + LOGE("Get distributed data success, key = [%{public}s] value = [%{public}lf]", key.c_str(), value); + } + break; + } + case Storage::DataType::BOOLEAN: { + bool value = false; + if (stroage_->GetBoolean(key, value)) { + returnValue = JSVal(ToJSValue(value)); + LOGE("Get distributed data success, key = [%{public}s] value = [%{public}d]", key.c_str(), value); + } + break; + } + default: + break; + } + if (returnValue.IsEmpty()) { + LOGE("fail to Get distributed data, key = [%{public}s]", key.c_str()); + return; + } + auto returnPtr = JSRef::Make(returnValue); + args.SetReturnValue(returnPtr); +} + +void JSDistributed::Delete(const JSCallbackInfo& args) +{ +#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) + LOGW("[Engine Log] Unable to use the DistributedStorage in the Previewer. Perform this operation on the " + "emulator or a real device instead."); + return; +#endif + if (args.Length() < 1) { + LOGW("fail to Delete distributed data"); + return; + } + std::string key = args[0]->ToString(); + stroage_->Delete(key); +} + +void JSDistributed::Init(const JSRef& object, const std::string& sessionId) +{ + JSRef jsVal = object->GetProperty("onDataOnChange"); + if (!jsVal->IsFunction()) { + LOGE("JSDistributed, get func onDataOnChange failed."); + return; + } + onDataOnChange_ = JSRef::Cast(jsVal); + + jsVal = object->GetProperty("onConnected"); + if (!jsVal->IsFunction()) { + LOGE("JSDistributed, get func onConnected failed."); + return; + } + onConnected_ = JSRef::Cast(jsVal); + + object_ = object; + auto instanceId = ContainerScope::CurrentId(); + auto notifier = [weak = WeakClaim(this), instanceId](const std::string& onlineStatus) { + ContainerScope scope(instanceId); + auto distributed = weak.Upgrade(); + distributed->OnStatusNotify(onlineStatus); + }; + + auto container = Container::Current(); + if (!container) { + LOGW("container is null"); + return; + } + auto executor = container->GetTaskExecutor(); + + stroage_ = StorageProxy::GetInstance()->GetStorage(sessionId, notifier, executor); + + auto onChangeCallback = [weak = WeakClaim(this), weakExecutor = WeakPtr(executor), instanceId]( + const std::string& key) { + auto taskExecutor_ = weakExecutor.Upgrade(); + if (!taskExecutor_) { + return; + } + taskExecutor_->PostTask( + [weak, key, instanceId] { + ContainerScope scope(instanceId); + auto distributed = weak.Upgrade(); + if (distributed) { + distributed->OnDataOnChanged(key); + } + }, + TaskExecutor::TaskType::JS); + }; + + stroage_->SetDataOnChangeCallback(std::move(onChangeCallback)); +} + +void JSDistributed::OnDataOnChanged(const std::string& key) +{ + LOGI("distributed date on change key = [%{public}s]", key.c_str()); + + auto params = ConvertToJSValues(key); + onDataOnChange_->Call(object_, params.size(), params.data()); +} + +void JSDistributed::OnStatusNotify(const std::string& onlineStatus) +{ + LOGI("distributed OnStatusNotify = [%{public}s]", onlineStatus.c_str()); + auto params = ConvertToJSValues(onlineStatus); + onConnected_->Call(object_, params.size(), params.data()); +} + +} // namespace OHOS::Ace::Framework \ No newline at end of file diff --git a/frameworks/bridge/declarative_frontend/jsview/js_distributed.h b/frameworks/bridge/declarative_frontend/jsview/js_distributed.h new file mode 100644 index 00000000..e913777d --- /dev/null +++ b/frameworks/bridge/declarative_frontend/jsview/js_distributed.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_DISTRIBUTED_H +#define FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_DISTRIBUTED_H + +#include "base/memory/referenced.h" +#include "bridge/declarative_frontend/engine/bindings.h" +#include "core/common/storage/storage_proxy.h" +#include "frameworks/bridge/declarative_frontend/engine/js_types.h" + +namespace OHOS::Ace::Framework { + +class JSDistributed final : public Referenced { +public: + JSDistributed(const std::string& sessionId) : sessionId_(sessionId) {} + + void Set(const JSCallbackInfo& args); + void Get(const JSCallbackInfo& args); + void Delete(const JSCallbackInfo& args); + + static void ConstructorCallback(const JSCallbackInfo& args); + static void DestructorCallback(JSDistributed* obj); + + static void JSBind(BindingTarget globalObj); + + void Init(const JSRef& object, const std::string& sessionId); + + void OnDataOnChanged(const std::string& key); + + void OnStatusNotify(const std::string& onlineStatus); + +private: + std::string sessionId_; + + JSRef onDataOnChange_; + JSRef onConnected_; + JSRef object_; + RefPtr stroage_; +}; + +} // namespace OHOS::Ace::Framework +#endif // FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_DISTRIBUTED_H \ No newline at end of file diff --git a/frameworks/bridge/declarative_frontend/jsview/js_persistent.cpp b/frameworks/bridge/declarative_frontend/jsview/js_persistent.cpp index 65af613e..33683021 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_persistent.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_persistent.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 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 @@ -75,7 +75,7 @@ void JSPersistent::Set(const JSCallbackInfo& args) if(!StorageProxy::GetInstance()->GetStorage(executor)) { return; } - StorageProxy::GetInstance()->GetStorage(executor)->Set(key, value); + StorageProxy::GetInstance()->GetStorage(executor)->SetString(key, value); LOGD("cross window notify, containerId=%{private}d", container->GetInstanceId()); AceEngine::Get().NotifyContainers( [currInstanceId = container->GetInstanceId(), key, value](const RefPtr& container) { @@ -103,7 +103,7 @@ void JSPersistent::Get(const JSCallbackInfo& args) return; } auto executor = container->GetTaskExecutor(); - std::string value = StorageProxy::GetInstance()->GetStorage(executor)->Get(key); + std::string value = StorageProxy::GetInstance()->GetStorage(executor)->GetString(key); auto returnValue = JSVal(ToJSValue(value)); auto returnPtr = JSRef::Make(returnValue); args.SetReturnValue(returnPtr); diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/distributed_storage.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/distributed_storage.ts new file mode 100644 index 00000000..dc444918 --- /dev/null +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/distributed_storage.ts @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2022 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. + */ + +class DistributedStorage implements IMultiPropertiesChangeSubscriber { + private storage_: IStorage; + + private id_: number; + private links_: Map>; + private aviliable_: boolean; + private notifier_: (status: string) => void; + + public constructor(sessionId: string, notifier: (status: string) => void) { + this.links_ = new Map>(); + this.id_ = SubscriberManager.Get().MakeId(); + SubscriberManager.Get().add(this); + this.aviliable_ = false; + this.notifier_ = notifier; + } + + public keys(): Array { + let result = []; + const it = this.links_.keys(); + let val = it.next(); + + while (!val.done) { + result.push(val.value); + val = it.next(); + } + + return result; + } + + + public distributeProp(propName: string, defaultValue: T): void { + if (this.link(propName, defaultValue)) { + console.debug(`DistributedStorage: writing '${propName}' - '${this.links_.get(propName)}' to storage`); + } + } + + public distributeProps(properties: { + key: string, + defaultValue: any + }[]): void { + properties.forEach(property => this.link(property.key, property.defaultValue)); + } + + public link(propName: string, defaultValue: T): boolean { + if (defaultValue == null || defaultValue == undefined) { + console.error(`DistributedStorage: linkProp for ${propName} called with 'null' or 'undefined' default value!`); + return false; + } + if (this.links_.get(propName)) { + console.warn(`DistributedStorage: linkProp: ${propName} is already exist`); + return false; + } + let link = AppStorage.GetOrCreate().link(propName, this); + if (link) { + console.debug(`DistributedStorage: linkProp ${propName} in AppStorage, using that`); + this.links_.set(propName, link); + this.setDistributedProp(propName, defaultValue); + } + else { + let returnValue = defaultValue; + if (this.aviliable_) { + let newValue = this.getDistributedProp(propName); + if (newValue == null) { + console.debug(`DistributedStorage: no entry for ${propName}, will initialize with default value`); + this.setDistributedProp(propName, defaultValue); + } + else { + returnValue = newValue; + } + } + link = AppStorage.GetOrCreate().setAndLink(propName, returnValue, this); + this.links_.set(propName, link); + console.debug(`DistributedStorage: created new linkProp prop for ${propName}`); + } + return true; + } + + public deleteProp(propName: string): void { + let link = this.links_.get(propName); + if (link) { + link.aboutToBeDeleted(); + this.links_.delete(propName); + if (this.aviliable_) { + this.storage_.delete(propName); + } + } else { + console.warn(`DistributedStorage: '${propName}' is not a distributed property warning.`); + } + } + + private write(key: string): void { + let link = this.links_.get(key); + if (link) { + this.setDistributedProp(key, link.get()); + } + } + + + // public required by the interface, use the static method instead! + public aboutToBeDeleted(): void { + console.debug("DistributedStorage: about to be deleted"); + this.links_.forEach((val, key, map) => { + console.debug(`DistributedStorage: removing ${key}`); + val.aboutToBeDeleted(); + }); + + this.links_.clear(); + SubscriberManager.Get().delete(this.id()); + } + + public id__(): number { + return this.id_; + } + + public propertyHasChanged(info?: PropertyInfo): void { + console.debug("DistributedStorage: property changed"); + this.write(info); + } + + public onDataOnChange(propName: string): void { + let link = this.links_.get(propName); + let newValue = this.getDistributedProp(propName); + if (link && newValue != null) { + console.info(`DistributedStorage: dataOnChange[${propName}-${newValue}]`); + link.set(newValue) + } + } + + public onConnected(status): void { + console.info(`DistributedStorage onConnected: status = ${status}`); + if (!this.aviliable_) { + this.syncProp(); + this.aviliable_ = true; + } + if (this.notifier_ != null) { + this.notifier_(status); + } + } + + private syncProp(): void { + this.links_.forEach((val, key) => { + let newValue = this.getDistributedProp(key); + if (newValue == null) { + this.setDistributedProp(key, val.get()); + } else { + val.set(newValue); + } + }); + } + + private setDistributedProp(key, value): void { + if (!this.aviliable_) { + console.warn(`DistributedStorage is not aviliable`); + return; + } + console.error(`DistributedStorage value is object ${key}-${JSON.stringify(value)}`); + if (typeof value == 'object') { + this.storage_.set(key, JSON.stringify(value)); + return; + } + this.storage_.set(key, value); + } + + private getDistributedProp(key): any { + let value = this.storage_.get(key); + if (typeof value == 'string') { + try { + let returnValue = JSON.parse(value); + return returnValue; + } + finally { + return value; + } + } + return value; + } +}; diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.json b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.json index 914fcdc1..de693dbb 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.json +++ b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.json @@ -22,6 +22,7 @@ "src/lib/view_native.d.ts", "src/lib/view.ts", "src/lib/persistent_storage.ts", + "src/lib/distributed_storage.ts", "src/lib/environment.ts", "src/lib/i_environment_backend.ts", "src/index.ts", diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.release.json b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.release.json index 589ab1d5..70d9de86 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.release.json +++ b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.release.json @@ -22,6 +22,7 @@ "src/lib/view_native.d.ts", "src/lib/view.ts", "src/lib/persistent_storage.ts", + "src/lib/distributed_storage.ts", "src/lib/environment.ts", "src/lib/i_environment_backend.ts", "src/index.ts", diff --git a/frameworks/core/common/storage/storage.h b/frameworks/core/common/storage/storage.h index a1add01f..c56d080b 100644 --- a/frameworks/core/common/storage/storage.h +++ b/frameworks/core/common/storage/storage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 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 @@ -25,16 +25,49 @@ class Storage : public AceType { DECLARE_ACE_TYPE(Storage, AceType); public: + enum class DataType : uint32_t { + NONE = 0, + STRING, + DOUBLE, + BOOLEAN, + }; + + using DataOnChange = std::function; + ~Storage() override = default; - virtual void Set(const std::string& key, const std::string& value) = 0; - virtual std::string Get(const std::string& key) = 0; + virtual void SetString(const std::string& key, const std::string& value) = 0; + virtual std::string GetString(const std::string& key) = 0; + virtual void SetDouble(const std::string& key, const double value) = 0; + virtual bool GetDouble(const std::string& key, double& value) = 0; + virtual void SetBoolean(const std::string& key, const bool value) = 0; + virtual bool GetBoolean(const std::string& key, bool& value) = 0; + + virtual DataType GetDataType(const std::string& key) + { + return DataType::NONE; + } + virtual void Clear() = 0; virtual void Delete(const std::string& key) = 0; + void SetDataOnChangeCallback(DataOnChange&& dataOnChange) + { + dataOnChange_ = std::move(dataOnChange); + } + + void OnDataChange(const std::string& key) + { + if (dataOnChange_) { + dataOnChange_(key); + } + } + protected: explicit Storage(const RefPtr& taskExecutor) : taskExecutor_(taskExecutor) {} + Storage() = default; RefPtr taskExecutor_; + DataOnChange dataOnChange_; }; } // namespace OHOS::Ace diff --git a/frameworks/core/common/storage/storage_interface.h b/frameworks/core/common/storage/storage_interface.h index a6007b61..ae9f0b97 100644 --- a/frameworks/core/common/storage/storage_interface.h +++ b/frameworks/core/common/storage/storage_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 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 @@ -26,7 +26,16 @@ class StorageInterface { public: virtual ~StorageInterface() = default; - virtual RefPtr GetStorage(const RefPtr& taskExecutor) const = 0; + virtual RefPtr GetStorage(const RefPtr& taskExecutor) const + { + return nullptr; + } + + virtual RefPtr GetStorage(const std::string& sessionId, std::function&& notifier, + const RefPtr& taskExecutor) const + { + return nullptr; + } }; } // namespace OHOS::Ace diff --git a/frameworks/core/common/storage/storage_proxy.cpp b/frameworks/core/common/storage/storage_proxy.cpp index 993c4d70..7bf0aa17 100644 --- a/frameworks/core/common/storage/storage_proxy.cpp +++ b/frameworks/core/common/storage/storage_proxy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 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 @@ -32,6 +32,11 @@ void StorageProxy::SetDelegate(std::unique_ptr&& delegate) delegate_ = std::move(delegate); } +void StorageProxy::SetDistributedDelegate(std::unique_ptr&& delegate) +{ + distributedDelegate_ = std::move(delegate); +} + RefPtr StorageProxy::GetStorage(const RefPtr& taskExecutor) const { if (!delegate_) { @@ -40,4 +45,13 @@ RefPtr StorageProxy::GetStorage(const RefPtr& taskExecuto return delegate_->GetStorage(taskExecutor); } +RefPtr StorageProxy::GetStorage(const std::string& sessionId, + std::function&& notifier, const RefPtr& taskExecutor) const +{ + if (!distributedDelegate_) { + return nullptr; + } + return distributedDelegate_->GetStorage(sessionId, std::move(notifier), taskExecutor); +} + } // namespace OHOS::Ace diff --git a/frameworks/core/common/storage/storage_proxy.h b/frameworks/core/common/storage/storage_proxy.h index 8e6fcb86..bcc80476 100644 --- a/frameworks/core/common/storage/storage_proxy.h +++ b/frameworks/core/common/storage/storage_proxy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 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 @@ -25,12 +25,16 @@ class ACE_EXPORT StorageProxy : public StorageInterface { public: ACE_EXPORT static StorageProxy* GetInstance(); void SetDelegate(std::unique_ptr&& delegate); + void SetDistributedDelegate(std::unique_ptr&& delegate); RefPtr GetStorage(const RefPtr& taskExecutor) const override; + RefPtr GetStorage(const std::string& sessionId, std::function&& notifier, + const RefPtr& taskExecutor) const override; StorageProxy() = default; ~StorageProxy() = default; private: std::unique_ptr delegate_; + std::unique_ptr distributedDelegate_; static StorageProxy* inst_; };