diff --git a/frameworks/innerkits/file_access/include/js_file_access_ext_ability.h b/frameworks/innerkits/file_access/include/js_file_access_ext_ability.h index 8ac3b18d35db49103380f3f18940af83da2ecee7..49d26194d18b5db388475caaae0850f78016741e 100644 --- a/frameworks/innerkits/file_access/include/js_file_access_ext_ability.h +++ b/frameworks/innerkits/file_access/include/js_file_access_ext_ability.h @@ -17,14 +17,32 @@ #define JS_FILE_EXT_ABILITY_H #include "file_access_ext_ability.h" - +#include "file_access_extension_info.h" #include "js_runtime.h" +#include "napi_common_fileaccess.h" #include "native_engine/native_reference.h" #include "native_engine/native_value.h" namespace OHOS { namespace FileAccessFwk { using namespace AbilityRuntime; + +struct ThreadLockInfo { + std::mutex fileOperateMutex; + std::condition_variable fileOperateCondition; + bool isReady = false; +}; + +struct CallbackParam { + ThreadLockInfo *lockInfo; + JsRuntime &jsRuntime; + std::shared_ptr jsObj; + const char *funcName; + NativeValue * const *argv; + size_t argc; + NativeValue *result; +}; + class JsFileAccessExtAbility : public FileAccessExtAbility { public: JsFileAccessExtAbility(JsRuntime& jsRuntime); @@ -36,16 +54,22 @@ public: const std::shared_ptr &application, std::shared_ptr &handler, const sptr &token) override; - void OnStart(const AAFwk::Want &want) override; - sptr OnConnect(const AAFwk::Want &want) override; - + int OpenFile(const Uri &uri, int flags) override; + int CreateFile(const Uri &parent, const std::string &displayName, Uri &newFile) override; + int Mkdir(const Uri &parent, const std::string &displayName, Uri &newFile) override; + int Delete(const Uri &sourceFile) override; + int Move(const Uri &sourceFile, const Uri &targetParent, Uri &newFile) override; + int Rename(const Uri &sourceFile, const std::string &displayName, Uri &newFile) override; + std::vector ListFile(const Uri &sourceFile) override; + std::vector GetRoots() override; private: + NativeValue* AsnycCallObjectMethod(const char *name, NativeValue * const *argv = nullptr, size_t argc = 0); NativeValue* CallObjectMethod(const char *name, NativeValue * const *argv = nullptr, size_t argc = 0); void GetSrcPath(std::string &srcPath); - JsRuntime& jsRuntime_; + JsRuntime &jsRuntime_; std::shared_ptr jsObj_; }; } // namespace FileAccessFwk diff --git a/frameworks/innerkits/file_access/src/js_file_access_ext_ability.cpp b/frameworks/innerkits/file_access/src/js_file_access_ext_ability.cpp index d11607cc84df20e9d58ec533aa5d6191efb3f468..9bdefbef080602a6182f5b3d416f5de4723682bf 100644 --- a/frameworks/innerkits/file_access/src/js_file_access_ext_ability.cpp +++ b/frameworks/innerkits/file_access/src/js_file_access_ext_ability.cpp @@ -15,15 +15,18 @@ #include "js_file_access_ext_ability.h" -#include "extension_context.h" #include "ability_info.h" #include "accesstoken_kit.h" +#include "extension_context.h" +#include "file_access_ext_stub_impl.h" +#include "file_access_framework_errno.h" #include "hilog_wrapper.h" #include "ipc_skeleton.h" #include "js_runtime.h" #include "js_runtime_utils.h" #include "napi/native_api.h" #include "napi/native_node_api.h" +#include "napi_common_fileaccess.h" #include "napi_common_util.h" #include "napi_common_want.h" #include "napi_remote_object.h" @@ -31,7 +34,9 @@ namespace OHOS { namespace FileAccessFwk { namespace { +constexpr size_t ARGC_ZERO = 0; constexpr size_t ARGC_ONE = 1; +constexpr size_t ARGC_TWO = 2; } using namespace OHOS::AppExecFwk; @@ -88,7 +93,14 @@ void JsFileAccessExtAbility::OnStart(const AAFwk::Want &want) sptr JsFileAccessExtAbility::OnConnect(const AAFwk::Want &want) { Extension::OnConnect(want); - return nullptr; + sptr remoteObject = new (std::nothrow) FileAccessExtStubImpl( + std::static_pointer_cast(shared_from_this()), + reinterpret_cast(&jsRuntime_.GetNativeEngine())); + if (remoteObject == nullptr) { + HILOG_ERROR("%{public}s No memory allocated for FileExtStubImpl", __func__); + return nullptr; + } + return remoteObject->AsObject(); } NativeValue* JsFileAccessExtAbility::CallObjectMethod(const char* name, NativeValue* const* argv, size_t argc) @@ -121,6 +133,71 @@ NativeValue* JsFileAccessExtAbility::CallObjectMethod(const char* name, NativeVa return handleScope.Escape(nativeEngine.CallFunction(value, method, argv, argc)); } +static bool DoAsnycWork(CallbackParam *param) +{ + if (param == nullptr || param->jsObj == nullptr) { + HILOG_ERROR("Not found js file object"); + return false; + } + HandleScope handleScope(param->jsRuntime); + NativeValue* value = param->jsObj->Get(); + if (value == nullptr) { + HILOG_ERROR("Failed to get native value object"); + return false; + } + NativeObject* obj = ConvertNativeValueTo(value); + if (obj == nullptr) { + HILOG_ERROR("Failed to get FileExtAbility object"); + return false; + } + NativeValue* method = obj->GetProperty(param->funcName); + if (method == nullptr) { + HILOG_ERROR("Failed to get '%{public}s' from FileExtAbility object", param->funcName); + return false; + } + auto& nativeEngine = param->jsRuntime.GetNativeEngine(); + param->result = handleScope.Escape(nativeEngine.CallFunction(value, method, param->argv, param->argc)); + return true; +} + +NativeValue* JsFileAccessExtAbility::AsnycCallObjectMethod(const char* name, NativeValue* const* argv, size_t argc) +{ + std::shared_ptr lockInfo = std::make_shared(); + std::shared_ptr param = std::make_shared(CallbackParam { + .lockInfo = lockInfo.get(), + .jsRuntime = jsRuntime_, + .jsObj = jsObj_, + .funcName = name, + .argv = argv, + .argc = argc, + .result = nullptr + }); + if (param == nullptr) { + HILOG_ERROR("failed to new param"); + return nullptr; + } + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(reinterpret_cast(&jsRuntime_.GetNativeEngine()), &loop); + std::shared_ptr work = std::make_shared(); + if (work == nullptr) { + HILOG_ERROR("failed to new uv_work_t"); + return nullptr; + } + work->data = reinterpret_cast(param.get()); + uv_queue_work(loop, work.get(), [](uv_work_t *work) {}, [](uv_work_t *work, int status) { + CallbackParam *param = reinterpret_cast(work->data); + if (!DoAsnycWork(param)) { + HILOG_ERROR("failed to call DoAsnycWork"); + } + std::unique_lock lock(param->lockInfo->fileOperateMutex); + param->lockInfo->isReady = true; + param->lockInfo->fileOperateCondition.notify_all(); + }); + std::unique_lock lock(param->lockInfo->fileOperateMutex); + param->lockInfo->fileOperateCondition.wait(lock, [param]() { return param->lockInfo->isReady; }); + return std::move(param->result); +} + void JsFileAccessExtAbility::GetSrcPath(std::string &srcPath) { if (!Extension::abilityInfo_->isStageBasedModel) { @@ -141,5 +218,212 @@ void JsFileAccessExtAbility::GetSrcPath(std::string &srcPath) srcPath.append(".abc"); } } + +int JsFileAccessExtAbility::OpenFile(const Uri &uri, int flags) +{ + HandleScope handleScope(jsRuntime_); + napi_env env = reinterpret_cast(&jsRuntime_.GetNativeEngine()); + + napi_value napiUri = nullptr; + napi_create_string_utf8(env, uri.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri); + napi_value napiFlags = nullptr; + napi_create_int32(env, flags, &napiFlags); + + NativeValue* nativeUri = reinterpret_cast(napiUri); + NativeValue* nativeFlags = reinterpret_cast(napiFlags); + NativeValue* argv[] = {nativeUri, nativeFlags}; + NativeValue* nativeResult = AsnycCallObjectMethod("openFile", argv, ARGC_TWO); + int ret = ERR_ERROR; + if (nativeResult == nullptr) { + HILOG_ERROR("%{public}s call openFile with return null.", __func__); + return ret; + } + ret = OHOS::AppExecFwk::UnwrapInt32FromJS(env, reinterpret_cast(nativeResult)); + return ret; +} + +int JsFileAccessExtAbility::CreateFile(const Uri &parent, const std::string &displayName, Uri &newFile) +{ + HandleScope handleScope(jsRuntime_); + napi_env env = reinterpret_cast(&jsRuntime_.GetNativeEngine()); + + napi_value napiParent = nullptr; + napi_create_string_utf8(env, parent.ToString().c_str(), NAPI_AUTO_LENGTH, &napiParent); + napi_value napiDisplayName = nullptr; + napi_create_string_utf8(env, displayName.c_str(), NAPI_AUTO_LENGTH, &napiDisplayName); + + NativeValue* nativeParent = reinterpret_cast(napiParent); + NativeValue* nativeDisplayName = reinterpret_cast(napiDisplayName); + NativeValue* argv[] = {nativeParent, nativeDisplayName}; + NativeValue* nativeResult = AsnycCallObjectMethod("createFile", argv, ARGC_TWO); + int ret = ERR_ERROR; + if (nativeResult == nullptr) { + HILOG_ERROR("%{public}s call createFile with return null.", __func__); + return ret; + } + std::string uriStr = OHOS::AppExecFwk::UnwrapStringFromJS(env, reinterpret_cast(nativeResult)); + if (uriStr.empty()) { + HILOG_ERROR("%{public}s call createFile with return empty.", __func__); + return ret; + } else { + ret = NO_ERROR; + } + newFile = Uri(uriStr); + return ret; +} + +int JsFileAccessExtAbility::Mkdir(const Uri &parent, const std::string &displayName, Uri &newFile) +{ + HandleScope handleScope(jsRuntime_); + napi_env env = reinterpret_cast(&jsRuntime_.GetNativeEngine()); + + napi_value napiParent = nullptr; + napi_create_string_utf8(env, parent.ToString().c_str(), NAPI_AUTO_LENGTH, &napiParent); + napi_value napiDisplayName = nullptr; + napi_create_string_utf8(env, displayName.c_str(), NAPI_AUTO_LENGTH, &napiDisplayName); + + NativeValue* nativeParent = reinterpret_cast(napiParent); + NativeValue* nativeDisplayName = reinterpret_cast(napiDisplayName); + NativeValue* argv[] = {nativeParent, nativeDisplayName}; + NativeValue* nativeResult = AsnycCallObjectMethod("mkdir", argv, ARGC_TWO); + int ret = ERR_ERROR; + if (nativeResult == nullptr) { + HILOG_ERROR("%{public}s call Mkdir with return null.", __func__); + return ret; + } + std::string uriStr = OHOS::AppExecFwk::UnwrapStringFromJS(env, reinterpret_cast(nativeResult)); + if (uriStr.empty()) { + HILOG_ERROR("%{public}s call Mkdir with return empty.", __func__); + return ret; + } else { + ret = NO_ERROR; + } + newFile = Uri(uriStr); + return ret; +} + +int JsFileAccessExtAbility::Delete(const Uri &sourceFile) +{ + HandleScope handleScope(jsRuntime_); + napi_env env = reinterpret_cast(&jsRuntime_.GetNativeEngine()); + + napi_value napiUri = nullptr; + napi_create_string_utf8(env, sourceFile.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri); + + NativeValue* nativeUri = reinterpret_cast(napiUri); + NativeValue* argv[] = {nativeUri}; + NativeValue* nativeResult = AsnycCallObjectMethod("delete", argv, ARGC_ONE); + int ret = ERR_ERROR; + if (nativeResult == nullptr) { + HILOG_ERROR("%{public}s call delete with return null.", __func__); + return ret; + } + ret = OHOS::AppExecFwk::UnwrapInt32FromJS(env, reinterpret_cast(nativeResult)); + return ret; +} + +int JsFileAccessExtAbility::Move(const Uri &sourceFile, const Uri &targetParent, Uri &newFile) +{ + HandleScope handleScope(jsRuntime_); + napi_env env = reinterpret_cast(&jsRuntime_.GetNativeEngine()); + + napi_value napiSourceFile = nullptr; + napi_create_string_utf8(env, sourceFile.ToString().c_str(), NAPI_AUTO_LENGTH, &napiSourceFile); + napi_value napiTargetParent = nullptr; + napi_create_string_utf8(env, targetParent.ToString().c_str(), NAPI_AUTO_LENGTH, &napiTargetParent); + + NativeValue* nativeSourceFile = reinterpret_cast(napiSourceFile); + NativeValue* nativeTargetParent = reinterpret_cast(napiTargetParent); + NativeValue* argv[] = {nativeSourceFile, nativeTargetParent}; + NativeValue* nativeResult = AsnycCallObjectMethod("move", argv, ARGC_TWO); + int ret = ERR_ERROR; + if (nativeResult == nullptr) { + HILOG_ERROR("%{public}s call move with return null.", __func__); + return ret; + } + std::string uriStr = OHOS::AppExecFwk::UnwrapStringFromJS(env, reinterpret_cast(nativeResult)); + if (uriStr.empty()) { + HILOG_ERROR("%{public}s call move with return empty.", __func__); + return ret; + } else { + ret = NO_ERROR; + } + newFile = Uri(uriStr); + return ret; +} + +int JsFileAccessExtAbility::Rename(const Uri &sourceFile, const std::string &displayName, Uri &newFile) +{ + HandleScope handleScope(jsRuntime_); + napi_env env = reinterpret_cast(&jsRuntime_.GetNativeEngine()); + + napi_value napiSourceFile = nullptr; + napi_create_string_utf8(env, sourceFile.ToString().c_str(), NAPI_AUTO_LENGTH, &napiSourceFile); + napi_value napiDisplayName = nullptr; + napi_create_string_utf8(env, displayName.c_str(), NAPI_AUTO_LENGTH, &napiDisplayName); + + NativeValue* nativeSourceFile = reinterpret_cast(napiSourceFile); + NativeValue* nativeDisplayName = reinterpret_cast(napiDisplayName); + NativeValue* argv[] = {nativeSourceFile, nativeDisplayName}; + NativeValue* nativeResult = AsnycCallObjectMethod("rename", argv, ARGC_TWO); + int ret = ERR_ERROR; + if (nativeResult == nullptr) { + HILOG_ERROR("%{public}s call rename with return null.", __func__); + return ret; + } + std::string uriStr = OHOS::AppExecFwk::UnwrapStringFromJS(env, reinterpret_cast(nativeResult)); + if (uriStr.empty()) { + HILOG_ERROR("%{public}s call rename with return empty.", __func__); + return ret; + } else { + ret = NO_ERROR; + } + newFile = Uri(uriStr); + return ret; +} + +std::vector JsFileAccessExtAbility::ListFile(const Uri &sourceFile) +{ + HandleScope handleScope(jsRuntime_); + napi_env env = reinterpret_cast(&jsRuntime_.GetNativeEngine()); + + napi_value napiUri = nullptr; + std::vector vec; + napi_create_string_utf8(env, sourceFile.ToString().c_str(), NAPI_AUTO_LENGTH, &napiUri); + + NativeValue* nativeUri = reinterpret_cast(napiUri); + NativeValue* argv[] = {nativeUri}; + NativeValue* nativeResult = AsnycCallObjectMethod("listFile", argv, ARGC_ONE); + if (nativeResult == nullptr) { + HILOG_ERROR("%{public}s call listFile with return null.", __func__); + return vec; + } + if (UnwrapArrayFileInfoFromJS(env, reinterpret_cast(nativeResult), vec)) { + return vec; + } else { + HILOG_ERROR("%{public}s end with faild.", __func__); + return vec; + } +} + +std::vector JsFileAccessExtAbility::GetRoots() +{ + HandleScope handleScope(jsRuntime_); + napi_env env = reinterpret_cast(&jsRuntime_.GetNativeEngine()); + + std::vector vec; + NativeValue* argv[] = {}; + NativeValue* nativeResult = AsnycCallObjectMethod("getRoots", argv, ARGC_ZERO); + if (nativeResult == nullptr) { + HILOG_ERROR("%{public}s call getRoots with return null.", __func__); + return vec; + } + if (UnwrapArrayDeviceInfoFromJS(env, reinterpret_cast(nativeResult), vec)) { + return vec; + } else { + HILOG_ERROR("%{public}s end with faild.", __func__); + return vec; + } +} } // namespace FileAccessFwk } // namespace OHOS \ No newline at end of file diff --git a/utils/file_access_framework_errno.h b/utils/file_access_framework_errno.h new file mode 100644 index 0000000000000000000000000000000000000000..4f71ccc3b97d7f35d4d10619dc98ae2ad47ff0f7 --- /dev/null +++ b/utils/file_access_framework_errno.h @@ -0,0 +1,41 @@ +/* + * 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 FILE_ACCESS_FRAMEWORK_ERRNO_H +#define FILE_ACCESS_FRAMEWORK_ERRNO_H +#include "errors.h" + +namespace OHOS { +namespace FileAccessFwk { +enum { + MODULE_FILE_ACCESS_FRAMEWORK = 0x01 +}; +constexpr ErrCode BASE_OFFSET = ErrCodeOffset(SUBSYS_FILEMANAGEMENT, MODULE_FILE_ACCESS_FRAMEWORK); +enum { + ERR_OK = 0, + ERR_ERROR = -1, + ERR_IPC_ERROR = BASE_OFFSET, // ipc error + ERR_PERMISSION_DENIED, // no permission + ERR_INVALID_FD, // invalid fd + ERR_INVALID_URI, // invalid uri + ERR_URI_CHECK, // check uri head fail + ERR_CREATE, // create file/dir fail + ERR_DELETE, // delete file/dir fail + ERR_MOVE, // move file/dir fail + ERR_RENAME, // rename file/dir fail + ERR_INVALID_PARAM // invalid parameter +}; +} // namespace FileAccessFwk +} // namespace OHOS +#endif // FILE_ACCESS_FRAMEWORK_ERRNO_H \ No newline at end of file