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