From 6c5de30657f14c5eff74672f60ad4c25f0e295a9 Mon Sep 17 00:00:00 2001 From: hunili Date: Tue, 2 Sep 2025 15:27:31 +0800 Subject: [PATCH] =?UTF-8?q?[Bug]:=20=E4=BA=91=E7=9B=98=5F=20dfs=20https://?= =?UTF-8?q?gitee.com/openharmony/filemanagement=5Fuser=5Ffile=5Fservice/is?= =?UTF-8?q?sues/ICRWI6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hunili --- bundle.json | 4 +- interfaces/kits/js/clouddiskmanager/BUILD.gn | 56 +++ .../include/comm_root_info.h | 30 ++ .../include/sync_folder_access_n_exporter.h | 37 ++ .../include/sync_folder_manager_n_exporter.h | 43 ++ .../src/comm_root_info.cpp | 95 ++++ .../src/sync_folder_access_n_exporter.cpp | 171 +++++++ .../src/sync_folder_manager_n_exporter.cpp | 465 ++++++++++++++++++ .../kits/js/clouddiskmanager/module.cpp | 62 +++ utils/log/include/dfs_error.h | 17 + 10 files changed, 979 insertions(+), 1 deletion(-) create mode 100644 interfaces/kits/js/clouddiskmanager/BUILD.gn create mode 100644 interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/comm_root_info.h create mode 100644 interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/sync_folder_access_n_exporter.h create mode 100644 interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/sync_folder_manager_n_exporter.h create mode 100644 interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/comm_root_info.cpp create mode 100644 interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/sync_folder_access_n_exporter.cpp create mode 100644 interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/sync_folder_manager_n_exporter.cpp create mode 100644 interfaces/kits/js/clouddiskmanager/module.cpp diff --git a/bundle.json b/bundle.json index 5460115ae..3c6c4fc9e 100644 --- a/bundle.json +++ b/bundle.json @@ -72,7 +72,8 @@ "os_account", "power_manager", "libfuse", - "zlib" + "zlib", + "user_file_service" ], "third_party": [] }, @@ -88,6 +89,7 @@ "//foundation/filemanagement/dfs_service:cloudsync_asset_kit_inner_target", "//foundation/filemanagement/dfs_service:distributed_file_daemon_kit_inner_target", "//foundation/filemanagement/dfs_service/interfaces/kits/js/ani:ani_package", + "//foundation/filemanagement/dfs_service/interfaces/kits/js/clouddiskmanager:clouddiskmanager", "//foundation/filemanagement/dfs_service/interfaces/kits/js/cloudsyncmanager:cloudsyncmanager", "//foundation/filemanagement/dfs_service/interfaces/kits/js/cloudfilesync:cloudsync", "//foundation/filemanagement/dfs_service/adapter/cloud_adapter_example:cloud_adapter_example_target" diff --git a/interfaces/kits/js/clouddiskmanager/BUILD.gn b/interfaces/kits/js/clouddiskmanager/BUILD.gn new file mode 100644 index 000000000..8e916b47a --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/BUILD.gn @@ -0,0 +1,56 @@ +# Copyright (c) 2025 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. + +import("//build/ohos.gni") +import("//foundation/filemanagement/dfs_service/distributedfile.gni") + +ohos_shared_library("clouddiskmanager") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + include_dirs = [ + "clouddisksyncfoldermanager/include", + ] + + sources = [ + "clouddisksyncfoldermanager/src/comm_root_info.cpp", + "clouddisksyncfoldermanager/src/sync_folder_access_n_exporter.cpp", + "clouddisksyncfoldermanager/src/sync_folder_manager_n_exporter.cpp", + "module.cpp", + ] + + deps = [ + "${utils_path}:libdistributedfileutils" + ] + + external_deps = [ + "c_utils:utils", + "file_api:filemgmt_libhilog", + "file_api:filemgmt_libn", + "hilog:libhilog", + "napi:ace_napi", + "user_file_service:cloud_disk_manager_js_kit" + ] + + relative_install_dir = "module/file" + + part_name = "dfs_service" + subsystem_name = "filemanagement" +} diff --git a/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/comm_root_info.h b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/comm_root_info.h new file mode 100644 index 000000000..d71485fdb --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/comm_root_info.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 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 INTERFACES_KITS_NATIVE_CLOUDDISK_COMM_ROOT_INFO_H +#define INTERFACES_KITS_NATIVE_CLOUDDISK_COMM_ROOT_INFO_H + +#include "filemgmt_libn.h" +#include "napi/native_node_api.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +void InitSyncFolder(napi_env env, napi_value exports); +void InitSyncFolderExt(napi_env env, napi_value exports); +void InitState(napi_env env, napi_value exports); +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_NATIVE_CLOUDDISK_COMM_ROOT_INFO_H \ No newline at end of file diff --git a/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/sync_folder_access_n_exporter.h b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/sync_folder_access_n_exporter.h new file mode 100644 index 000000000..5cbb68aac --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/sync_folder_access_n_exporter.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 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 INTERFACES_KITS_NATIVE_CLOUDDISK_NAPI_SYNC_FOLDER_ACCESS_H +#define INTERFACES_KITS_NATIVE_CLOUDDISK_NAPI_SYNC_FOLDER_ACCESS_H + +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +class SyncFolderAccessNExporter final : public LibN::NExporter { +public: + inline static const std::string className_ = "SyncFolderAccess"; + bool Export() override; + std::string GetClassName() override; + + static napi_value Constructor(napi_env env, napi_callback_info cbinfo); + static napi_value GetAllSyncFolders(napi_env env, napi_callback_info cbinfo); + SyncFolderAccessNExporter(napi_env env, napi_value exports); + ~SyncFolderAccessNExporter() override; +}; +} // namespace SyncFolderAccessNExporter +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_NATIVE_CLOUDDISK_NAPI_SYNC_FOLDER_ACCESS_H diff --git a/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/sync_folder_manager_n_exporter.h b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/sync_folder_manager_n_exporter.h new file mode 100644 index 000000000..282a4e2ba --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/include/sync_folder_manager_n_exporter.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 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 INTERFACES_KITS_NATIVE_CLOUDDISK_NAPI_SYNC_FOLDER_MANAGER_H +#define INTERFACES_KITS_NATIVE_CLOUDDISK_NAPI_SYNC_FOLDER_MANAGER_H + +#include "filemgmt_libn.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudDiskService { +class SyncFolderManagerNExporter final : public LibN::NExporter { +public: + inline static const std::string className_ = "SyncFolderManager"; + bool Export() override; + std::string GetClassName() override; + + static napi_value Constructor(napi_env env, napi_callback_info cbinfo); + static napi_value Register(napi_env env, napi_callback_info cbinfo); + static napi_value Unregister(napi_env env, napi_callback_info cbinfo); + static napi_value Active(napi_env env, napi_callback_info cbinfo); + static napi_value Deactive(napi_env env, napi_callback_info cbinfo); + static napi_value GetSyncFolders(napi_env env, napi_callback_info cbinfo); + static napi_value GetAllSyncFolders(napi_env env, napi_callback_info cbinfo); + static napi_value UpdateDisplayName(napi_env env, napi_callback_info cbinfo); + SyncFolderManagerNExporter(napi_env env, napi_value exports); + ~SyncFolderManagerNExporter() override; +}; +} // namespace CloudDiskService +} // namespace FileManagement +} // namespace OHOS +#endif // INTERFACES_KITS_NATIVE_CLOUDDISK_NAPI_SYNC_FOLDER_MANAGER_H diff --git a/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/comm_root_info.cpp b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/comm_root_info.cpp new file mode 100644 index 000000000..d11d84d28 --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/comm_root_info.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025 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 "comm_root_info.h" + +#include "dfs_error.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace LibN; + +constexpr const char* PATH = "path"; +constexpr const char* STATE = "state"; +constexpr const char* DISPLAY_NAME_RES_ID = "displayNameResId"; +constexpr const char* DISPLAY_NAME = "displayName"; +constexpr const char* BUNDLE_NAME = "bundleName"; +constexpr const char* ACTIVE = "ACTIVE"; +constexpr const char* INACTIVE = "INACTIVE"; + +enum class State { + INACTIVE = 0, + ACTIVE, +}; + +static napi_value SyncFolderConstructor(napi_env env, napi_callback_info info) +{ + size_t argc = 0; + napi_value args[1] = {0}; // 1: argc + napi_value res = nullptr; + void *data = nullptr; + + napi_status status = napi_get_cb_info(env, info, &argc, args, &res, &data); + if (status != napi_ok) { + LOGE("SyncFolderConstructor, status is not napi_ok"); + return nullptr; + } + + return res; +} + +void InitSyncFolder(napi_env env, napi_value exports) +{ + char className[] = "SyncFolder"; + napi_property_descriptor desc[] = { + DECLARE_NAPI_STATIC_PROPERTY(PATH, NVal::CreateUTF8String(env, "").val_), + DECLARE_NAPI_STATIC_PROPERTY(DISPLAY_NAME_RES_ID, NVal::CreateInt32(env, 0).val_), + DECLARE_NAPI_STATIC_PROPERTY(DISPLAY_NAME, NVal::CreateUTF8String(env, "").val_) + }; + napi_value obj = nullptr; + napi_define_class(env, className, NAPI_AUTO_LENGTH, SyncFolderConstructor, nullptr, + sizeof(desc) / sizeof(*desc), desc, &obj); + napi_set_named_property(env, exports, className, obj); +} + +void InitSyncFolderExt(napi_env env, napi_value exports) +{ + char className[] = "SyncFolderExt"; + napi_property_descriptor desc[] = { + DECLARE_NAPI_STATIC_PROPERTY(PATH, NVal::CreateUTF8String(env, "").val_), + DECLARE_NAPI_STATIC_PROPERTY(STATE, NVal::CreateInt32(env, static_cast(State::INACTIVE)).val_), + DECLARE_NAPI_STATIC_PROPERTY(DISPLAY_NAME_RES_ID, NVal::CreateInt32(env, 0).val_), + DECLARE_NAPI_STATIC_PROPERTY(DISPLAY_NAME, NVal::CreateUTF8String(env, "").val_), + DECLARE_NAPI_STATIC_PROPERTY(BUNDLE_NAME, NVal::CreateUTF8String(env, "").val_) + }; + napi_value obj = nullptr; + napi_define_class(env, className, NAPI_AUTO_LENGTH, SyncFolderConstructor, nullptr, + sizeof(desc) / sizeof(*desc), desc, &obj); + napi_set_named_property(env, exports, className, obj); +} + +void InitState(napi_env env, napi_value exports) +{ + char propertyName[] = "State"; + napi_property_descriptor desc[] = { + DECLARE_NAPI_STATIC_PROPERTY(ACTIVE, NVal::CreateInt32(env, static_cast(State::ACTIVE)).val_), + DECLARE_NAPI_STATIC_PROPERTY(INACTIVE, NVal::CreateInt32(env, static_cast(State::INACTIVE)).val_) + }; + napi_value obj = nullptr; + napi_create_object(env, &obj); + napi_define_properties(env, obj, sizeof(desc) / sizeof(desc[0]), desc); + napi_set_named_property(env, exports, propertyName, obj); +} +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/sync_folder_access_n_exporter.cpp b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/sync_folder_access_n_exporter.cpp new file mode 100644 index 000000000..53762c07c --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/sync_folder_access_n_exporter.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2025 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 "sync_folder_access_n_exporter.h" + +#include + +#include "cloud_disk_js_manager.h" +#include "dfs_error.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; +using namespace LibN; +constexpr const char* PATH = "path"; +constexpr const char* STATE = "state"; +constexpr const char* DISPLAY_NAME_RES_ID = "displayNameResId"; +constexpr const char* DISPLAY_NAME = "displayName"; +constexpr const char* BUNDLE_NAME = "bundleName"; + +std::tuple CreateSyncFolderExtList(napi_env env, + const std::vector &syncFolderExts) +{ + napi_value res = nullptr; + napi_status status = napi_ok; + if ((status = napi_create_array(env, &res)) != napi_ok) { + LOGE("Create array failed"); + return { status, res }; + } + for (size_t i = 0; i < syncFolderExts.size(); ++i) { + napi_value ele = nullptr; + if ((napi_create_object(env, &ele)) != napi_ok) { + LOGE("Create object failed"); + return { status, res }; + } + if ((napi_set_named_property( + env, ele, PATH, NVal::CreateUTF8String(env, syncFolderExts[i].path_).val_)) != napi_ok) { + LOGE("Set named property path failed"); + return { status, res }; + } + if ((status = napi_set_named_property(env, ele, STATE, + NVal::CreateInt32(env, static_cast(syncFolderExts[i].state_)).val_)) != napi_ok) { + LOGE("Set named property state failed"); + return { status, res }; + } + if (syncFolderExts[i].displayNameResId_ != -1) { + if ((status = napi_set_named_property(env, ele, DISPLAY_NAME_RES_ID, + NVal::CreateInt32(env, syncFolderExts[i].displayNameResId_).val_)) != napi_ok) { + LOGE("Set named property resId failed"); + return { status, res }; + } + } + if (!syncFolderExts[i].displayName_.empty()) { + if ((status = napi_set_named_property(env, + ele, DISPLAY_NAME, NVal::CreateUTF8String(env, syncFolderExts[i].displayName_).val_)) != napi_ok) { + LOGE("Set named property displayName failed"); + return { status, res }; + } + } + if ((status = napi_set_named_property(env, + ele, BUNDLE_NAME, NVal::CreateUTF8String(env, syncFolderExts[i].bundleName_).val_)) != napi_ok) { + LOGE("Set named property bundleName failed"); + return { status, res }; + } + if ((status = napi_set_element(env, res, i, ele)) != napi_ok) { + LOGE("Set element failed"); + return { status, res }; + } + } + return { napi_ok, res }; +} + +SyncFolderAccessNExporter::SyncFolderAccessNExporter(napi_env env, napi_value exports): NExporter(env, exports) {} + +SyncFolderAccessNExporter::~SyncFolderAccessNExporter() {}; + +napi_value SyncFolderAccessNExporter::GetAllSyncFolders(napi_env env, napi_callback_info cbinfo) +{ + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + LOGE("Number of arguments unmatched"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto result = std::make_shared>(); + auto syncFolerJSAccess = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolerJSAccess) { + LOGE("GetEntityOf syncFolerJSAccess failed"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto cbExec = [result, syncFolerJSAccess]() -> NError { + if (!syncFolerJSAccess) { + LOGE("syncFolerManager is nullptr"); + return NError(ERR_INTERNAL_ERROR); + } + int ret = syncFolerJSAccess->GetAllSyncFolders(*result); + return NError(ret); + }; + auto cbCompl = [result](napi_env env, NError err) -> NVal { + if (err) { + return {env, err.GetNapiErr(env)}; + } + auto [succSta, syncFolderVec] = CreateSyncFolderExtList(env, *result); + if (succSta == napi_ok) { + return {env, syncFolderVec}; + } + LOGE("CreateSyncFolderExtList failed"); + return {env, NError(ERR_INTERNAL_ERROR).GetNapiErr(env)}; + }; + const string procedureName = "clouddisk_getAllSyncFolders"; + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_; +} + +std::string SyncFolderAccessNExporter::GetClassName() +{ + return SyncFolderAccessNExporter::className_; +} + +napi_value SyncFolderAccessNExporter::Constructor(napi_env env, napi_callback_info cbinfo) +{ + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + LOGE("Number of arguments unmatched"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + unique_ptr cloudDiskJSManager = make_unique(); + if (!NClass::SetEntityFor(env, funcArg.GetThisVar(), std::move(cloudDiskJSManager))) { + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + return funcArg.GetThisVar(); +} + +bool SyncFolderAccessNExporter::Export() +{ + vector props = { + NVal::DeclareNapiFunction("getAllSyncFolders", GetAllSyncFolders) + }; + string className = GetClassName(); + bool succ = false; + napi_value classValue = nullptr; + std::tie(succ, classValue) = NClass::DefineClass( + exports_.env_, className, SyncFolderAccessNExporter::Constructor, std::move(props)); + if (!succ) { + LOGE("Failed to define class %{public}s", className.c_str()); + NError(ERR_INVALID_PARAM).ThrowErr(exports_.env_); + return false; + } + succ = NClass::SaveClass(exports_.env_, className, classValue); + if (!succ) { + LOGE("Failed to save class %{public}s", className.c_str()); + NError(ERR_INVALID_PARAM).ThrowErr(exports_.env_); + return false; + } + return exports_.AddProp(className, classValue); +} +} // namespace OHOS::FileManagement::CloudDiskService diff --git a/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/sync_folder_manager_n_exporter.cpp b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/sync_folder_manager_n_exporter.cpp new file mode 100644 index 000000000..93db72acd --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/clouddisksyncfoldermanager/src/sync_folder_manager_n_exporter.cpp @@ -0,0 +1,465 @@ +/* + * Copyright (c) 2025 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 "sync_folder_manager_n_exporter.h" + +#include + +#include "cloud_disk_js_manager.h" +#include "dfs_error.h" +#include "utils_log.h" + +namespace OHOS::FileManagement::CloudDiskService { +using namespace std; +using namespace LibN; +constexpr const char* PATH = "path"; +constexpr const char* DISPLAY_NAME_RES_ID = "displayNameResId"; +constexpr const char* DISPLAY_NAME = "displayName"; +constexpr const char* STATE = "state"; +static napi_status ParseOptionalArguments(napi_env env, napi_value argv, SyncFolder &syncFolder) +{ + napi_value resIdValue = nullptr; + napi_value displayNameValue = nullptr; + napi_status status = napi_ok; + bool isHasResId = false; + if ((status = napi_has_named_property(env, argv, DISPLAY_NAME_RES_ID, &isHasResId)) == napi_ok && isHasResId) { + if ((status = napi_get_named_property(env, argv, DISPLAY_NAME_RES_ID, &resIdValue)) != napi_ok) { + LOGE("get named property displayNameResId failed"); + return status; + } + } else { + LOGW("has no property displayNameResId"); + } + bool isHasName = false; + if ((status = napi_has_named_property(env, argv, DISPLAY_NAME, &isHasName)) == napi_ok && isHasName) { + if ((status = napi_get_named_property(env, argv, DISPLAY_NAME, &displayNameValue)) != napi_ok) { + LOGE("get named property displayNameResId failed"); + return status; + } + } else { + LOGW("has no property displayName"); + } + if (isHasResId) { + auto [succResId, resId] = NVal(env, resIdValue).ToInt32(); + if (!succResId) { + LOGE("the argument resId error"); + return napi_invalid_arg; + } + syncFolder.displayNameResId_ = resId; + } + if (isHasName) { + auto [succdisplayName, strDisplayName, ignore] = NVal(env, displayNameValue).ToUTF8String(); + if (!succdisplayName) { + LOGE("the argument displayName error"); + return napi_invalid_arg; + } + syncFolder.displayName_ = strDisplayName.get(); + } + return napi_ok; +} + +napi_status ParseNecessaryArguments(napi_env env, napi_value argv, SyncFolder &syncFolder) +{ + napi_value pathValue = nullptr; + napi_status status = napi_ok; + if ((status = napi_get_named_property(env, argv, PATH, &pathValue)) != napi_ok) { + LOGE("get named property path failed"); + return status; + } + auto [succStr, strPath, ignorePath] = NVal(env, pathValue).ToUTF8String(); + if (!succStr) { + LOGE("the argument error, succStr = %{public}d", succStr); + return napi_invalid_arg; + } + syncFolder.path_ = strPath.get(); + if (syncFolder.path_.empty()) { + LOGE("the argument path error"); + return napi_invalid_arg; + } + return napi_ok; +} + +static napi_status GetSyncFolderFromNapi(napi_env env, + napi_value argv, SyncFolder &syncFolder) +{ + napi_status status = napi_ok; + status = ParseNecessaryArguments(env, argv, syncFolder); + if (status != napi_ok) { + LOGE("ParseNecessaryArguments failed"); + return status; + } + status = ParseOptionalArguments(env, argv, syncFolder); + if (status != napi_ok) { + LOGE("ParseOptionalArguments failed"); + return status; + } + return napi_ok; +} + +static std::tuple CreateSyncFolderList(napi_env env, + const std::vector &syncFolders) +{ + napi_value res = nullptr; + napi_status status = napi_ok; + if ((status = napi_create_array(env, &res)) != napi_ok) { + LOGE("Create array failed"); + return { status, res }; + } + for (size_t i = 0; i < syncFolders.size(); ++i) { + napi_value ele = nullptr; + if ((napi_create_object(env, &ele)) != napi_ok) { + LOGE("Create object failed"); + return { status, res }; + } + if ((napi_set_named_property( + env, ele, PATH, NVal::CreateUTF8String(env, syncFolders[i].path_).val_)) != napi_ok) { + LOGE("Set named property path failed"); + return { status, res }; + } + if ((status = napi_set_named_property( + env, ele, STATE, NVal::CreateInt32(env, static_cast(syncFolders[i].state_)).val_)) != napi_ok) { + LOGE("Set named property state failed"); + return { status, res }; + } + if (syncFolders[i].displayNameResId_ != -1) { + if ((status = napi_set_named_property(env, ele, DISPLAY_NAME_RES_ID, + NVal::CreateInt32(env, syncFolders[i].displayNameResId_).val_)) != napi_ok) { + LOGE("Set named property resId failed"); + return { status, res }; + } + } + if (!syncFolders[i].displayName_.empty()) { + if ((status = napi_set_named_property(env, + ele, DISPLAY_NAME, NVal::CreateUTF8String(env, syncFolders[i].displayName_).val_)) != napi_ok) { + LOGE("Set named property displayName failed"); + return { status, res }; + } + } + if ((status = napi_set_element(env, res, i, ele)) != napi_ok) { + LOGE("Set element failed"); + return { status, res }; + } + } + return { napi_ok, res }; +} + +SyncFolderManagerNExporter::SyncFolderManagerNExporter(napi_env env, napi_value exports): NExporter(env, exports) {} + +SyncFolderManagerNExporter::~SyncFolderManagerNExporter() {}; + + +std::string SyncFolderManagerNExporter::GetClassName() +{ + return SyncFolderManagerNExporter::className_; +} +napi_value SyncFolderManagerNExporter::Constructor(napi_env env, napi_callback_info cbinfo) +{ + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + LOGE("Number of arguments unmatched"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + unique_ptr cloudDiskJSManager = make_unique(); + if (!NClass::SetEntityFor(env, funcArg.GetThisVar(), std::move(cloudDiskJSManager))) { + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + return funcArg.GetThisVar(); +} + +bool SyncFolderManagerNExporter::Export() +{ + vector props = { + NVal::DeclareNapiFunction("register", Register), + NVal::DeclareNapiFunction("unregister", Unregister), + NVal::DeclareNapiFunction("active", Active), + NVal::DeclareNapiFunction("deactive", Deactive), + NVal::DeclareNapiFunction("getSyncFolders", GetSyncFolders), + NVal::DeclareNapiFunction("updateDisplayName", UpdateDisplayName), + }; + string className = GetClassName(); + bool succ = false; + napi_value classValue = nullptr; + std::tie(succ, classValue) = NClass::DefineClass( + exports_.env_, className, SyncFolderManagerNExporter::Constructor, std::move(props)); + if (!succ) { + LOGE("Failed to define class %{public}s", className.c_str()); + NError(ERR_INTERNAL_ERROR).ThrowErr(exports_.env_); + return false; + } + succ = NClass::SaveClass(exports_.env_, className, classValue); + if (!succ) { + LOGE("Failed to save class %{public}s", className.c_str()); + NError(ERR_INTERNAL_ERROR).ThrowErr(exports_.env_); + return false; + } + return exports_.AddProp(className, classValue); +} + +napi_value SyncFolderManagerNExporter::Register(napi_env env, napi_callback_info cbinfo) +{ + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ONE)) { + LOGE("Number of arguments unmatched"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + SyncFolder syncFolder; + if (GetSyncFolderFromNapi(env, funcArg[NARG_POS::FIRST], syncFolder) != napi_ok) { + LOGE("GetSyncFolderFromNapi failed"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto syncFolerJSManager = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolerJSManager) { + LOGE("GetEntityOf syncFolerJSManager failed"); + NError(ERR_INTERNAL_ERROR).ThrowErr(env); + return nullptr; + } + auto cbExec = [syncFolerJSManager, syncFolder]() -> NError { + if (!syncFolerJSManager) { + LOGE("syncFolerJSManager is nullptr"); + return NError(ERR_INTERNAL_ERROR); + } + int ret = syncFolerJSManager->Register(syncFolder); + return NError(ret); + }; + auto cbCompl = [](napi_env env, NError err) -> NVal { + if (err) { + return {env, err.GetNapiErr(env)}; + } + return { NVal::CreateBool(env, true) }; + }; + const string procedureName = "clouddisk_register"; + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_; +} + +napi_value SyncFolderManagerNExporter::Unregister(napi_env env, napi_callback_info cbinfo) +{ + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ONE)) { + LOGE("Number of arguments unmatched"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto [succStr, str, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succStr) { + LOGE("NVal trans to string failed"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + std::string path = string(str.get()); + if (path.empty()) { + LOGE("The argument path is empty"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto syncFolerJSManager = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolerJSManager) { + LOGE("GetEntityOf syncFolerJSManager failed"); + NError(ERR_INTERNAL_ERROR).ThrowErr(env); + return nullptr; + } + auto cbExec = [path, syncFolerJSManager]() -> NError { + if (!syncFolerJSManager) { + LOGE("syncFolerJSManager is nullptr"); + return NError(ERR_INTERNAL_ERROR); + } + int ret = syncFolerJSManager->Unregister(path); + return NError(ret); + }; + auto cbCompl = [](napi_env env, NError err) -> NVal { + if (err) { + return {env, err.GetNapiErr(env)}; + } + return { NVal::CreateBool(env, true) }; + }; + const string procedureName = "clouddisk_unregister"; + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_; +} + +napi_value SyncFolderManagerNExporter::Active(napi_env env, napi_callback_info cbinfo) +{ + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ONE)) { + LOGE("Number of arguments unmatched"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto [succStr, str, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succStr) { + LOGE("NVal trans to string failed"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + std::string path = string(str.get()); + if (path.empty()) { + LOGE("The argument path is empty"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto syncFolerJSManager = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolerJSManager) { + LOGE("GetEntityOf syncFolerJSManager failed"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto cbExec = [path, syncFolerJSManager]() -> NError { + if (!syncFolerJSManager) { + LOGE("syncFolerJSManager is nullptr"); + return NError(ERR_INTERNAL_ERROR); + } + int ret = syncFolerJSManager->Active(path); + return NError(ret); + }; + auto cbCompl = [](napi_env env, NError err) -> NVal { + if (err) { + return {env, err.GetNapiErr(env)}; + } + return { NVal::CreateBool(env, true) }; + }; + const string procedureName = "clouddisk_active"; + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_; +} + +napi_value SyncFolderManagerNExporter::Deactive(napi_env env, napi_callback_info cbinfo) +{ + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ONE)) { + LOGE("Number of arguments unmatched"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto [succStr, str, ignore] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + if (!succStr) { + LOGE("NVal trans to string failed"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + std::string path = string(str.get()); + if (path.empty()) { + LOGE("The argument path is empty"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto syncFolerJSManager = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolerJSManager) { + LOGE("GetEntityOf syncFolerJSManager failed"); + NError(ERR_INTERNAL_ERROR).ThrowErr(env); + return nullptr; + } + auto cbExec = [path, syncFolerJSManager]() -> NError { + if (!syncFolerJSManager) { + LOGE("syncFolerJSManager is nullptr"); + return NError(ERR_INTERNAL_ERROR); + } + int ret = syncFolerJSManager->Deactive(path); + return NError(ret); + }; + auto cbCompl = [](napi_env env, NError err) -> NVal { + if (err) { + return {env, err.GetNapiErr(env)}; + } + return { NVal::CreateBool(env, true) }; + }; + const string procedureName = "clouddisk_inactive"; + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_; +} + +napi_value SyncFolderManagerNExporter::GetSyncFolders(napi_env env, napi_callback_info cbinfo) +{ + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::ZERO)) { + LOGE("Number of arguments unmatched"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto result = std::make_shared>(); + auto syncFolerJSManager = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolerJSManager) { + LOGE("GetEntityOf syncFolerJSManager failed"); + NError(ERR_INTERNAL_ERROR).ThrowErr(env); + return nullptr; + } + auto cbExec = [result, syncFolerJSManager]() -> NError { + if (!syncFolerJSManager) { + LOGE("syncFolerJSManager is nullptr"); + return NError(ERR_INTERNAL_ERROR); + } + int ret = syncFolerJSManager->GetSyncFolders(*result); + return NError(ret); + }; + auto cbCompl = [result](napi_env env, NError err) -> NVal { + if (err) { + return {env, err.GetNapiErr(env)}; + } + auto [succSta, syncFolderVec] = CreateSyncFolderList(env, *result); + if (succSta == napi_ok) { + return {env, syncFolderVec}; + } + LOGE("CreateSyncFolderList failed"); + return {env, NError(ERR_INVALID_PARAM).GetNapiErr(env)}; + }; + const string procedureName = "clouddisk_getsyncfolders"; + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_; +} + +napi_value SyncFolderManagerNExporter::UpdateDisplayName(napi_env env, napi_callback_info cbinfo) +{ + NFuncArg funcArg(env, cbinfo); + if (!funcArg.InitArgs(NARG_CNT::TWO)) { + LOGE("Number of arguments unmatched"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto [succPath, strPath, ignorePath] = NVal(env, funcArg[NARG_POS::FIRST]).ToUTF8String(); + auto [succName, strName, ignoreName] = NVal(env, funcArg[NARG_POS::SECOND]).ToUTF8String(); + std::string path = std::string(strPath.get()); + std::string bundleName = std::string(strName.get()); + auto syncFolerJSManager = NClass::GetEntityOf(env, funcArg.GetThisVar()); + if (!syncFolerJSManager) { + LOGE("GetEntityOf syncFolerJSManager failed"); + NError(ERR_INTERNAL_ERROR).ThrowErr(env); + return nullptr; + } + if (path.empty()) { + LOGE("The argument path is empty"); + NError(ERR_INVALID_PARAM).ThrowErr(env); + return nullptr; + } + auto cbExec = [path, bundleName, syncFolerJSManager]() -> NError { + if (!syncFolerJSManager) { + LOGE("syncFolerJSManager is nullptr"); + return NError(ERR_INTERNAL_ERROR); + } + int ret = syncFolerJSManager->UpdateDisplayName(path, bundleName); + return NError(ret); + }; + auto cbCompl = [](napi_env env, NError err) -> NVal { + if (err) { + return {env, err.GetNapiErr(env)}; + } + return { NVal::CreateBool(env, true) }; + }; + const string procedureName = "cloud_disk_updatedisplayname"; + NVal thisVar(env, funcArg.GetThisVar()); + return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_; +} +} // namespace OHOS::FileManagement::CloudDisk diff --git a/interfaces/kits/js/clouddiskmanager/module.cpp b/interfaces/kits/js/clouddiskmanager/module.cpp new file mode 100644 index 000000000..134ebd5c4 --- /dev/null +++ b/interfaces/kits/js/clouddiskmanager/module.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 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 +#include + +#include "comm_root_info.h" +#include "filemgmt_libn.h" +#include "sync_folder_access_n_exporter.h" +#include "sync_folder_manager_n_exporter.h" +#include "utils_log.h" +namespace OHOS::FileManagement::CloudDiskService { +using namespace LibN; + +static napi_value InitCloudDisk(napi_env env, napi_value exports) +{ + InitSyncFolder(env, exports); + InitSyncFolderExt(env, exports); + InitState(env, exports); + std::vector> products; + products.emplace_back(std::make_unique(env, exports)); + products.emplace_back(std::make_unique(env, exports)); + for (auto &&product : products) { + if (!product->Export()) { + LOGE("INNER BUG. Failed to export class %{public}s for module recent", + product->GetClassName().c_str()); + return nullptr; + } else { + LOGW("Class %{public}s for module fileio has been exported", product->GetClassName().c_str()); + } + } + + return exports; +} + +static napi_module _module = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = InitCloudDisk, + .nm_modname = "file.cloudDiskManager", + .nm_priv = ((void *)0), + .reserved = {0} +}; + +extern "C" __attribute__((constructor)) void RegisterModule(void) +{ + napi_module_register(&_module); +} +} // namespace OHOS::FileManagement::CloudDiskService \ No newline at end of file diff --git a/utils/log/include/dfs_error.h b/utils/log/include/dfs_error.h index 512b8db99..edb8d4ba1 100644 --- a/utils/log/include/dfs_error.h +++ b/utils/log/include/dfs_error.h @@ -34,6 +34,7 @@ constexpr int SOFTBUS_TRANS_FILE_NETWORK_ERROR = -426114935; constexpr int SOFTBUS_TRANS_FILE_NOT_FOUND = -426114934; constexpr int SOFTBUS_TRANS_FILE_EXISTED = -426114933; constexpr int DFS_CANCEL_SUCCESS = 204; +constexpr int CLOUD_DISK_MANAGER_BASE_OFFSET = 14500001; enum CloudSyncServiceErrCode : ErrCode { E_OK = 0, @@ -139,6 +140,22 @@ enum CloudSyncServiceErrCode : ErrCode { E_DK_NO_ATTRIBUTES = E_DK_FIELD_BASIC + 1, }; +enum CloudDiskManagerErrCode { + // cloud disk errcode + ERR_INVALID_PARAM = CLOUD_DISK_MANAGER_BASE_OFFSET, // Invalid parameter + ERR_PERSIST_SYNC_FOLDER_FAILED, // Failed to persist Sync folder + ERR_IPC_FAILED, // IPC error + ERR_SYNC_FOLDER_LIMIT_EXCEEDED, // Sync folder limit exceeded + ERR_SYNC_FOLDER_CONFLICT_SELF, // Conflict with own app's Sync folder + ERR_SYNC_FOLDER_CONFLICT_OTHER, // Conflict with other app's Sync folder + ERR_CREATE_SYNC_FOLDER_FAILED, // Failed to create Sync folder + ERR_SYNC_FOLDER_NOT_EXIST, // Sync folder does not exist + ERR_REMOVE_SYNC_FOLDER_FAILED, // Failed to remove Sync folder + ERR_UPDATE_SYNC_FOLDER_FAILED, // Failed to update Sync folder properties + ERR_INTERNAL_ERROR, // Internal error + ERR_SYSTEM_RESTRICTED, // System restricted +}; + enum DFSErrCode { ERR_OK = 0, ERR_BAD_VALUE = -1, -- Gitee