1 /* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef EXTERN_API_H 17 #define EXTERN_API_H 18 19 #include <memory> 20 #include <map> 21 #include <string> 22 #include <set> 23 #include <functional> 24 #include <list> 25 #include "common_defines.h" 26 #include "common_utilities_hpp.h" 27 #include "json.hpp" 28 29 namespace OHOS::uitest { 30 enum ErrCode : uint8_t { 31 NO_ERROR = 0, 32 /**Internal error, not expected to happen.*/ 33 INTERNAL_ERROR = 1, 34 /**Widget that is expected to be exist lost.*/ 35 WIDGET_LOST = 2, 36 USAGE_ERROR = 4, 37 }; 38 39 /**Get the readable name of the error enum value.*/ 40 std::string GetErrorName(ErrCode code); 41 42 /**API invocation error detail wrapper.*/ 43 class ApiCallErr { 44 public: 45 ErrCode code_ = NO_ERROR; 46 std::string message_; 47 48 ApiCallErr() = delete; 49 ApiCallErr(ErrCode ec)50 explicit ApiCallErr(ErrCode ec) : ApiCallErr(ec, "") {} 51 ApiCallErr(ErrCode ec,std::string_view msg)52 ApiCallErr(ErrCode ec, std::string_view msg) 53 { 54 code_ = ec; 55 message_ = "[" + GetErrorName(ec) + "]:" + std::string(msg); 56 } 57 }; 58 59 /**Base type of types that can be serialized into json data and deserialized from json data.*/ 60 class Parcelable { 61 public: 62 /**Serialize this object (value and typeid) into json data.*/ 63 virtual void WriteIntoParcel(nlohmann::json &data) const = 0; 64 65 /**Construct this object from json data.*/ 66 virtual void ReadFromParcel(const nlohmann::json &data) = 0; 67 }; 68 69 class ExternApiBase : public Parcelable { 70 public: 71 // need at least one virtual method to make this class polymorphic 72 virtual ~ExternApiBase() = default; 73 74 virtual TypeId GetTypeId() const = 0; 75 }; 76 77 /** Base class of all the UiTest API classes which may be used externally which must be 78 * parcelable to be transferred to/from external. */ 79 template<TypeId kTypeId> 80 class ExternApi : public ExternApiBase { 81 public: 82 ~ExternApi() override = default; 83 GetTypeId()84 TypeId GetTypeId() const override 85 { 86 return kTypeId; 87 } 88 }; 89 90 /**Prototype of function that handles ExternAPI invocation request. 91 * 92 * @param function the requested function id. 93 * @param callerObj the caller ExternAPI object (serialized). 94 * @param in the incoming serialized parameters (json-array). 95 * @param out the returning serialized objects (json-array). 96 * @param error the error information. 97 * @return true if the request is accepted and handled by the handler, false otherwise. 98 **/ 99 using ApiRequstHandler = bool (*)(std::string_view function, nlohmann::json &callerObj, 100 const nlohmann::json &in, nlohmann::json &out, ApiCallErr &err); 101 102 /** 103 * Server that accepts and handles api invocation request. 104 **/ 105 class ExternApiServer { 106 public: 107 108 /** 109 * Register api invocation handler. 110 **/ 111 void AddHandler(ApiRequstHandler handler); 112 113 /** 114 * Remove api invocation handler. 115 **/ 116 void RemoveHandler(ApiRequstHandler handler); 117 118 /** 119 * Handle api invocation request. 120 * 121 * */ 122 void Call(std::string_view apiId, nlohmann::json &caller, const nlohmann::json &in, 123 nlohmann::json &out, ApiCallErr &err) const; 124 125 /** 126 * Get the singleton instance. 127 * */ 128 static ExternApiServer &Get(); 129 ~ExternApiServer()130 ~ExternApiServer() {} 131 132 private: 133 ExternApiServer() = default; 134 135 std::list<ApiRequstHandler> handlers_; 136 }; 137 138 /** Function used to read out ExternAPI transact parameters, get parameter item value 139 * at the given index in the json data. */ 140 template<typename T> GetItemValueFromJson(const nlohmann::json & data,uint32_t index)141 T GetItemValueFromJson(const nlohmann::json &data, uint32_t index) 142 { 143 DCHECK(index >= 0 && index < data.size()); 144 const nlohmann::json item = data.at(index); 145 const uint32_t typeId = item[KEY_DATA_TYPE]; 146 if constexpr(std::is_same<T, bool>::value) { 147 DCHECK(typeId == TypeId::BOOL); 148 bool value = item[KEY_DATA_VALUE]; 149 return value; 150 } else if constexpr(std::is_integral<T>::value) { 151 DCHECK(typeId == TypeId::INT); 152 T value = item[KEY_DATA_VALUE]; 153 return value; 154 } else if constexpr(std::is_same<T, float>::value) { 155 DCHECK(typeId == TypeId::FLOAT); 156 float value = item[KEY_DATA_VALUE]; 157 return value; 158 } else if constexpr(std::is_same<T, std::string>::value) { 159 DCHECK(typeId == TypeId::STRING); 160 std::string value = item[KEY_DATA_VALUE]; 161 return value; 162 } else if constexpr(std::is_same<T, nlohmann::json>::value) { 163 DCHECK(typeId >= TypeId::BY && typeId <= TypeId::OPTIONS); 164 nlohmann::json value = item[KEY_DATA_VALUE]; 165 return value; 166 } else { 167 static_assert(!std::is_same<T, T>::value, "Unsupported type"); 168 } 169 } 170 171 /**Function used to write ExternAPI transact results, serialize return value and push into json array.*/ 172 template<typename T> PushBackValueItemIntoJson(const T & value,nlohmann::json & out)173 void PushBackValueItemIntoJson(const T &value, nlohmann::json &out) 174 { 175 nlohmann::json item; 176 if constexpr(std::is_same<T, bool>::value) { 177 item[KEY_DATA_TYPE] = TypeId::BOOL; 178 item[KEY_DATA_VALUE] = value; 179 } else if constexpr(std::is_integral<T>::value) { 180 item[KEY_DATA_TYPE] = TypeId::INT; 181 item[KEY_DATA_VALUE] = value; 182 } else if constexpr(std::is_same<T, float>::value) { 183 item[KEY_DATA_TYPE] = TypeId::FLOAT; 184 item[KEY_DATA_VALUE] = value; 185 } else if constexpr(std::is_same<T, std::string>::value) { 186 item[KEY_DATA_TYPE] = TypeId::STRING; 187 item[KEY_DATA_VALUE] = value; 188 } else if constexpr(std::is_base_of<ExternApiBase, T>::value) { 189 item[KEY_DATA_TYPE] = value.GetTypeId(); 190 nlohmann::json objData; 191 value.WriteIntoParcel(objData); 192 item[KEY_DATA_VALUE] = objData; 193 } else { 194 static_assert(!std::is_same<T, T>::value, "Unsupported type"); 195 } 196 out.push_back(item); 197 } 198 199 /** Function serving external api-transaction with json-parcel incoming arguments and outgoing results.*/ 200 std::string ApiTransact(std::string_view func, std::string_view caller, std::string_view params); 201 202 /**Function to register creator and function invoker of all the <b>ExternAPI</b> types.*/ 203 void RegisterExternApIs(); 204 } 205 206 #endif