1 /* 2 * Copyright (c) 2021 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 ECMASCRIPT_TOOLING_DISPATCHER_H 17 #define ECMASCRIPT_TOOLING_DISPATCHER_H 18 19 #include <map> 20 #include <memory> 21 #include <set> 22 23 #include "tooling/dynamic/base/pt_returns.h" 24 25 #include "ecmascript/debugger/js_debugger_interface.h" 26 #include "ecmascript/napi/include/jsnapi.h" 27 #include "libpandabase/macros.h" 28 29 namespace panda::ecmascript::tooling { 30 class ProtocolChannel; 31 class PtBaseReturns; 32 class PtBaseEvents; 33 34 enum class RequestCode : uint8_t { 35 OK = 0, 36 NOK, 37 38 // Json parse errors 39 JSON_PARSE_ERROR, 40 PARSE_ID_ERROR, 41 ID_FORMAT_ERROR, 42 PARSE_METHOD_ERROR, 43 METHOD_FORMAT_ERROR, 44 PARSE_PARAMS_ERROR, 45 PARAMS_FORMAT_ERROR 46 }; 47 48 enum class ResponseCode : uint8_t { OK, NOK }; 49 50 class DispatchRequest { 51 public: 52 explicit DispatchRequest(const std::string &message); 53 ~DispatchRequest(); 54 IsValid()55 bool IsValid() const 56 { 57 return code_ == RequestCode::OK; 58 } GetCallId()59 int32_t GetCallId() const 60 { 61 return callId_; 62 } GetParams()63 const PtJson &GetParams() const 64 { 65 return *params_; 66 } GetDomain()67 const std::string &GetDomain() const 68 { 69 return domain_; 70 } GetMethod()71 const std::string &GetMethod() const 72 { 73 return method_; 74 } 75 76 private: 77 int32_t callId_ = -1; 78 std::string domain_ {}; 79 std::string method_ {}; 80 std::unique_ptr<PtJson> params_ = std::make_unique<PtJson>(); 81 RequestCode code_ {RequestCode::OK}; 82 std::string errorMsg_ {}; JsonParseError()83 void JsonParseError() 84 { 85 code_ = RequestCode::JSON_PARSE_ERROR; 86 LOG_DEBUGGER(ERROR) << "json parse error"; 87 } JsonFormatError(std::unique_ptr<PtJson> & json)88 void JsonFormatError(std::unique_ptr<PtJson>& json) 89 { 90 code_ = RequestCode::PARAMS_FORMAT_ERROR; 91 LOG_DEBUGGER(ERROR) << "json parse format error"; 92 json->ReleaseRoot(); 93 } 94 }; 95 96 class DispatchResponse { 97 public: IsOk()98 bool IsOk() const 99 { 100 return code_ == ResponseCode::OK; 101 } 102 GetError()103 ResponseCode GetError() const 104 { 105 return code_; 106 } 107 GetMessage()108 const std::string &GetMessage() const 109 { 110 return errorMsg_; 111 } 112 113 static DispatchResponse Create(ResponseCode code, const std::string &msg = ""); 114 static DispatchResponse Create(std::optional<std::string> error); 115 static DispatchResponse Ok(); 116 static DispatchResponse Fail(const std::string &message); 117 118 ~DispatchResponse() = default; 119 120 private: 121 DispatchResponse() = default; 122 123 ResponseCode code_ {ResponseCode::OK}; 124 std::string errorMsg_ {}; 125 }; 126 127 class DispatcherBase { 128 public: DispatcherBase(ProtocolChannel * channel)129 explicit DispatcherBase(ProtocolChannel *channel) : channel_(channel) {} ~DispatcherBase()130 virtual ~DispatcherBase() 131 { 132 channel_ = nullptr; 133 }; 134 virtual void Dispatch(const DispatchRequest &request) = 0; 135 136 protected: 137 void SendResponse(const DispatchRequest &request, const DispatchResponse &response, 138 const PtBaseReturns &result = PtBaseReturns()); 139 std::string ReturnsValueToString(const int32_t callId, const std::unique_ptr<PtJson> resultObj); 140 std::unique_ptr<PtJson> DispatchResponseToJson(const DispatchResponse &response) const; 141 142 private: 143 ProtocolChannel *channel_ {nullptr}; 144 145 NO_COPY_SEMANTIC(DispatcherBase); 146 NO_MOVE_SEMANTIC(DispatcherBase); 147 }; 148 149 class Dispatcher { 150 public: 151 explicit Dispatcher(const EcmaVM *vm, ProtocolChannel *channel); 152 ~Dispatcher() = default; 153 void Dispatch(const DispatchRequest &request); 154 std::string GetJsFrames() const; 155 std::string OperateDebugMessage(const char* message) const; 156 157 enum class MethodType { 158 SAVE_ALL_POSSIBLE_BREAKPOINTS, 159 REMOVE_BREAKPOINTS_BY_URL, 160 GET_POSSIBLE_AND_SET_BREAKPOINT_BY_URL, 161 GET_PROPERTIES, 162 CALL_FUNCTION_ON, 163 EVALUATE_ON_CALL_FRAME, 164 UNKNOWN 165 }; 166 MethodType GetMethodType(const std::string &method) const; 167 168 private: 169 std::string SaveAllBreakpoints(const DispatchRequest &request, DispatcherBase *dispatcher) const; 170 std::string RemoveBreakpoint(const DispatchRequest &request, DispatcherBase *dispatcher) const; 171 std::string SetBreakpoint(const DispatchRequest &request, DispatcherBase *dispatcher) const; 172 std::string GetProperties(const DispatchRequest &request, DispatcherBase *dispatcher) const; 173 std::string CallFunctionOn(const DispatchRequest &request, DispatcherBase *dispatcher) const; 174 std::string EvaluateOnCallFrame(const DispatchRequest &request, DispatcherBase *dispatcher) const; 175 176 std::unordered_map<std::string, std::unique_ptr<DispatcherBase>> dispatchers_ {}; 177 178 NO_COPY_SEMANTIC(Dispatcher); 179 NO_MOVE_SEMANTIC(Dispatcher); 180 }; 181 } // namespace panda::ecmascript::tooling 182 #endif 183