1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_TEST_CHROMEDRIVER_SERVER_HTTP_HANDLER_H_
#define CHROME_TEST_CHROMEDRIVER_SERVER_HTTP_HANDLER_H_
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "chrome/test/chromedriver/command.h"
#include "chrome/test/chromedriver/commands.h"
#include "chrome/test/chromedriver/connection_session_map.h"
#include "chrome/test/chromedriver/element_commands.h"
#include "chrome/test/chromedriver/net/sync_websocket_factory.h"
#include "chrome/test/chromedriver/session_commands.h"
#include "chrome/test/chromedriver/session_connection_map.h"
#include "chrome/test/chromedriver/session_thread_map.h"
#include "chrome/test/chromedriver/window_commands.h"
#include "net/http/http_status_code.h"
namespace base {
class SingleThreadTaskRunner;
}
namespace net {
class HttpServerRequestInfo;
class HttpServerResponseInfo;
}
namespace network {
class TransitionalURLLoaderFactoryOwner;
}
class Adb;
class DeviceManager;
class URLRequestContextGetter;
class WrapperURLLoaderFactory;
class HttpServer;
class HttpServerInterface;
enum HttpMethod {
kGet,
kPost,
kDelete,
};
struct CommandMapping {
CommandMapping(HttpMethod method,
const std::string& path_pattern,
const Command& command);
CommandMapping(const CommandMapping& other);
~CommandMapping();
HttpMethod method;
std::string path_pattern;
Command command;
};
extern const char kCreateWebSocketPath[];
extern const char kSendCommandFromWebSocket[];
typedef base::RepeatingCallback<void(
std::unique_ptr<net::HttpServerResponseInfo>)>
HttpResponseSenderFunc;
class HttpHandler {
public:
explicit HttpHandler(const std::string& url_base);
HttpHandler(const base::RepeatingClosure& quit_func,
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner> cmd_task_runner,
const std::string& url_base,
int adb_port);
HttpHandler(const HttpHandler&) = delete;
HttpHandler& operator=(const HttpHandler&) = delete;
~HttpHandler();
void Handle(const net::HttpServerRequestInfo& request,
const HttpResponseSenderFunc& send_response_func);
void OnWebSocketMessage(HttpServerInterface* http_server,
int connection_id,
const std::string& data);
void OnWebSocketRequest(HttpServerInterface* http_server,
int connection_id,
const net::HttpServerRequestInfo& info);
base::WeakPtr<HttpHandler> WeakPtr();
private:
FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, HandleUnknownCommand);
FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, HandleNewSession);
FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, HandleInvalidPost);
FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, HandleUnimplementedCommand);
FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, HandleCommand);
FRIEND_TEST_ALL_PREFIXES(HttpHandlerTest, StandardResponse_ErrorNoMessage);
typedef std::vector<CommandMapping> CommandMap;
friend class HttpServer;
friend class WebSocketMessageTest;
friend class WebSocketRequestTest;
Command WrapToCommand(const char* name,
const SessionCommand& session_command,
bool w3c_standard_command = true);
Command WrapToCommand(const char* name,
const WindowCommand& window_command,
bool w3c_standard_command = true);
Command WrapToCommand(const char* name,
const ElementCommand& element_command,
bool w3c_standard_command = true);
void HandleCommand(const net::HttpServerRequestInfo& request,
const std::string& trimmed_path,
const HttpResponseSenderFunc& send_response_func);
void PrepareResponse(const std::string& trimmed_path,
const HttpResponseSenderFunc& send_response_func,
const Status& status,
std::unique_ptr<base::Value> value,
const std::string& session_id,
bool w3c_compliant);
std::unique_ptr<net::HttpServerResponseInfo> PrepareLegacyResponse(
const std::string& trimmed_path,
const Status& status,
std::unique_ptr<base::Value> value,
const std::string& session_id);
std::unique_ptr<net::HttpServerResponseInfo> PrepareStandardResponse(
const std::string& trimmed_path,
const Status& status,
std::unique_ptr<base::Value> value,
const std::string& session_id);
void OnWebSocketAttachToSessionRequest(
HttpServerInterface* http_server,
int connection_id,
const std::string& session_id,
const net::HttpServerRequestInfo& info);
void OnWebSocketUnboundConnectionRequest(
HttpServerInterface* http_server,
int connection_id,
const net::HttpServerRequestInfo& info);
void SendResponseOverWebSocket(HttpServerInterface* http_server,
int connection_id,
const std::optional<base::Value>& maybe_id,
const Status& status,
std::unique_ptr<base::Value> result,
const std::string& session_id,
bool w3c);
void CloseConnectionOnCommandThread(HttpServerInterface* http_server,
int connection_id);
void SendForwardedResponseOnCommandThread(HttpServerInterface* http_server,
int connection_id,
std::string message);
void OnWebSocketResponseOnCmdThread(HttpServerInterface* http_server,
int connection_id,
const std::string& data);
void OnWebSocketResponseOnSessionThread(HttpServerInterface* http_server,
int connection_id,
const std::string& data);
Command WrapCreateNewSessionCommand(Command command);
void OnNewSessionCreated(const CommandCallback& next_callback,
const Status& status,
std::unique_ptr<base::Value> result,
const std::string& session_id,
bool w3c);
void OnSessionTerminated(std::string session_id);
void OnNewBidiSessionOnCmdThread(HttpServerInterface* http_server,
int connection_id,
const std::optional<base::Value>& maybe_id,
const Status& status,
std::unique_ptr<base::Value> result,
const std::string& session_id,
bool w3c);
void OnClose(HttpServerInterface* http_server, int connection_id);
void SendWebSocketRejectResponse(
base::RepeatingCallback<void(int,
const net::HttpServerResponseInfo&,
const net::NetworkTrafficAnnotationTag&)>
send_http_response,
int connection_id,
net::HttpStatusCode code,
const std::string& msg);
base::ThreadChecker thread_checker_;
base::RepeatingClosure quit_func_;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> cmd_task_runner_;
std::string url_base_;
bool received_shutdown_;
scoped_refptr<URLRequestContextGetter> context_getter_;
std::unique_ptr<network::TransitionalURLLoaderFactoryOwner>
url_loader_factory_owner_;
std::unique_ptr<WrapperURLLoaderFactory> wrapper_url_loader_factory_;
SyncWebSocketFactory socket_factory_;
SessionThreadMap session_thread_map_;
SessionConnectionMap session_connection_map_;
ConnectionSessionMap connection_session_map_;
std::unique_ptr<CommandMap> command_map_;
std::unique_ptr<Adb> adb_;
std::unique_ptr<DeviceManager> device_manager_;
std::map<std::string, Command> static_bidi_command_map_;
std::map<std::string, Command> session_bidi_command_map_;
Command forward_session_command_;
base::WeakPtrFactory<HttpHandler> weak_ptr_factory_{this};
};
namespace internal {
extern const char kNewSessionPathPattern[];
bool MatchesCommand(const std::string& method,
const std::string& path,
const CommandMapping& command,
std::string* session_id,
base::Value::Dict* out_params);
bool IsNewSession(const CommandMapping& command);
Status ParseBidiCommand(const std::string& data, base::Value::Dict& parsed);
base::Value::Dict CreateBidiErrorResponse(
Status status,
std::optional<base::Value> maybe_id = std::nullopt);
} // namespace internal
#endif // CHROME_TEST_CHROMEDRIVER_SERVER_HTTP_HANDLER_H_
|