• 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 #include <sstream>
17 #include "extern_api.h"
18 
19 namespace OHOS::uitest {
20     using namespace std;
21     using namespace nlohmann;
22 
23     /**Get the readable name of the error enum value.*/
GetErrorName(ErrCode code)24     string GetErrorName(ErrCode code)
25     {
26         static const std::map<ErrCode, std::string> names = {
27             {NO_ERROR,       "NO_ERROR"},
28             {INTERNAL_ERROR, "INTERNAL_ERROR"},
29             {WIDGET_LOST,    "WIDGET_LOST"},
30             {USAGE_ERROR,    "USAGE_ERROR"}
31         };
32         const auto find = names.find(code);
33         return (find == names.end()) ? "UNKNOWN" : find->second;
34     }
35 
36     /**Constructor function to register all the ExternAPI creators and functions.*/
ApiRegistration()37     static void __attribute__((constructor)) ApiRegistration()
38     {
39         RegisterExternApIs();
40     }
41 
Get()42     ExternApiServer &ExternApiServer::Get()
43     {
44         static ExternApiServer singleton;
45         return singleton;
46     }
47 
AddHandler(ApiRequstHandler handler)48     void ExternApiServer::AddHandler(ApiRequstHandler handler)
49     {
50         if (handler == nullptr) {
51             return;
52         }
53         handlers_.emplace_back(handler);
54     }
55 
RemoveHandler(ApiRequstHandler handler)56     void ExternApiServer::RemoveHandler(ApiRequstHandler handler)
57     {
58         auto newEnd = remove_if(handlers_.begin(), handlers_.end(), [handler](ApiRequstHandler hdl) {
59             return hdl == handler;
60         });
61         handlers_.erase(newEnd, handlers_.end());
62     }
63 
Call(string_view apiId,json & caller,const json & in,json & out,ApiCallErr & err) const64     void ExternApiServer::Call(string_view apiId, json &caller, const json &in, json &out, ApiCallErr &err) const
65     {
66         string api(apiId);
67         for (auto handler:handlers_) {
68             try {
69                 if (handler(apiId, caller, in, out, err)) {
70                     return;
71                 }
72             } catch (exception &ex) {
73                 // catch possible json-parsing error
74                 err = ApiCallErr(INTERNAL_ERROR, "Exception raised when handling '" + api + "':" + ex.what());
75                 return;
76             }
77         }
78         err = ApiCallErr(INTERNAL_ERROR, "No handler found for extern-api: " + api);
79     }
80 
ApiTransact(string_view funcStr,string_view callerStr,string_view paramsStr)81     string ApiTransact(string_view funcStr, string_view callerStr, string_view paramsStr)
82     {
83         LOG_D("Begin to invoke api: %{public}s, params=%{public}s", funcStr.data(), paramsStr.data());
84         auto error = ApiCallErr(NO_ERROR);
85         auto out = json::array();
86         json returnData;
87         try {
88             auto caller = json::parse(callerStr);
89             auto in = json::parse(paramsStr);
90             ExternApiServer::Get().Call(funcStr, caller, in, out, error);
91             returnData[KEY_UPDATED_CALLER] = caller;
92             returnData[KEY_RESULT_VALUES] = out;
93         } catch (exception &ex) {
94             error = ApiCallErr(INTERNAL_ERROR, string("Convert transaction parameters failed: ") + ex.what());
95         }
96 
97         if (error.code_ != NO_ERROR) {
98             // deliver exception
99             LOG_W("Transact on api '%{public}s' failed, caller='%{public}s', params='%{public}s', error='%{public}s'",
100                   funcStr.data(), callerStr.data(), paramsStr.data(), error.message_.c_str());
101             json exceptionInfo;
102             exceptionInfo[KEY_CODE] = GetErrorName(error.code_);
103             exceptionInfo[KEY_MESSAGE] = error.message_;
104             returnData[KEY_EXCEPTION] = exceptionInfo;
105         }
106         return returnData.dump();
107     }
108 }
109 
110