• 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 
Dispatcher(const EcmaVM * vm,ProtocolChannel * channel)133 Dispatcher::Dispatcher(const EcmaVM *vm, ProtocolChannel *channel)
134 {
135     // profiler
136 #ifdef ECMASCRIPT_SUPPORT_CPUPROFILER
137     auto profiler = std::make_unique<ProfilerImpl>(vm, channel);
138     dispatchers_["Profiler"] =
139         std::make_unique<ProfilerImpl::DispatcherImpl>(channel, std::move(profiler));
140 #endif
141 #ifdef ECMASCRIPT_SUPPORT_HEAPPROFILER
142     auto heapProfiler = std::make_unique<HeapProfilerImpl>(vm, channel);
143     dispatchers_["HeapProfiler"] =
144         std::make_unique<HeapProfilerImpl::DispatcherImpl>(channel, std::move(heapProfiler));
145 #endif
146 #ifdef ECMASCRIPT_SUPPORT_TRACING
147     auto tracing = std::make_unique<TracingImpl>(vm, channel);
148     dispatchers_["Tracing"] =
149         std::make_unique<TracingImpl::DispatcherImpl>(channel, std::move(tracing));
150 #endif
151 
152     // debugger
153     auto runtime = std::make_unique<RuntimeImpl>(vm, channel);
154     auto debugger = std::make_unique<DebuggerImpl>(vm, channel, runtime.get());
155     dispatchers_["Runtime"] =
156         std::make_unique<RuntimeImpl::DispatcherImpl>(channel, std::move(runtime));
157     dispatchers_["Debugger"] =
158         std::make_unique<DebuggerImpl::DispatcherImpl>(channel, std::move(debugger));
159 
160     auto dom = std::make_unique<DomImpl>();
161     dispatchers_["DOM"] =
162         std::make_unique<DomImpl::DispatcherImpl>(channel, std::move(dom));
163 
164     auto css = std::make_unique<CssImpl>();
165     dispatchers_["CSS"] =
166         std::make_unique<CssImpl::DispatcherImpl>(channel, std::move(css));
167 
168     auto overlay = std::make_unique<OverlayImpl>();
169     dispatchers_["Overlay"] =
170         std::make_unique<OverlayImpl::DispatcherImpl>(channel, std::move(overlay));
171 
172     auto target = std::make_unique<TargetImpl>();
173     dispatchers_["Target"] =
174         std::make_unique<TargetImpl::DispatcherImpl>(channel, std::move(target));
175 
176     auto page = std::make_unique<PageImpl>();
177     dispatchers_["Page"] =
178         std::make_unique<PageImpl::DispatcherImpl>(channel, std::move(page));
179 
180     auto animation = std::make_unique<AnimationImpl>();
181     dispatchers_["Animation"] =
182         std::make_unique<AnimationImpl::DispatcherImpl>(channel, std::move(animation));
183 }
184 
Dispatch(const DispatchRequest & request)185 void Dispatcher::Dispatch(const DispatchRequest &request)
186 {
187     if (!request.IsValid()) {
188         LOG_DEBUGGER(ERROR) << "Unknown request";
189         return;
190     }
191     const std::string &domain = request.GetDomain();
192     auto dispatcher = dispatchers_.find(domain);
193     if (dispatcher != dispatchers_.end()) {
194         dispatcher->second->Dispatch(request);
195     } else {
196         if (domain == "Test") {
197             if (request.GetMethod() == "fail") {
198                 LOG_DEBUGGER(FATAL) << "Test fail";
199                 UNREACHABLE();
200             }
201             LOG_DEBUGGER(INFO) << "Test success";
202         } else {
203             LOG_DEBUGGER(ERROR) << "unknown domain: " << domain;
204         }
205     }
206 }
207 
GetJsFrames() const208 std::string Dispatcher::GetJsFrames() const
209 {
210     auto dispatcher = dispatchers_.find("Debugger");
211     if (dispatcher != dispatchers_.end()) {
212         auto debuggerImpl = reinterpret_cast<DebuggerImpl::DispatcherImpl*>(dispatcher->second.get());
213         return debuggerImpl->GetJsFrames();
214     }
215     return "";
216 }
217 }  // namespace panda::ecmascript::tooling
218