133eb0b6dSopenharmony_ci/*
233eb0b6dSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
333eb0b6dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
433eb0b6dSopenharmony_ci * you may not use this file except in compliance with the License.
533eb0b6dSopenharmony_ci * You may obtain a copy of the License at
633eb0b6dSopenharmony_ci *
733eb0b6dSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
833eb0b6dSopenharmony_ci *
933eb0b6dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1033eb0b6dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1133eb0b6dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1233eb0b6dSopenharmony_ci * See the License for the specific language governing permissions and
1333eb0b6dSopenharmony_ci * limitations under the License.
1433eb0b6dSopenharmony_ci */
1533eb0b6dSopenharmony_ci
1633eb0b6dSopenharmony_ci#ifndef FOUNDATION_ACE_NAPI_MODULE_MANAGER_NATIVE_MODULE_MANAGER_H
1733eb0b6dSopenharmony_ci#define FOUNDATION_ACE_NAPI_MODULE_MANAGER_NATIVE_MODULE_MANAGER_H
1833eb0b6dSopenharmony_ci
1933eb0b6dSopenharmony_ci#include <cstdint>
2033eb0b6dSopenharmony_ci#include <map>
2133eb0b6dSopenharmony_ci#include <mutex>
2233eb0b6dSopenharmony_ci#include <unordered_map>
2333eb0b6dSopenharmony_ci#include <unordered_set>
2433eb0b6dSopenharmony_ci#include <vector>
2533eb0b6dSopenharmony_ci#include <string>
2633eb0b6dSopenharmony_ci#include <pthread.h>
2733eb0b6dSopenharmony_ci
2833eb0b6dSopenharmony_ci#include "module_load_checker.h"
2933eb0b6dSopenharmony_ci#include "utils/macros.h"
3033eb0b6dSopenharmony_ci#include "interfaces/inner_api/napi/native_node_api.h"
3133eb0b6dSopenharmony_ci
3233eb0b6dSopenharmony_ci#ifdef WINDOWS_PLATFORM
3333eb0b6dSopenharmony_ci#include <winsock2.h>
3433eb0b6dSopenharmony_ci#include <windows.h>
3533eb0b6dSopenharmony_ciusing LIBHANDLE = HMODULE;
3633eb0b6dSopenharmony_ci#define LIBFREE FreeLibrary
3733eb0b6dSopenharmony_ci#define LIBSYM GetProcAddress
3833eb0b6dSopenharmony_ci#else
3933eb0b6dSopenharmony_ci#include <dlfcn.h>
4033eb0b6dSopenharmony_ciusing LIBHANDLE = void*;
4133eb0b6dSopenharmony_ci#define LIBFREE dlclose
4233eb0b6dSopenharmony_ci#define LIBSYM dlsym
4333eb0b6dSopenharmony_ci#endif
4433eb0b6dSopenharmony_ci
4533eb0b6dSopenharmony_ci#define NAPI_PATH_MAX 4096
4633eb0b6dSopenharmony_ci
4733eb0b6dSopenharmony_ciclass NativeValue;
4833eb0b6dSopenharmony_ci
4933eb0b6dSopenharmony_ciclass NativeEngine;
5033eb0b6dSopenharmony_ci
5133eb0b6dSopenharmony_citypedef napi_value (*RegisterCallback)(napi_env, napi_value);
5233eb0b6dSopenharmony_ci
5333eb0b6dSopenharmony_citypedef void (*GetJSCodeCallback)(const char** buf, int* bufLen);
5433eb0b6dSopenharmony_ci
5533eb0b6dSopenharmony_cistruct NativeModule {
5633eb0b6dSopenharmony_ci    const char* name = nullptr;       /* .nm_modname from native c++ register info */
5733eb0b6dSopenharmony_ci    const char* moduleName = nullptr; /* moduleName required or imported */
5833eb0b6dSopenharmony_ci    const char* fileName = nullptr;
5933eb0b6dSopenharmony_ci    const char* systemFilePath = nullptr;
6033eb0b6dSopenharmony_ci    RegisterCallback registerCallback = nullptr;
6133eb0b6dSopenharmony_ci    GetJSCodeCallback getABCCode = nullptr;
6233eb0b6dSopenharmony_ci    GetJSCodeCallback getJSCode = nullptr;
6333eb0b6dSopenharmony_ci    int32_t version = 0;
6433eb0b6dSopenharmony_ci    uint32_t flags = 0;
6533eb0b6dSopenharmony_ci    uint32_t refCount = 0;
6633eb0b6dSopenharmony_ci    NativeModule* next = nullptr;
6733eb0b6dSopenharmony_ci    const char* jsCode = nullptr;
6833eb0b6dSopenharmony_ci    const uint8_t* jsABCCode = nullptr;
6933eb0b6dSopenharmony_ci    int32_t jsCodeLen = 0;
7033eb0b6dSopenharmony_ci    bool moduleLoaded = false;
7133eb0b6dSopenharmony_ci    bool isAppModule = false;
7233eb0b6dSopenharmony_ci    std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr;
7333eb0b6dSopenharmony_ci};
7433eb0b6dSopenharmony_ci
7533eb0b6dSopenharmony_cistruct NativeModuleHeadTailStruct {
7633eb0b6dSopenharmony_ci    NativeModule* headNativeModule = nullptr;
7733eb0b6dSopenharmony_ci    NativeModule* tailNativeModule = nullptr;
7833eb0b6dSopenharmony_ci};
7933eb0b6dSopenharmony_ciclass NAPI_EXPORT NativeModuleManager {
8033eb0b6dSopenharmony_cipublic:
8133eb0b6dSopenharmony_ci    static NativeModuleManager* GetInstance();
8233eb0b6dSopenharmony_ci    static uint64_t Release();
8333eb0b6dSopenharmony_ci
8433eb0b6dSopenharmony_ci    void Register(NativeModule* nativeModule);
8533eb0b6dSopenharmony_ci    void SetAppLibPath(const std::string& moduleName, const std::vector<std::string>& appLibPath,
8633eb0b6dSopenharmony_ci                       const bool& isSystemApp = false);
8733eb0b6dSopenharmony_ci    NativeModule* LoadNativeModule(const char* moduleName, const char* path, bool isAppModule,
8833eb0b6dSopenharmony_ci        std::string& errInfo, bool internal = false, const char* relativePath = "");
8933eb0b6dSopenharmony_ci    void SetNativeEngine(std::string moduleName, NativeEngine* nativeEngine);
9033eb0b6dSopenharmony_ci    bool UnloadNativeModule(const std::string& moduleKey);
9133eb0b6dSopenharmony_ci    std::string GetModuleFileName(const char* moduleName, bool isAppModule);
9233eb0b6dSopenharmony_ci
9333eb0b6dSopenharmony_ci    /**
9433eb0b6dSopenharmony_ci     * @brief Set the path for searching napi dynamic libraries, only for the previewer.
9533eb0b6dSopenharmony_ci     *
9633eb0b6dSopenharmony_ci     * @param previewSearchPath the path for searching napi dynamic libraries
9733eb0b6dSopenharmony_ci     */
9833eb0b6dSopenharmony_ci    void SetPreviewSearchPath(const std::string& previewSearchPath);
9933eb0b6dSopenharmony_ci
10033eb0b6dSopenharmony_ci    /**
10133eb0b6dSopenharmony_ci     * @brief Set the Module Load Checker delegate
10233eb0b6dSopenharmony_ci     *
10333eb0b6dSopenharmony_ci     * @param moduleCheckerDelegate The Module Load Checker delegate
10433eb0b6dSopenharmony_ci     */
10533eb0b6dSopenharmony_ci    void SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate);
10633eb0b6dSopenharmony_ci
10733eb0b6dSopenharmony_ci    inline bool CheckModuleRestricted(const std::string& moduleName)
10833eb0b6dSopenharmony_ci    {
10933eb0b6dSopenharmony_ci        const std::string whiteList[] = {
11033eb0b6dSopenharmony_ci            "worker",
11133eb0b6dSopenharmony_ci            "arkui.uicontext",
11233eb0b6dSopenharmony_ci            "arkui.node",
11333eb0b6dSopenharmony_ci            "arkui.modifier",
11433eb0b6dSopenharmony_ci            "measure",
11533eb0b6dSopenharmony_ci        };
11633eb0b6dSopenharmony_ci
11733eb0b6dSopenharmony_ci        size_t listLen = sizeof(whiteList) / sizeof(whiteList[0]);
11833eb0b6dSopenharmony_ci        for (size_t i = 0; i < listLen; ++i) {
11933eb0b6dSopenharmony_ci            if (moduleName == whiteList[i]) {
12033eb0b6dSopenharmony_ci                return true;
12133eb0b6dSopenharmony_ci            }
12233eb0b6dSopenharmony_ci        }
12333eb0b6dSopenharmony_ci
12433eb0b6dSopenharmony_ci        return false;
12533eb0b6dSopenharmony_ci    }
12633eb0b6dSopenharmony_ci
12733eb0b6dSopenharmony_ciprivate:
12833eb0b6dSopenharmony_ci    NativeModuleManager();
12933eb0b6dSopenharmony_ci    virtual ~NativeModuleManager();
13033eb0b6dSopenharmony_ci
13133eb0b6dSopenharmony_ci    bool GetNativeModulePath(const char* moduleName, const char* path, const char* relativePath,
13233eb0b6dSopenharmony_ci        bool isAppModule, char nativeModulePath[][NAPI_PATH_MAX], int32_t pathLength);
13333eb0b6dSopenharmony_ci    NativeModule* FindNativeModuleByDisk(const char* moduleName, const char* path, const char* relativePath,
13433eb0b6dSopenharmony_ci        bool internal, const bool isAppModule, std::string& errInfo, char nativeModulePath[][NAPI_PATH_MAX],
13533eb0b6dSopenharmony_ci        NativeModule* cacheNativeModule);
13633eb0b6dSopenharmony_ci    NativeModule* FindNativeModuleByCache(const char* moduleName,
13733eb0b6dSopenharmony_ci                                          char nativeModulePath[][NAPI_PATH_MAX],
13833eb0b6dSopenharmony_ci                                          NativeModule*& cacheNativeModule,
13933eb0b6dSopenharmony_ci                                          NativeModuleHeadTailStruct& cacheHeadTailStruct);
14033eb0b6dSopenharmony_ci    bool CheckModuleExist(const char* modulePath);
14133eb0b6dSopenharmony_ci    LIBHANDLE LoadModuleLibrary(std::string& moduleKey, const char* path, const char* pathKey,
14233eb0b6dSopenharmony_ci        const bool isAppModule, std::string& errInfo, uint32_t& errReason);
14333eb0b6dSopenharmony_ci    const uint8_t* GetFileBuffer(const std::string& filePath, const std::string& moduleKey, size_t &len);
14433eb0b6dSopenharmony_ci    bool UnloadModuleLibrary(LIBHANDLE handle);
14533eb0b6dSopenharmony_ci    bool CloseModuleLibrary(LIBHANDLE handle);
14633eb0b6dSopenharmony_ci    void CreateLdNamespace(const std::string moduleName, const char* lib_ld_path, const bool& isSystemApp);
14733eb0b6dSopenharmony_ci    bool IsExistedPath(const char* pathKey) const;
14833eb0b6dSopenharmony_ci    void EmplaceModuleLib(const std::string moduleKey, LIBHANDLE lib);
14933eb0b6dSopenharmony_ci    bool RemoveModuleLib(const std::string moduleKey);
15033eb0b6dSopenharmony_ci    void EmplaceModuleBuffer(const std::string moduleKey, const uint8_t* lib);
15133eb0b6dSopenharmony_ci    bool RemoveModuleBuffer(const std::string moduleKey);
15233eb0b6dSopenharmony_ci    const uint8_t* GetBufferHandle(const std::string& moduleKey) const;
15333eb0b6dSopenharmony_ci    void RegisterByBuffer(const std::string& moduleKey, const uint8_t* abcBuffer, size_t len);
15433eb0b6dSopenharmony_ci    bool CreateTailNativeModule();
15533eb0b6dSopenharmony_ci    bool CreateHeadNativeModule();
15633eb0b6dSopenharmony_ci    LIBHANDLE GetNativeModuleHandle(const std::string& moduleKey) const;
15733eb0b6dSopenharmony_ci    bool RemoveNativeModuleByCache(const std::string& moduleKey);
15833eb0b6dSopenharmony_ci    bool RemoveNativeModule(const std::string& moduleKey);
15933eb0b6dSopenharmony_ci    bool CheckNativeListChanged(const NativeModule* cacheHeadNativeModule, const NativeModule* cacheTailNativeModule);
16033eb0b6dSopenharmony_ci    void MoveApiAllowListCheckerPtr(
16133eb0b6dSopenharmony_ci        std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker, NativeModule* nativeModule);
16233eb0b6dSopenharmony_ci#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
16333eb0b6dSopenharmony_ci    !defined(LINUX_PLATFORM)
16433eb0b6dSopenharmony_ci    void CreateSharedLibsSonames();
16533eb0b6dSopenharmony_ci
16633eb0b6dSopenharmony_ci    char* sharedLibsSonames_ = nullptr;
16733eb0b6dSopenharmony_ci    std::map<std::string, Dl_namespace> nsMap_;
16833eb0b6dSopenharmony_ci#endif
16933eb0b6dSopenharmony_ci
17033eb0b6dSopenharmony_ci    std::mutex nativeModuleListMutex_;
17133eb0b6dSopenharmony_ci    NativeModule* headNativeModule_ = nullptr;
17233eb0b6dSopenharmony_ci    NativeModule* tailNativeModule_ = nullptr;
17333eb0b6dSopenharmony_ci
17433eb0b6dSopenharmony_ci    static NativeModuleManager *instance_;
17533eb0b6dSopenharmony_ci    pthread_mutex_t mutex_;
17633eb0b6dSopenharmony_ci    std::string prefix_;
17733eb0b6dSopenharmony_ci    bool isAppModule_ = false;
17833eb0b6dSopenharmony_ci    std::string loadingModuleName_;
17933eb0b6dSopenharmony_ci
18033eb0b6dSopenharmony_ci    std::mutex nativeEngineListMutex_;
18133eb0b6dSopenharmony_ci    std::map<std::string, NativeEngine*> nativeEngineList_;
18233eb0b6dSopenharmony_ci
18333eb0b6dSopenharmony_ci    mutable std::mutex moduleLibMutex_;
18433eb0b6dSopenharmony_ci    std::map<std::string, const LIBHANDLE> moduleLibMap_;
18533eb0b6dSopenharmony_ci
18633eb0b6dSopenharmony_ci    mutable std::mutex moduleBufMutex_;
18733eb0b6dSopenharmony_ci    std::map<std::string, const uint8_t*> moduleBufMap_;
18833eb0b6dSopenharmony_ci
18933eb0b6dSopenharmony_ci    mutable std::mutex appLibPathMapMutex_;
19033eb0b6dSopenharmony_ci    std::map<std::string, char*> appLibPathMap_;
19133eb0b6dSopenharmony_ci    std::string previewSearchPath_;
19233eb0b6dSopenharmony_ci    std::unique_ptr<ModuleLoadChecker> moduleLoadChecker_ = nullptr;
19333eb0b6dSopenharmony_ci};
19433eb0b6dSopenharmony_ci
19533eb0b6dSopenharmony_ci#endif /* FOUNDATION_ACE_NAPI_MODULE_MANAGER_NATIVE_MODULE_MANAGER_H */
196