• 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 #include "dispatcher.h"
17 
18 #include "agent/debugger_impl.h"
19 #ifdef ECMASCRIPT_SUPPORT_HEAPPROFILER
20 #include "agent/heapprofiler_impl.h"
21 #endif
22 #ifdef ECMASCRIPT_SUPPORT_CPUPROFILER
23 #include "agent/profiler_impl.h"
24 #endif
25 #include "agent/animation_impl.h"
26 #include "agent/css_impl.h"
27 #include "agent/dom_impl.h"
28 #include "agent/overlay_impl.h"
29 #include "agent/page_impl.h"
30 #include "agent/target_impl.h"
31 #include "agent/tracing_impl.h"
32 #include "protocol_channel.h"
33 
34 namespace panda::ecmascript::tooling {
DispatchRequest(const std::string & message)35 DispatchRequest::DispatchRequest(const std::string &message)
36 {
37     std::unique_ptr<PtJson> json = PtJson::Parse(message);
38     if (json == nullptr) {
39         JsonParseError();
40         return;
41     }
42     if (!json->IsObject()) {
43         JsonFormatError(json);
44         return;
45     }
46 
47     Result ret;
48     int32_t callId;
49     ret = json->GetInt("id", &callId);
50     if (ret != Result::SUCCESS) {
51         code_ = RequestCode::PARSE_ID_ERROR;
52         LOG_DEBUGGER(ERROR) << "parse id error";
53         return;
54     }
55     callId_ = callId;
56 
57     std::string wholeMethod;
58     ret = json->GetString("method", &wholeMethod);
59     if (ret != Result::SUCCESS || wholeMethod.empty()) {
60         code_ = RequestCode::PARSE_METHOD_ERROR;
61         LOG_DEBUGGER(ERROR) << "parse method error";
62         return;
63     }
64     std::string::size_type length = wholeMethod.length();
65     std::string::size_type indexPoint = wholeMethod.find_first_of('.', 0);
66     if (indexPoint == std::string::npos || indexPoint == 0 || indexPoint == length - 1) {
67         code_ = RequestCode::METHOD_FORMAT_ERROR;
68         LOG_DEBUGGER(ERROR) << "method format error: " << wholeMethod;
69         return;
70     }
71     domain_ = wholeMethod.substr(0, indexPoint);
72     method_ = wholeMethod.substr(indexPoint + 1, length);
73 
74     LOG_DEBUGGER(DEBUG) << "id: " << callId_ << ", domain: " << domain_ << ", method: " << method_;
75 
76     std::unique_ptr<PtJson> params;
77     ret = json->GetObject("params", &params);
78     if (ret == Result::NOT_EXIST) {
79         return;
80     }
81     if (ret == Result::TYPE_ERROR) {
82         code_ = RequestCode::PARAMS_FORMAT_ERROR;
83         LOG_DEBUGGER(ERROR) << "params format error";
84         return;
85     }
86     params_ = std::move(params);
87 }
88 
~DispatchRequest()89 DispatchRequest::~DispatchRequest()
90 {
91     params_->ReleaseRoot();
92 }
93 
Create(ResponseCode code,const std::string & msg)94 DispatchResponse DispatchResponse::Create(ResponseCode code, const std::string &msg)
95 {
96     DispatchResponse response;
97     response.code_ = code;
98     response.errorMsg_ = msg;
99     return response;
100 }
101 
Create(std::optional<std::string> error)102 DispatchResponse DispatchResponse::Create(std::optional<std::string> error)
103 {
104     DispatchResponse response;
105     if (error.has_value()) {
106         response.code_ = ResponseCode::NOK;
107         response.errorMsg_ = error.value();
108     }
109     return response;
110 }
111 
Ok()112 DispatchResponse DispatchResponse::Ok()
113 {
114     return DispatchResponse();
115 }
116 
Fail(const std::string & message)117 DispatchResponse DispatchResponse::Fail(const std::string &message)
118 {
119     DispatchResponse response;
120     response.code_ = ResponseCode::NOK;
121     response.errorMsg_ = message;
122     return response;
123 }
124 
SendResponse(const DispatchRequest & request,const DispatchResponse & response,const PtBaseReturns & result)125 void DispatcherBase::SendResponse(const DispatchRequest &request, const DispatchResponse &response,
126                                   const PtBaseReturns &result)
127 {
128     if (channel_ != nullptr) {
129         channel_->SendResponse(request, response, result);
130     }
131 }
132 
ReturnsValueToString(const int32_t callId,const std::unique_ptr<PtJson> resultObj)133 std::string DispatcherBase::ReturnsValueToString(const int32_t callId, const std::unique_ptr<PtJson> resultObj)
134 {
135     std::unique_ptr<PtJson> ptJson = PtJson::CreateObject();
136     ptJson->Add("id", callId);
137     ptJson->Add("result", resultObj);
138     std::string str = ptJson->Stringify();
139     if (str.empty()) {
140         LOG_DEBUGGER(ERROR) << "Dispatcher::ReturnsValueToString: json stringify error";
141         return "";
142     }
143     ptJson->ReleaseRoot();
144     return str;
145 }
146 
DispatchResponseToJson(const DispatchResponse & response) const147 std::unique_ptr<PtJson> DispatcherBase::DispatchResponseToJson(const DispatchResponse &response) const
148 {
149     std::unique_ptr<PtJson> result = PtJson::CreateObject();
150 
151     if (!response.IsOk()) {
152         result->Add("code", static_cast<int32_t>(response.GetError()));
153         result->Add("message", response.GetMessage().c_str());
154     }
155 
156     return result;
157 }
158 
Dispatcher(const EcmaVM * vm,ProtocolChannel * channel)159 Dispatcher::Dispatcher(const EcmaVM *vm, ProtocolChannel *channel)
160 {
161     // profiler
162 #ifdef ECMASCRIPT_SUPPORT_CPUPROFILER
163     auto profiler = std::make_unique<ProfilerImpl>(vm, channel);
164     dispatchers_["Profiler"] =
165         std::make_unique<ProfilerImpl::DispatcherImpl>(channel, std::move(profiler));
166 #endif
167 #ifdef ECMASCRIPT_SUPPORT_HEAPPROFILER
168     auto heapProfiler = std::make_unique<HeapProfilerImpl>(vm, channel);
169     dispatchers_["HeapProfiler"] =
170         std::make_unique<HeapProfilerImpl::DispatcherImpl>(channel, std::move(heapProfiler));
171 #endif
172 #ifdef ECMASCRIPT_SUPPORT_TRACING
173     auto tracing = std::make_unique<TracingImpl>(vm, channel);
174     dispatchers_["Tracing"] =
175         std::make_unique<TracingImpl::DispatcherImpl>(channel, std::move(tracing));
176 #endif
177 
178     // debugger
179     auto runtime = std::make_unique<RuntimeImpl>(vm, channel);
180     auto debugger = std::make_unique<DebuggerImpl>(vm, channel, runtime.get());
181     dispatchers_["Runtime"] =
182         std::make_unique<RuntimeImpl::DispatcherImpl>(channel, std::move(runtime));
183     dispatchers_["Debugger"] =
184         std::make_unique<DebuggerImpl::DispatcherImpl>(channel, std::move(debugger));
185 
186     auto dom = std::make_unique<DomImpl>();
187     dispatchers_["DOM"] =
188         std::make_unique<DomImpl::DispatcherImpl>(channel, std::move(dom));
189 
190     auto css = std::make_unique<CssImpl>();
191     dispatchers_["CSS"] =
192         std::make_unique<CssImpl::DispatcherImpl>(channel, std::move(css));
193 
194     auto overlay = std::make_unique<OverlayImpl>();
195     dispatchers_["Overlay"] =
196         std::make_unique<OverlayImpl::DispatcherImpl>(channel, std::move(overlay));
197 
198     auto target = std::make_unique<TargetImpl>();
199     dispatchers_["Target"] =
200         std::make_unique<TargetImpl::DispatcherImpl>(channel, std::move(target));
201 
202     auto page = std::make_unique<PageImpl>();
203     dispatchers_["Page"] =
204         std::make_unique<PageImpl::DispatcherImpl>(channel, std::move(page));
205 
206     auto animation = std::make_unique<AnimationImpl>();
207     dispatchers_["Animation"] =
208         std::make_unique<AnimationImpl::DispatcherImpl>(channel, std::move(animation));
209 }
210 
Dispatch(const DispatchRequest & request)211 void Dispatcher::Dispatch(const DispatchRequest &request)
212 {
213     if (!request.IsValid()) {
214         LOG_DEBUGGER(ERROR) << "Unknown request";
215         return;
216     }
217     const std::string &domain = request.GetDomain();
218     auto dispatcher = dispatchers_.find(domain);
219     if (dispatcher != dispatchers_.end()) {
220         dispatcher->second->Dispatch(request);
221     } else {
222         if (domain == "Test") {
223             if (request.GetMethod() == "fail") {
224                 LOG_DEBUGGER(FATAL) << "Test fail";
225                 UNREACHABLE();
226             }
227             LOG_DEBUGGER(INFO) << "Test success";
228         } else {
229             LOG_DEBUGGER(ERROR) << "unknown domain: " << domain;
230         }
231     }
232 }
233 
OperateDebugMessage(const char * message) const234 std::string Dispatcher::OperateDebugMessage(const char* message) const
235 {
236     DispatchRequest request(message);
237     const std::string &domain = request.GetDomain();
238     auto dispatcher = dispatchers_.find(domain);
239     if (dispatcher == dispatchers_.end()) {
240         LOG_DEBUGGER(ERROR) << "unknown domain: " << domain;
241         return "";
242     }
243     std::string method = request.GetMethod();
244     MethodType methodType = GetMethodType(method);
245     switch (methodType) {
246         case MethodType::SAVE_ALL_POSSIBLE_BREAKPOINTS:
247             return SaveAllBreakpoints(request, dispatcher->second.get());
248         case MethodType::REMOVE_BREAKPOINTS_BY_URL:
249             return RemoveBreakpoint(request, dispatcher->second.get());
250         case MethodType::GET_POSSIBLE_AND_SET_BREAKPOINT_BY_URL:
251             return SetBreakpoint(request, dispatcher->second.get());
252         case MethodType::GET_PROPERTIES:
253             return GetProperties(request, dispatcher->second.get());
254         case MethodType::CALL_FUNCTION_ON:
255             return CallFunctionOn(request, dispatcher->second.get());
256         case MethodType::EVALUATE_ON_CALL_FRAME:
257             return EvaluateOnCallFrame(request, dispatcher->second.get());
258         default:
259             LOG_DEBUGGER(ERROR) << "unknown method: " << method;
260             return "";
261     }
262     return "";
263 }
264 
GetMethodType(const std::string & method) const265 Dispatcher::MethodType Dispatcher::GetMethodType(const std::string &method) const
266 {
267     static const std::unordered_map<std::string, MethodType> methodMap = {
268         {"saveAllPossibleBreakpoints", MethodType::SAVE_ALL_POSSIBLE_BREAKPOINTS},
269         {"removeBreakpointsByUrl", MethodType::REMOVE_BREAKPOINTS_BY_URL},
270         {"getPossibleAndSetBreakpointByUrl", MethodType::GET_POSSIBLE_AND_SET_BREAKPOINT_BY_URL},
271         {"getProperties", MethodType::GET_PROPERTIES},
272         {"callFunctionOn", MethodType::CALL_FUNCTION_ON},
273         {"evaluateOnCallFrame", MethodType::EVALUATE_ON_CALL_FRAME}
274     };
275     auto it = methodMap.find(method);
276     if (it == methodMap.end()) {
277         LOG_DEBUGGER(ERROR) << "unknown method: " << method;
278         return MethodType::UNKNOWN;
279     }
280     return it->second;
281 }
282 
GetJsFrames() const283 std::string Dispatcher::GetJsFrames() const
284 {
285     auto dispatcher = dispatchers_.find("Debugger");
286     if (dispatcher != dispatchers_.end()) {
287         auto debuggerImpl = reinterpret_cast<DebuggerImpl::DispatcherImpl*>(dispatcher->second.get());
288         return debuggerImpl->GetJsFrames();
289     }
290     return "";
291 }
292 
SaveAllBreakpoints(const DispatchRequest & request,DispatcherBase * dispatcher) const293 std::string Dispatcher::SaveAllBreakpoints(const DispatchRequest &request, DispatcherBase *dispatcher) const
294 {
295     auto debuggerImpl = reinterpret_cast<DebuggerImpl::DispatcherImpl*>(dispatcher);
296     std::unique_ptr<SaveAllPossibleBreakpointsParams> params =
297         SaveAllPossibleBreakpointsParams::Create(request.GetParams());
298     return debuggerImpl->SaveAllPossibleBreakpoints(request.GetCallId(), std::move(params));
299 }
300 
RemoveBreakpoint(const DispatchRequest & request,DispatcherBase * dispatcher) const301 std::string Dispatcher::RemoveBreakpoint(const DispatchRequest &request, DispatcherBase *dispatcher) const
302 {
303     auto debuggerImpl = reinterpret_cast<DebuggerImpl::DispatcherImpl*>(dispatcher);
304     std::unique_ptr<RemoveBreakpointsByUrlParams> params =
305         RemoveBreakpointsByUrlParams::Create(request.GetParams());
306     return debuggerImpl->RemoveBreakpointsByUrl(request.GetCallId(), std::move(params));
307 }
308 
SetBreakpoint(const DispatchRequest & request,DispatcherBase * dispatcher) const309 std::string Dispatcher::SetBreakpoint(const DispatchRequest &request, DispatcherBase *dispatcher) const
310 {
311     auto debuggerImpl = reinterpret_cast<DebuggerImpl::DispatcherImpl*>(dispatcher);
312     std::unique_ptr<GetPossibleAndSetBreakpointParams> params =
313         GetPossibleAndSetBreakpointParams::Create(request.GetParams());
314     return debuggerImpl->GetPossibleAndSetBreakpointByUrl(request.GetCallId(), std::move(params));
315 }
316 
GetProperties(const DispatchRequest & request,DispatcherBase * dispatcher) const317 std::string Dispatcher::GetProperties(const DispatchRequest &request, DispatcherBase *dispatcher) const
318 {
319     auto runtimeImpl = reinterpret_cast<RuntimeImpl::DispatcherImpl*>(dispatcher);
320     std::unique_ptr<GetPropertiesParams> params = GetPropertiesParams::Create(request.GetParams());
321     return runtimeImpl->GetProperties(request.GetCallId(), std::move(params));
322 }
323 
CallFunctionOn(const DispatchRequest & request,DispatcherBase * dispatcher) const324 std::string Dispatcher::CallFunctionOn(const DispatchRequest &request, DispatcherBase *dispatcher) const
325 {
326     auto debuggerImpl = reinterpret_cast<DebuggerImpl::DispatcherImpl*>(dispatcher);
327     std::unique_ptr<CallFunctionOnParams> params = CallFunctionOnParams::Create(request.GetParams());
328     return debuggerImpl->CallFunctionOn(request.GetCallId(), std::move(params));
329 }
330 
EvaluateOnCallFrame(const DispatchRequest & request,DispatcherBase * dispatcher) const331 std::string Dispatcher::EvaluateOnCallFrame(const DispatchRequest &request, DispatcherBase *dispatcher) const
332 {
333     auto debuggerImpl = reinterpret_cast<DebuggerImpl::DispatcherImpl*>(dispatcher);
334     std::unique_ptr<EvaluateOnCallFrameParams> params = EvaluateOnCallFrameParams::Create(request.GetParams());
335     return debuggerImpl->EvaluateOnCallFrame(request.GetCallId(), std::move(params));
336 }
337 }  // namespace panda::ecmascript::tooling
338