1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_TEST_WEBDRIVER_WEBDRIVER_DISPATCH_H_ 6 #define CHROME_TEST_WEBDRIVER_WEBDRIVER_DISPATCH_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "chrome/test/webdriver/commands/response.h" 13 #include "third_party/mongoose/mongoose.h" 14 15 namespace base { 16 class DictionaryValue; 17 class WaitableEvent; 18 } 19 20 namespace webdriver { 21 22 class Command; 23 class HttpResponse; 24 25 namespace mongoose { 26 27 typedef void (HttpCallback)(struct mg_connection* connection, 28 const struct mg_request_info* request_info, 29 void* user_data); 30 31 struct CallbackDetails { 32 CallbackDetails() { 33 } 34 35 CallbackDetails(const std::string &uri_regex, 36 HttpCallback* func, 37 void* user_data) 38 : uri_regex_(uri_regex), 39 func_(func), 40 user_data_(user_data) { 41 } 42 43 std::string uri_regex_; 44 HttpCallback* func_; 45 void* user_data_; 46 }; 47 48 } // namespace mongoose 49 50 namespace internal { 51 52 // Converts a |Response| into a |HttpResponse| to be returned to the client. 53 // This function is exposed for testing. 54 void PrepareHttpResponse(const Response& command_response, 55 HttpResponse* const http_response); 56 57 // Sends a |response| to a WebDriver command back to the client. 58 // |connection| is the communication pipe to the HTTP server and 59 // |request_info| contains any data sent by the user. 60 void SendResponse(struct mg_connection* const connection, 61 const std::string& request_method, 62 const Response& response); 63 64 // Parses the request info and returns whether parsing was successful. If not, 65 // |response| has been modified with the error. 66 bool ParseRequestInfo(const struct mg_request_info* const request_info, 67 struct mg_connection* const connection, 68 std::string* method, 69 std::vector<std::string>* path_segments, 70 base::DictionaryValue** parameters, 71 Response* const response); 72 73 // Allows the bulk of the implementation of |Dispatch| to be moved out of this 74 // header file. Takes ownership of |command|. 75 void DispatchHelper(Command* const command, 76 const std::string& method, 77 Response* const response); 78 79 } // namespace internal 80 81 // Template function for dispatching commands sent to the WebDriver REST 82 // service. |CommandType| must be a subtype of |webdriver::Command|. 83 template<typename CommandType> 84 void Dispatch(struct mg_connection* connection, 85 const struct mg_request_info* request_info, 86 void* user_data) { 87 std::string method; 88 std::vector<std::string> path_segments; 89 base::DictionaryValue* parameters = NULL; 90 Response response; 91 if (internal::ParseRequestInfo(request_info, 92 connection, 93 &method, 94 &path_segments, 95 ¶meters, 96 &response)) { 97 internal::DispatchHelper( 98 new CommandType(path_segments, parameters), 99 method, 100 &response); 101 } 102 internal::SendResponse(connection, 103 request_info->request_method, 104 response); 105 } 106 107 class Dispatcher { 108 public: 109 // Creates a new dispatcher that will register all URL callbacks with the 110 // given |context|. Each callback's pattern will be prefixed with the provided 111 // |root|. 112 explicit Dispatcher(const std::string& root); 113 ~Dispatcher(); 114 115 bool ProcessHttpRequest(struct mg_connection* conn, 116 const struct mg_request_info* request_info); 117 118 // Registers a callback for a WebDriver command using the given URL |pattern|. 119 // The |CommandType| must be a subtype of |webdriver::Command|. 120 template<typename CommandType> 121 void Add(const std::string& pattern); 122 123 // Registers a callback that will shutdown the server. When any HTTP request 124 // is received at this URL |pattern|, the |shutdown_event| will be signaled. 125 void AddShutdown(const std::string& pattern, 126 base::WaitableEvent* shutdown_event); 127 128 // Registers a callback that responds to with this server's status 129 // information, as defined by the WebDriver wire protocol: 130 // http://code.google.com/p/selenium/wiki/JsonWireProtocol#GET_/status. 131 void AddStatus(const std::string& pattern); 132 133 // Registers a callback for the given pattern that will return the current 134 // WebDriver log contents. 135 void AddLog(const std::string& pattern); 136 137 // Registers a callback that will always respond with a 138 // "HTTP/1.1 501 Not Implemented" message. 139 void SetNotImplemented(const std::string& pattern); 140 141 // Registers a callback that will respond for all other requests with a 142 // "HTTP/1.1 403 Forbidden" message. Should be called only after registering 143 // other callbacks. 144 void ForbidAllOtherRequests(); 145 146 private: 147 void AddCallback(const std::string& uri_pattern, 148 webdriver::mongoose::HttpCallback callback, 149 void* user_data); 150 151 std::vector<webdriver::mongoose::CallbackDetails> callbacks_; 152 const std::string url_base_; 153 154 DISALLOW_COPY_AND_ASSIGN(Dispatcher); 155 }; 156 157 158 template <typename CommandType> 159 void Dispatcher::Add(const std::string& pattern) { 160 AddCallback(url_base_ + pattern, &Dispatch<CommandType>, NULL); 161 } 162 163 } // namespace webdriver 164 165 #endif // CHROME_TEST_WEBDRIVER_WEBDRIVER_DISPATCH_H_ 166