Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/cpp/webdriver-server/response.cc
2867 views
1
// Licensed to the Software Freedom Conservancy (SFC) under one
2
// or more contributor license agreements. See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership. The SFC licenses this file
5
// to you under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing, software
12
// distributed under the License is distributed on an "AS IS" BASIS,
13
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
// See the License for the specific language governing permissions and
15
// limitations under the License.
16
17
#include "response.h"
18
#include "errorcodes.h"
19
#include "logging.h"
20
21
namespace webdriver {
22
23
Response::Response(void) : error_(""), value_(Json::Value::null), additional_data_(Json::Value::null) {
24
}
25
26
Response::~Response(void) {
27
}
28
29
void Response::Deserialize(const std::string& json) {
30
LOG(TRACE) << "Entering Response::Deserialize";
31
32
Json::Value response_object;
33
std::string parse_errors;
34
std::stringstream json_stream;
35
json_stream.str(json);
36
Json::parseFromStream(Json::CharReaderBuilder(),
37
json_stream,
38
&response_object,
39
&parse_errors);
40
41
Json::Value value_object;
42
if (response_object.isMember("value")) {
43
value_object = response_object["value"];
44
if (value_object.isObject() && value_object.isMember("error")) {
45
this->error_ = value_object["error"].asString();
46
this->value_ = value_object["message"].asString();
47
if (value_object.isMember("data")) {
48
this->additional_data_ = value_object["data"];
49
}
50
} else {
51
this->error_ = "";
52
this->value_ = value_object;
53
}
54
} else {
55
this->value_ = Json::Value::null;
56
}
57
}
58
59
std::string Response::Serialize(void) {
60
LOG(TRACE) << "Entering Response::Serialize";
61
62
Json::Value json_object;
63
if (this->error_.size() > 0) {
64
Json::Value error_object;
65
error_object["error"] = this->error_;
66
error_object["message"] = this->value_.asString();
67
error_object["stacktrace"] = "";
68
if (!this->value_.isNull() && !this->additional_data_.isNull()) {
69
error_object["data"] = this->additional_data_;
70
}
71
json_object["value"] = error_object;
72
} else {
73
json_object["value"] = this->value_;
74
}
75
Json::StreamWriterBuilder writer;
76
std::string output(Json::writeString(writer, json_object));
77
return output;
78
}
79
80
void Response::SetSuccessResponse(const Json::Value& response_value) {
81
LOG(TRACE) << "Entering Response::SetSuccessResponse";
82
this->SetResponse("", response_value);
83
}
84
85
void Response::SetResponse(const std::string& error,
86
const Json::Value& response_value) {
87
LOG(TRACE) << "Entering Response::SetResponse";
88
this->error_ = error;
89
this->value_ = response_value;
90
}
91
92
void Response::SetErrorResponse(const std::string& error,
93
const std::string& message) {
94
LOG(TRACE) << "Entering Response::SetErrorResponse";
95
this->SetResponse(error, message);
96
}
97
98
void Response::SetErrorResponse(const int status_code,
99
const std::string& message) {
100
LOG(TRACE) << "Entering Response::SetErrorResponse";
101
LOG(WARN) << "Error response has status code " << status_code << " and message '" << message << "' message";
102
this->SetErrorResponse(ConvertErrorCode(status_code), message);
103
}
104
105
void Response::AddAdditionalData(const std::string& data_name,
106
const std::string& data_value) {
107
LOG(TRACE) << "Entering Response::AddAdditionalData";
108
if (this->additional_data_.isNull()) {
109
Json::Value new_data;
110
this->additional_data_ = new_data;
111
}
112
this->additional_data_[data_name] = data_value;
113
}
114
115
std::string Response::GetSessionId(void) {
116
if (this->error_.size() == 0) {
117
return this->value_.get("sessionId", "").asString();
118
}
119
return "";
120
}
121
122
int Response::GetHttpResponseCode(void) {
123
int response_code = 200;
124
if (this->error_ == ERROR_ELEMENT_CLICK_INTERCEPTED ||
125
this->error_ == ERROR_ELEMENT_NOT_SELECTABLE ||
126
this->error_ == ERROR_ELEMENT_NOT_INTERACTABLE ||
127
this->error_ == ERROR_INSECURE_CERTIFICATE ||
128
this->error_ == ERROR_INVALID_ARGUMENT ||
129
this->error_ == ERROR_INVALID_COOKIE_DOMAIN ||
130
this->error_ == ERROR_INVALID_COORDINATES ||
131
this->error_ == ERROR_INVALID_ELEMENT_STATE ||
132
this->error_ == ERROR_INVALID_SELECTOR) {
133
response_code = 400;
134
} else if (this->error_ == ERROR_INVALID_SESSION_ID ||
135
this->error_ == ERROR_NO_SUCH_COOKIE ||
136
this->error_ == ERROR_NO_SUCH_ALERT ||
137
this->error_ == ERROR_NO_SUCH_ELEMENT ||
138
this->error_ == ERROR_NO_SUCH_FRAME ||
139
this->error_ == ERROR_NO_SUCH_WINDOW ||
140
this->error_ == ERROR_STALE_ELEMENT_REFERENCE ||
141
this->error_ == ERROR_UNKNOWN_COMMAND) {
142
response_code = 404;
143
} else if (this->error_ == ERROR_UNKNOWN_METHOD) {
144
response_code = 405;
145
} else if (this->error_ == ERROR_JAVASCRIPT_ERROR ||
146
this->error_ == ERROR_MOVE_TARGET_OUT_OF_BOUNDS ||
147
this->error_ == ERROR_SCRIPT_TIMEOUT ||
148
this->error_ == ERROR_SESSION_NOT_CREATED ||
149
this->error_ == ERROR_UNABLE_TO_SET_COOKIE ||
150
this->error_ == ERROR_UNABLE_TO_CAPTURE_SCREEN ||
151
this->error_ == ERROR_UNEXPECTED_ALERT_OPEN ||
152
this->error_ == ERROR_UNKNOWN_ERROR ||
153
this->error_ == ERROR_UNSUPPORTED_OPERATION ||
154
this->error_ == ERROR_WEBDRIVER_TIMEOUT) {
155
response_code = 500;
156
} else {
157
response_code = 200;
158
}
159
160
return response_code;
161
}
162
163
std::string Response::ConvertErrorCode(const int error_code) {
164
if (error_code == WD_SUCCESS) {
165
return "";
166
} else if (error_code == ENOSUCHFRAME) {
167
return ERROR_NO_SUCH_FRAME;
168
} else if (error_code == ENOSUCHWINDOW) {
169
return ERROR_NO_SUCH_WINDOW;
170
} else if (error_code == EOBSOLETEELEMENT) {
171
return ERROR_STALE_ELEMENT_REFERENCE;
172
} else if (error_code == EINVALIDSELECTOR) {
173
return ERROR_INVALID_SELECTOR;
174
} else if (error_code == ENOSUCHALERT) {
175
return ERROR_NO_SUCH_ALERT;
176
} else if (error_code == EUNEXPECTEDALERTOPEN) {
177
return ERROR_UNEXPECTED_ALERT_OPEN;
178
} else if (error_code == ENOSUCHCOOKIE) {
179
return ERROR_NO_SUCH_COOKIE;
180
} else if (error_code == EELEMENTNOTENABLED) {
181
return ERROR_INVALID_ELEMENT_STATE;
182
} else if (error_code == EELEMENTNOTDISPLAYED) {
183
return ERROR_ELEMENT_NOT_INTERACTABLE;
184
} else if (error_code == EUNEXPECTEDJSERROR) {
185
return ERROR_JAVASCRIPT_ERROR;
186
} else if (error_code == EINVALIDCOOKIEDOMAIN) {
187
return ERROR_INVALID_COOKIE_DOMAIN;
188
} else if (error_code == ESCRIPTTIMEOUT) {
189
return ERROR_SCRIPT_TIMEOUT;
190
} else if (error_code == EMOVETARGETOUTOFBOUNDS) {
191
return ERROR_MOVE_TARGET_OUT_OF_BOUNDS;
192
} else if (error_code == EINVALIDARGUMENT) {
193
return ERROR_INVALID_ARGUMENT;
194
} else if (error_code == ENOSUCHELEMENT) {
195
return ERROR_NO_SUCH_ELEMENT;
196
} else if (error_code == EUNSUPPORTEDOPERATION) {
197
return ERROR_UNSUPPORTED_OPERATION;
198
}
199
200
return "";
201
}
202
203
// TODO: This method will be rendered unnecessary once all implementations
204
// move to string status codes instead of integer status codes. This mapping
205
// is not entirely correct; it's merely intended as a stopgap.
206
int Response::ConvertStatusToCode(const std::string& status_string) {
207
if (status_string == "success") {
208
// Special case success to return early.
209
return WD_SUCCESS;
210
}
211
212
if (status_string == "element not selectable") {
213
return EELEMENTNOTSELECTED;
214
}
215
216
if (status_string == "element not visible") {
217
return EELEMENTNOTDISPLAYED;
218
}
219
220
if (status_string == "invalid cookie domain") {
221
return EINVALIDCOOKIEDOMAIN;
222
}
223
224
if (status_string == "invalid element coordinates") {
225
return EINVALIDCOORDINATES;
226
}
227
228
if (status_string == "invalid element state") {
229
return EELEMENTNOTENABLED;
230
}
231
232
if (status_string == "invalid selector") {
233
return EINVALIDSELECTOR;
234
}
235
236
if (status_string == "javascript error") {
237
return EUNEXPECTEDJSERROR;
238
}
239
240
if (status_string == "no such alert") {
241
return ENOSUCHALERT;
242
}
243
244
if (status_string == "no such element") {
245
return ENOSUCHELEMENT;
246
}
247
248
if (status_string == "no such frame") {
249
return ENOSUCHFRAME;
250
}
251
252
if (status_string == "no such window") {
253
return ENOSUCHWINDOW;
254
}
255
256
if (status_string == "script timeout") {
257
return ESCRIPTTIMEOUT;
258
}
259
260
if (status_string == "stale element reference") {
261
return EOBSOLETEELEMENT;
262
}
263
264
if (status_string == "timeout") {
265
return ETIMEOUT;
266
}
267
268
if (status_string == "unable to set cookie") {
269
return EUNABLETOSETCOOKIE;
270
}
271
272
if (status_string == "unexpected alert open") {
273
return EUNEXPECTEDALERTOPEN;
274
}
275
276
if (status_string == "unknown command") {
277
return ENOTIMPLEMENTED;
278
}
279
280
if (status_string == "unknown error") {
281
return EUNHANDLEDERROR;
282
}
283
284
if (status_string == "unsupported operation") {
285
return EUNSUPPORTEDOPERATION;
286
}
287
288
return EUNHANDLEDERROR;
289
}
290
291
} // namespace webdriver
292
293