• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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