• 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 #include "agent/runtime_impl.h"
20 #ifdef ECMASCRIPT_SUPPORT_HEAPPROFILER
21 #include "agent/heapprofiler_impl.h"
22 #endif
23 #ifdef ECMASCRIPT_SUPPORT_CPUPROFILER
24 #include "agent/profiler_impl.h"
25 #endif
26 #include "agent/tracing_impl.h"
27 #include "agent/css_impl.h"
28 #include "agent/dom_impl.h"
29 #include "agent/overlay_impl.h"
30 #include "agent/page_impl.h"
31 #include "agent/target_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         code_ = RequestCode::JSON_PARSE_ERROR;
40         LOG_DEBUGGER(ERROR) << "json parse error";
41         return;
42     }
43     if (!json->IsObject()) {
44         code_ = RequestCode::PARAMS_FORMAT_ERROR;
45         LOG_DEBUGGER(ERROR) << "json parse format error";
46         json->ReleaseRoot();
47         return;
48     }
49 
50     Result ret;
51     int32_t callId;
52     ret = json->GetInt("id", &callId);
53     if (ret != Result::SUCCESS) {
54         code_ = RequestCode::PARSE_ID_ERROR;
55         LOG_DEBUGGER(ERROR) << "parse id error";
56         return;
57     }
58     callId_ = callId;
59 
60     std::string wholeMethod;
61     ret = json->GetString("method", &wholeMethod);
62     if (ret != Result::SUCCESS) {
63         code_ = RequestCode::PARSE_METHOD_ERROR;
64         LOG_DEBUGGER(ERROR) << "parse method error";
65         return;
66     }
67     std::string::size_type length = wholeMethod.length();
68     std::string::size_type indexPoint;
69     indexPoint = wholeMethod.find_first_of('.', 0);
70     if (indexPoint == std::string::npos || indexPoint == 0 || indexPoint == length - 1) {
71         code_ = RequestCode::METHOD_FORMAT_ERROR;
72         LOG_DEBUGGER(ERROR) << "method format error: " << wholeMethod;
73         return;
74     }
75     domain_ = wholeMethod.substr(0, indexPoint);
76     method_ = wholeMethod.substr(indexPoint + 1, length);
77 
78     LOG_DEBUGGER(DEBUG) << "id: " << callId_ << ", domain: " << domain_ << ", method: " << method_;
79 
80     std::unique_ptr<PtJson> params;
81     ret = json->GetObject("params", &params);
82     if (ret == Result::NOT_EXIST) {
83         return;
84     }
85     if (ret == Result::TYPE_ERROR) {
86         code_ = RequestCode::PARAMS_FORMAT_ERROR;
87         LOG_DEBUGGER(ERROR) << "params format error";
88         return;
89     }
90     params_ = std::move(params);
91 }
92 
~DispatchRequest()93 DispatchRequest::~DispatchRequest()
94 {
95     params_->ReleaseRoot();
96 }
97 
Create(ResponseCode code,const std::string & msg)98 DispatchResponse DispatchResponse::Create(ResponseCode code, const std::string &msg)
99 {
100     DispatchResponse response;
101     response.code_ = code;
102     response.errorMsg_ = msg;
103     return response;
104 }
105 
Create(std::optional<std::string> error)106 DispatchResponse DispatchResponse::Create(std::optional<std::string> error)
107 {
108     DispatchResponse response;
109     if (error.has_value()) {
110         response.code_ = ResponseCode::NOK;
111         response.errorMsg_ = error.value();
112     }
113     return response;
114 }
115 
Ok()116 DispatchResponse DispatchResponse::Ok()
117 {
118     return DispatchResponse();
119 }
120 
Fail(const std::string & message)121 DispatchResponse DispatchResponse::Fail(const std::string &message)
122 {
123     DispatchResponse response;
124     response.code_ = ResponseCode::NOK;
125     response.errorMsg_ = message;
126     return response;
127 }
128 
SendResponse(const DispatchRequest & request,const DispatchResponse & response,const PtBaseReturns & result)129 void DispatcherBase::SendResponse(const DispatchRequest &request, const DispatchResponse &response,
130                                   const PtBaseReturns &result)
131 {
132     if (channel_ != nullptr) {
133         channel_->SendResponse(request, response, result);
134     }
135 }
136 
Dispatcher(const EcmaVM * vm,ProtocolChannel * channel)137 Dispatcher::Dispatcher(const EcmaVM *vm, ProtocolChannel *channel)
138 {
139     // profiler
140 #ifdef ECMASCRIPT_SUPPORT_CPUPROFILER
141     auto profiler = std::make_unique<ProfilerImpl>(vm, channel);
142     dispatchers_["Profiler"] =
143         std::make_unique<ProfilerImpl::DispatcherImpl>(channel, std::move(profiler));
144 #endif
145 #ifdef ECMASCRIPT_SUPPORT_HEAPPROFILER
146     auto heapProfiler = std::make_unique<HeapProfilerImpl>(vm, channel);
147     dispatchers_["HeapProfiler"] =
148         std::make_unique<HeapProfilerImpl::DispatcherImpl>(channel, std::move(heapProfiler));
149 #endif
150 #ifdef ECMASCRIPT_SUPPORT_TRACING
151     auto tracing = std::make_unique<TracingImpl>(vm, channel);
152     dispatchers_["Tracing"] =
153         std::make_unique<TracingImpl::DispatcherImpl>(channel, std::move(tracing));
154 #endif
155 
156     // debugger
157     auto runtime = std::make_unique<RuntimeImpl>(vm, channel);
158     auto debugger = std::make_unique<DebuggerImpl>(vm, channel, runtime.get());
159     dispatchers_["Runtime"] =
160         std::make_unique<RuntimeImpl::DispatcherImpl>(channel, std::move(runtime));
161     dispatchers_["Debugger"] =
162         std::make_unique<DebuggerImpl::DispatcherImpl>(channel, std::move(debugger));
163 
164     auto dom = std::make_unique<DomImpl>();
165     dispatchers_["DOM"] =
166         std::make_unique<DomImpl::DispatcherImpl>(channel, std::move(dom));
167 
168     auto css = std::make_unique<CssImpl>();
169     dispatchers_["CSS"] =
170         std::make_unique<CssImpl::DispatcherImpl>(channel, std::move(css));
171 
172     auto overlay = std::make_unique<OverlayImpl>();
173     dispatchers_["Overlay"] =
174         std::make_unique<OverlayImpl::DispatcherImpl>(channel, std::move(overlay));
175 
176     auto target = std::make_unique<TargetImpl>();
177     dispatchers_["Target"] =
178         std::make_unique<TargetImpl::DispatcherImpl>(channel, std::move(target));
179 
180     auto page = std::make_unique<PageImpl>();
181     dispatchers_["Page"] =
182         std::make_unique<PageImpl::DispatcherImpl>(channel, std::move(page));
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 }  // namespace panda::ecmascript::tooling
208