WebDriver: implement user prompt commands
[WebKit-https.git] / Source / WebDriver / CommandResult.cpp
1 /*
2  * Copyright (C) 2017 Igalia S.L.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "CommandResult.h"
28
29 #include <inspector/InspectorValues.h>
30
31 using namespace Inspector;
32
33 namespace WebDriver {
34
35 // These error codes are specified in JSON-RPC 2.0, Section 5.1.
36 enum ProtocolErrorCode {
37     ParseError = -32700,
38     InvalidRequest = -32600,
39     MethodNotFound = -32601,
40     InvalidParams = -32602,
41     InternalError = -32603,
42     ServerError = -32000
43 };
44
45 CommandResult::CommandResult(RefPtr<InspectorValue>&& result, std::optional<ErrorCode> errorCode)
46     : m_errorCode(errorCode)
47 {
48     if (!m_errorCode) {
49         m_result = WTFMove(result);
50         return;
51     }
52
53     if (!result)
54         return;
55
56     RefPtr<InspectorObject> errorObject;
57     if (!result->asObject(errorObject))
58         return;
59
60     int error;
61     if (!errorObject->getInteger("code", error))
62         return;
63     String errorMessage;
64     if (!errorObject->getString("message", errorMessage))
65         return;
66
67     switch (error) {
68     case ProtocolErrorCode::ParseError:
69     case ProtocolErrorCode::InvalidRequest:
70     case ProtocolErrorCode::MethodNotFound:
71     case ProtocolErrorCode::InvalidParams:
72     case ProtocolErrorCode::InternalError:
73         m_errorCode = ErrorCode::UnknownError;
74         m_errorMessage = errorMessage;
75         break;
76     case ProtocolErrorCode::ServerError: {
77         String errorName;
78         auto position = errorMessage.find(';');
79         if (position != notFound) {
80             errorName = errorMessage.substring(0, position);
81             m_errorMessage = errorMessage.substring(position + 1);
82         } else
83             errorName = errorMessage;
84
85         if (errorName == "WindowNotFound")
86             m_errorCode = ErrorCode::NoSuchWindow;
87         else if (errorName == "FrameNotFound")
88             m_errorCode = ErrorCode::NoSuchFrame;
89         else if (errorName == "NotImplemented")
90             m_errorCode = ErrorCode::UnsupportedOperation;
91         else if (errorName == "JavaScriptError")
92             m_errorCode = ErrorCode::JavascriptError;
93         else if (errorName == "JavaScriptTimeout")
94             m_errorCode = ErrorCode::ScriptTimeout;
95         else if (errorName == "NodeNotFound")
96             m_errorCode = ErrorCode::StaleElementReference;
97         else if (errorName == "MissingParameter" || errorName == "InvalidParameter")
98             m_errorCode = ErrorCode::InvalidArgument;
99         else if (errorName == "InvalidElementState")
100             m_errorCode = ErrorCode::InvalidElementState;
101         else if (errorName == "InvalidSelector")
102             m_errorCode = ErrorCode::InvalidSelector;
103         else if (errorName == "Timeout")
104             m_errorCode = ErrorCode::Timeout;
105         else if (errorName == "NoJavaScriptDialog")
106             m_errorCode = ErrorCode::NoSuchAlert;
107
108         break;
109     }
110     }
111 }
112
113 CommandResult::CommandResult(ErrorCode errorCode, std::optional<String> errorMessage)
114     : m_errorCode(errorCode)
115     , m_errorMessage(errorMessage)
116 {
117 }
118
119 unsigned CommandResult::httpStatusCode() const
120 {
121     if (!m_errorCode)
122         return 200;
123
124     // ยง6.6 Handling Errors.
125     // https://www.w3.org/TR/webdriver/#handling-errors
126     switch (m_errorCode.value()) {
127     case ErrorCode::ElementClickIntercepted:
128     case ErrorCode::ElementNotInteractable:
129     case ErrorCode::InvalidArgument:
130     case ErrorCode::InvalidElementState:
131     case ErrorCode::InvalidSelector:
132     case ErrorCode::NoSuchAlert:
133     case ErrorCode::NoSuchElement:
134     case ErrorCode::NoSuchFrame:
135     case ErrorCode::NoSuchWindow:
136     case ErrorCode::StaleElementReference:
137         return 400;
138     case ErrorCode::InvalidSessionID:
139     case ErrorCode::UnknownCommand:
140         return 404;
141     case ErrorCode::ScriptTimeout:
142     case ErrorCode::Timeout:
143         return 408;
144     case ErrorCode::JavascriptError:
145     case ErrorCode::SessionNotCreated:
146     case ErrorCode::UnknownError:
147     case ErrorCode::UnsupportedOperation:
148         return 500;
149     }
150
151     ASSERT_NOT_REACHED();
152     return 200;
153 }
154
155 String CommandResult::errorString() const
156 {
157     ASSERT(isError());
158
159     switch (m_errorCode.value()) {
160     case ErrorCode::ElementClickIntercepted:
161         return ASCIILiteral("element click intercepted");
162     case ErrorCode::ElementNotInteractable:
163         return ASCIILiteral("element not interactable");
164     case ErrorCode::InvalidArgument:
165         return ASCIILiteral("invalid argument");
166     case ErrorCode::InvalidElementState:
167         return ASCIILiteral("invalid element state");
168     case ErrorCode::InvalidSelector:
169         return ASCIILiteral("invalid selector");
170     case ErrorCode::InvalidSessionID:
171         return ASCIILiteral("invalid session id");
172     case ErrorCode::JavascriptError:
173         return ASCIILiteral("javascript error");
174     case ErrorCode::NoSuchAlert:
175         return ASCIILiteral("no such alert");
176     case ErrorCode::NoSuchElement:
177         return ASCIILiteral("no such element");
178     case ErrorCode::NoSuchFrame:
179         return ASCIILiteral("no such frame");
180     case ErrorCode::NoSuchWindow:
181         return ASCIILiteral("no such window");
182     case ErrorCode::ScriptTimeout:
183         return ASCIILiteral("script timeout");
184     case ErrorCode::SessionNotCreated:
185         return ASCIILiteral("session not created");
186     case ErrorCode::StaleElementReference:
187         return ASCIILiteral("stale element reference");
188     case ErrorCode::Timeout:
189         return ASCIILiteral("timeout");
190     case ErrorCode::UnknownCommand:
191         return ASCIILiteral("unknown command");
192     case ErrorCode::UnknownError:
193         return ASCIILiteral("unknown error");
194     case ErrorCode::UnsupportedOperation:
195         return ASCIILiteral("unsupported operation");
196     }
197
198     ASSERT_NOT_REACHED();
199     return emptyString();
200 }
201
202 } // namespace WebDriver