2015-04-13 12:09:26 -04:00
|
|
|
// Licensed to the Software Freedom Conservancy (SFC) under one
|
|
|
|
|
// or more contributor license agreements. See the NOTICE file
|
|
|
|
|
// distributed with this work for additional information
|
|
|
|
|
// regarding copyright ownership. The SFC licenses this file
|
|
|
|
|
// to you under the Apache License, Version 2.0 (the "License");
|
2013-01-11 22:18:32 +01:00
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
|
|
#include "response.h"
|
2014-09-05 02:00:00 +00:00
|
|
|
#include "errorcodes.h"
|
2013-01-11 22:18:32 +01:00
|
|
|
#include "logging.h"
|
|
|
|
|
|
|
|
|
|
namespace webdriver {
|
|
|
|
|
|
2017-02-22 14:13:25 -08:00
|
|
|
Response::Response(void) : error_(""), value_(Json::Value::null), additional_data_(Json::Value::null) {
|
2013-01-11 22:18:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Response::~Response(void) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Response::Deserialize(const std::string& json) {
|
|
|
|
|
LOG(TRACE) << "Entering Response::Deserialize";
|
|
|
|
|
|
|
|
|
|
Json::Value response_object;
|
2018-03-22 13:55:29 -07:00
|
|
|
std::string parse_errors;
|
|
|
|
|
std::stringstream json_stream;
|
|
|
|
|
json_stream.str(json);
|
|
|
|
|
Json::parseFromStream(Json::CharReaderBuilder(),
|
|
|
|
|
json_stream,
|
|
|
|
|
&response_object,
|
|
|
|
|
&parse_errors);
|
|
|
|
|
|
2017-02-22 14:13:25 -08:00
|
|
|
Json::Value value_object;
|
|
|
|
|
if (response_object.isMember("value")) {
|
|
|
|
|
value_object = response_object["value"];
|
|
|
|
|
if (value_object.isObject() && value_object.isMember("error")) {
|
|
|
|
|
this->error_ = value_object["error"].asString();
|
|
|
|
|
this->value_ = value_object["message"].asString();
|
2019-01-10 17:20:12 -08:00
|
|
|
if (value_object.isMember("data")) {
|
|
|
|
|
this->additional_data_ = value_object["data"];
|
|
|
|
|
}
|
2017-02-22 14:13:25 -08:00
|
|
|
} else {
|
|
|
|
|
this->error_ = "";
|
|
|
|
|
this->value_ = value_object;
|
|
|
|
|
}
|
2014-09-05 02:00:00 +00:00
|
|
|
} else {
|
2017-02-22 14:13:25 -08:00
|
|
|
this->value_ = Json::Value::null;
|
2014-09-05 02:00:00 +00:00
|
|
|
}
|
2013-01-11 22:18:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string Response::Serialize(void) {
|
|
|
|
|
LOG(TRACE) << "Entering Response::Serialize";
|
|
|
|
|
|
|
|
|
|
Json::Value json_object;
|
2017-02-22 14:13:25 -08:00
|
|
|
if (this->error_.size() > 0) {
|
|
|
|
|
Json::Value error_object;
|
|
|
|
|
error_object["error"] = this->error_;
|
|
|
|
|
error_object["message"] = this->value_.asString();
|
|
|
|
|
error_object["stacktrace"] = "";
|
2019-01-10 17:20:12 -08:00
|
|
|
if (!this->value_.isNull() && !this->additional_data_.isNull()) {
|
2017-02-22 14:13:25 -08:00
|
|
|
error_object["data"] = this->additional_data_;
|
|
|
|
|
}
|
|
|
|
|
json_object["value"] = error_object;
|
|
|
|
|
} else {
|
|
|
|
|
json_object["value"] = this->value_;
|
|
|
|
|
}
|
2018-03-22 13:55:29 -07:00
|
|
|
Json::StreamWriterBuilder writer;
|
|
|
|
|
std::string output(Json::writeString(writer, json_object));
|
2013-01-11 22:18:32 +01:00
|
|
|
return output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Response::SetSuccessResponse(const Json::Value& response_value) {
|
|
|
|
|
LOG(TRACE) << "Entering Response::SetSuccessResponse";
|
2017-02-22 14:13:25 -08:00
|
|
|
this->SetResponse("", response_value);
|
2013-01-11 22:18:32 +01:00
|
|
|
}
|
|
|
|
|
|
2017-02-22 14:13:25 -08:00
|
|
|
void Response::SetResponse(const std::string& error,
|
|
|
|
|
const Json::Value& response_value) {
|
2013-01-11 22:18:32 +01:00
|
|
|
LOG(TRACE) << "Entering Response::SetResponse";
|
2017-02-22 14:13:25 -08:00
|
|
|
this->error_ = error;
|
2013-01-11 22:18:32 +01:00
|
|
|
this->value_ = response_value;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-22 14:13:25 -08:00
|
|
|
void Response::SetErrorResponse(const std::string& error,
|
|
|
|
|
const std::string& message) {
|
|
|
|
|
LOG(TRACE) << "Entering Response::SetErrorResponse";
|
|
|
|
|
this->SetResponse(error, message);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-11 22:18:32 +01:00
|
|
|
void Response::SetErrorResponse(const int status_code,
|
|
|
|
|
const std::string& message) {
|
|
|
|
|
LOG(TRACE) << "Entering Response::SetErrorResponse";
|
|
|
|
|
LOG(WARN) << "Error response has status code " << status_code << " and message '" << message << "' message";
|
2017-02-22 14:13:25 -08:00
|
|
|
this->SetErrorResponse(ConvertErrorCode(status_code), message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Response::AddAdditionalData(const std::string& data_name,
|
|
|
|
|
const std::string& data_value) {
|
|
|
|
|
LOG(TRACE) << "Entering Response::AddAdditionalData";
|
|
|
|
|
if (this->additional_data_.isNull()) {
|
|
|
|
|
Json::Value new_data;
|
|
|
|
|
this->additional_data_ = new_data;
|
|
|
|
|
}
|
|
|
|
|
this->additional_data_[data_name] = data_value;
|
2013-01-11 22:18:32 +01:00
|
|
|
}
|
|
|
|
|
|
2017-02-22 14:13:25 -08:00
|
|
|
std::string Response::GetSessionId(void) {
|
|
|
|
|
if (this->error_.size() == 0) {
|
|
|
|
|
return this->value_.get("sessionId", "").asString();
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Response::GetHttpResponseCode(void) {
|
|
|
|
|
int response_code = 200;
|
|
|
|
|
if (this->error_ == ERROR_ELEMENT_CLICK_INTERCEPTED ||
|
|
|
|
|
this->error_ == ERROR_ELEMENT_NOT_SELECTABLE ||
|
|
|
|
|
this->error_ == ERROR_ELEMENT_NOT_INTERACTABLE ||
|
|
|
|
|
this->error_ == ERROR_INSECURE_CERTIFICATE ||
|
|
|
|
|
this->error_ == ERROR_INVALID_ARGUMENT ||
|
|
|
|
|
this->error_ == ERROR_INVALID_COOKIE_DOMAIN ||
|
|
|
|
|
this->error_ == ERROR_INVALID_COORDINATES ||
|
|
|
|
|
this->error_ == ERROR_INVALID_ELEMENT_STATE ||
|
2017-11-26 11:53:30 -08:00
|
|
|
this->error_ == ERROR_INVALID_SELECTOR) {
|
2017-02-22 14:13:25 -08:00
|
|
|
response_code = 400;
|
|
|
|
|
} else if (this->error_ == ERROR_INVALID_SESSION_ID ||
|
|
|
|
|
this->error_ == ERROR_NO_SUCH_COOKIE ||
|
2017-10-18 11:52:05 -07:00
|
|
|
this->error_ == ERROR_NO_SUCH_ALERT ||
|
2017-02-22 14:13:25 -08:00
|
|
|
this->error_ == ERROR_NO_SUCH_ELEMENT ||
|
2017-10-18 11:52:05 -07:00
|
|
|
this->error_ == ERROR_NO_SUCH_FRAME ||
|
|
|
|
|
this->error_ == ERROR_NO_SUCH_WINDOW ||
|
2017-11-26 11:53:30 -08:00
|
|
|
this->error_ == ERROR_STALE_ELEMENT_REFERENCE ||
|
2017-02-22 14:13:25 -08:00
|
|
|
this->error_ == ERROR_UNKNOWN_COMMAND) {
|
|
|
|
|
response_code = 404;
|
|
|
|
|
} else if (this->error_ == ERROR_UNKNOWN_METHOD) {
|
|
|
|
|
response_code = 405;
|
|
|
|
|
} else if (this->error_ == ERROR_JAVASCRIPT_ERROR ||
|
|
|
|
|
this->error_ == ERROR_MOVE_TARGET_OUT_OF_BOUNDS ||
|
2018-08-31 08:10:41 -07:00
|
|
|
this->error_ == ERROR_SCRIPT_TIMEOUT ||
|
2017-02-22 14:13:25 -08:00
|
|
|
this->error_ == ERROR_SESSION_NOT_CREATED ||
|
|
|
|
|
this->error_ == ERROR_UNABLE_TO_SET_COOKIE ||
|
|
|
|
|
this->error_ == ERROR_UNABLE_TO_CAPTURE_SCREEN ||
|
|
|
|
|
this->error_ == ERROR_UNEXPECTED_ALERT_OPEN ||
|
2018-08-31 08:10:41 -07:00
|
|
|
this->error_ == ERROR_UNKNOWN_ERROR ||
|
2019-02-25 11:33:54 -08:00
|
|
|
this->error_ == ERROR_UNSUPPORTED_OPERATION ||
|
2018-08-31 08:10:41 -07:00
|
|
|
this->error_ == ERROR_WEBDRIVER_TIMEOUT) {
|
2017-02-22 14:13:25 -08:00
|
|
|
response_code = 500;
|
|
|
|
|
} else {
|
|
|
|
|
response_code = 200;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return response_code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string Response::ConvertErrorCode(const int error_code) {
|
|
|
|
|
if (error_code == WD_SUCCESS) {
|
|
|
|
|
return "";
|
|
|
|
|
} else if (error_code == ENOSUCHFRAME) {
|
|
|
|
|
return ERROR_NO_SUCH_FRAME;
|
|
|
|
|
} else if (error_code == ENOSUCHWINDOW) {
|
|
|
|
|
return ERROR_NO_SUCH_WINDOW;
|
|
|
|
|
} else if (error_code == EOBSOLETEELEMENT) {
|
|
|
|
|
return ERROR_STALE_ELEMENT_REFERENCE;
|
|
|
|
|
} else if (error_code == EINVALIDSELECTOR) {
|
|
|
|
|
return ERROR_INVALID_SELECTOR;
|
|
|
|
|
} else if (error_code == ENOSUCHALERT) {
|
|
|
|
|
return ERROR_NO_SUCH_ALERT;
|
|
|
|
|
} else if (error_code == EUNEXPECTEDALERTOPEN) {
|
|
|
|
|
return ERROR_UNEXPECTED_ALERT_OPEN;
|
|
|
|
|
} else if (error_code == ENOSUCHCOOKIE) {
|
|
|
|
|
return ERROR_NO_SUCH_COOKIE;
|
|
|
|
|
} else if (error_code == EELEMENTNOTENABLED) {
|
|
|
|
|
return ERROR_INVALID_ELEMENT_STATE;
|
|
|
|
|
} else if (error_code == EELEMENTNOTDISPLAYED) {
|
|
|
|
|
return ERROR_ELEMENT_NOT_INTERACTABLE;
|
|
|
|
|
} else if (error_code == EUNEXPECTEDJSERROR) {
|
|
|
|
|
return ERROR_JAVASCRIPT_ERROR;
|
|
|
|
|
} else if (error_code == EINVALIDCOOKIEDOMAIN) {
|
|
|
|
|
return ERROR_INVALID_COOKIE_DOMAIN;
|
|
|
|
|
} else if (error_code == ESCRIPTTIMEOUT) {
|
|
|
|
|
return ERROR_SCRIPT_TIMEOUT;
|
2018-02-23 13:55:26 -08:00
|
|
|
} else if (error_code == EMOVETARGETOUTOFBOUNDS) {
|
|
|
|
|
return ERROR_MOVE_TARGET_OUT_OF_BOUNDS;
|
2018-05-01 13:02:45 -07:00
|
|
|
} else if (error_code == EINVALIDARGUMENT) {
|
|
|
|
|
return ERROR_INVALID_ARGUMENT;
|
2019-01-22 16:44:28 -08:00
|
|
|
} else if (error_code == ENOSUCHELEMENT) {
|
|
|
|
|
return ERROR_NO_SUCH_ELEMENT;
|
2019-02-25 11:33:54 -08:00
|
|
|
} else if (error_code == EUNSUPPORTEDOPERATION) {
|
|
|
|
|
return ERROR_UNSUPPORTED_OPERATION;
|
2017-02-22 14:13:25 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "";
|
2016-02-18 12:09:31 -08:00
|
|
|
}
|
|
|
|
|
|
2014-09-05 02:00:00 +00:00
|
|
|
// TODO: This method will be rendered unnecessary once all implementations
|
|
|
|
|
// move to string status codes instead of integer status codes. This mapping
|
|
|
|
|
// is not entirely correct; it's merely intended as a stopgap.
|
|
|
|
|
int Response::ConvertStatusToCode(const std::string& status_string) {
|
|
|
|
|
if (status_string == "success") {
|
|
|
|
|
// Special case success to return early.
|
|
|
|
|
return WD_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "element not selectable") {
|
|
|
|
|
return EELEMENTNOTSELECTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "element not visible") {
|
|
|
|
|
return EELEMENTNOTDISPLAYED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "invalid cookie domain") {
|
|
|
|
|
return EINVALIDCOOKIEDOMAIN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "invalid element coordinates") {
|
|
|
|
|
return EINVALIDCOORDINATES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "invalid element state") {
|
|
|
|
|
return EELEMENTNOTENABLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "invalid selector") {
|
|
|
|
|
return EINVALIDSELECTOR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "javascript error") {
|
|
|
|
|
return EUNEXPECTEDJSERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "no such alert") {
|
2015-07-14 14:52:52 -04:00
|
|
|
return ENOSUCHALERT;
|
2014-09-05 02:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "no such element") {
|
|
|
|
|
return ENOSUCHELEMENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "no such frame") {
|
|
|
|
|
return ENOSUCHFRAME;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "no such window") {
|
|
|
|
|
return ENOSUCHWINDOW;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "script timeout") {
|
|
|
|
|
return ESCRIPTTIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "stale element reference") {
|
|
|
|
|
return EOBSOLETEELEMENT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "timeout") {
|
|
|
|
|
return ETIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "unable to set cookie") {
|
|
|
|
|
return EUNABLETOSETCOOKIE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "unexpected alert open") {
|
2015-07-14 14:52:52 -04:00
|
|
|
return EUNEXPECTEDALERTOPEN;
|
2014-09-05 02:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "unknown command") {
|
|
|
|
|
return ENOTIMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status_string == "unknown error") {
|
|
|
|
|
return EUNHANDLEDERROR;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-25 11:33:54 -08:00
|
|
|
if (status_string == "unsupported operation") {
|
|
|
|
|
return EUNSUPPORTEDOPERATION;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-05 02:00:00 +00:00
|
|
|
return EUNHANDLEDERROR;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-11 22:18:32 +01:00
|
|
|
} // namespace webdriver
|