Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/test/chromedriver/server/http_handler.h" | 5 #include "chrome/test/chromedriver/server/http_handler.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | |
| 8 #include "base/callback.h" | |
| 7 #include "base/json/json_reader.h" | 9 #include "base/json/json_reader.h" |
| 8 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
| 9 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/message_loop.h" | |
| 13 #include "base/message_loop/message_loop_proxy.h" | |
| 10 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
| 11 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 12 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 17 #include "base/sys_info.h" | |
| 13 #include "base/values.h" | 18 #include "base/values.h" |
| 19 #include "chrome/test/chromedriver/alert_commands.h" | |
| 20 #include "chrome/test/chromedriver/chrome/adb_impl.h" | |
| 21 #include "chrome/test/chromedriver/chrome/device_manager.h" | |
| 14 #include "chrome/test/chromedriver/chrome/log.h" | 22 #include "chrome/test/chromedriver/chrome/log.h" |
| 15 #include "chrome/test/chromedriver/chrome/status.h" | 23 #include "chrome/test/chromedriver/chrome/status.h" |
| 16 #include "chrome/test/chromedriver/command_executor.h" | 24 #include "chrome/test/chromedriver/chrome/version.h" |
| 17 #include "chrome/test/chromedriver/command_names.h" | 25 #include "chrome/test/chromedriver/commands.h" |
| 26 #include "chrome/test/chromedriver/element_commands.h" | |
| 27 #include "chrome/test/chromedriver/net/url_request_context_getter.h" | |
| 18 #include "chrome/test/chromedriver/server/http_response.h" | 28 #include "chrome/test/chromedriver/server/http_response.h" |
| 29 #include "chrome/test/chromedriver/session.h" | |
| 30 #include "chrome/test/chromedriver/session_commands.h" | |
| 31 #include "chrome/test/chromedriver/session_map.h" | |
| 19 #include "chrome/test/chromedriver/util.h" | 32 #include "chrome/test/chromedriver/util.h" |
| 33 #include "chrome/test/chromedriver/window_commands.h" | |
| 34 | |
| 35 #if defined(OS_MACOSX) | |
| 36 #include "base/mac/scoped_nsautorelease_pool.h" | |
| 37 #endif | |
| 20 | 38 |
| 21 namespace { | 39 namespace { |
| 22 | 40 |
| 41 const char kLocalStorage[] = "localStorage"; | |
| 42 const char kSessionStorage[] = "sessionStorage"; | |
| 23 const char kShutdownPath[] = "shutdown"; | 43 const char kShutdownPath[] = "shutdown"; |
| 24 | 44 |
| 45 Status UnimplementedCommand( | |
| 46 const base::DictionaryValue& params, | |
| 47 const std::string& session_id, | |
| 48 scoped_ptr<base::Value>* value, | |
| 49 std::string* out_session_id) { | |
| 50 return Status(kUnknownCommand); | |
| 51 } | |
| 52 | |
| 25 } // namespace | 53 } // namespace |
| 26 | 54 |
| 27 HttpRequest::HttpRequest(HttpMethod method, | 55 HttpRequest::HttpRequest(HttpMethod method, |
| 28 const std::string& path, | 56 const std::string& path, |
| 29 const std::string& body) | 57 const std::string& body) |
| 30 : method(method), path(path), body(body) {} | 58 : method(method), path(path), body(body) {} |
| 31 | 59 |
| 32 HttpRequest::~HttpRequest() {} | 60 HttpRequest::~HttpRequest() {} |
| 33 | 61 |
| 62 CommandMapping::CommandMapping() {} | |
|
chrisgao (Use stgao instead)
2013/07/02 01:31:40
remove
chrisgao (Use stgao instead)
2013/07/02 18:13:04
Done.
| |
| 63 | |
| 34 CommandMapping::CommandMapping(HttpMethod method, | 64 CommandMapping::CommandMapping(HttpMethod method, |
| 35 const std::string& path_pattern, | 65 const std::string& path_pattern, |
| 36 const std::string& name) | 66 const Command& command) |
| 37 : method(method), path_pattern(path_pattern), name(name) {} | 67 : method(method), path_pattern(path_pattern), command(command) {} |
| 38 | 68 |
| 39 CommandMapping::~CommandMapping() {} | 69 CommandMapping::~CommandMapping() {} |
| 40 | 70 |
| 41 // static | 71 HttpHandler::HttpHandler(Log* log, const std::string& url_base) |
| 42 scoped_ptr<HttpHandler::CommandMap> HttpHandler::CreateCommandMap() { | 72 : log_(log), |
| 73 io_thread_("ChromeDriver IO"), | |
| 74 url_base_(url_base) { | |
| 75 } | |
| 76 | |
| 77 HttpHandler::~HttpHandler() {} | |
| 78 | |
| 79 void HttpHandler::Init() { | |
| 80 #if defined(OS_MACOSX) | |
| 81 base::mac::ScopedNSAutoreleasePool autorelease_pool; | |
| 82 #endif | |
| 83 base::Thread::Options options(base::MessageLoop::TYPE_IO, 0); | |
| 84 CHECK(io_thread_.StartWithOptions(options)); | |
| 85 context_getter_ = new URLRequestContextGetter( | |
| 86 io_thread_.message_loop_proxy()); | |
| 87 socket_factory_ = CreateSyncWebSocketFactory(context_getter_.get()); | |
| 88 adb_.reset(new AdbImpl(io_thread_.message_loop_proxy(), log_)); | |
| 89 device_manager_.reset(new DeviceManager(adb_.get())); | |
| 90 | |
| 43 CommandMapping commands[] = { | 91 CommandMapping commands[] = { |
| 44 CommandMapping(kPost, "session", CommandNames::kNewSession), | 92 CommandMapping(kPost, internal::kNewSessionPathPattern, |
| 93 base::Bind(&ExecuteNewSession, | |
| 94 NewSessionParams(log_, &session_map_, | |
| 95 context_getter_, socket_factory_, | |
| 96 device_manager_.get()))), | |
| 45 CommandMapping(kGet, "session/:sessionId", | 97 CommandMapping(kGet, "session/:sessionId", |
| 46 CommandNames::kGetSessionCapabilities), | 98 WrapToNonSessionCommand( |
| 47 CommandMapping(kDelete, "session/:sessionId", CommandNames::kQuit), | 99 base::Bind(&ExecuteGetSessionCapabilities, |
| 100 &session_map_))), | |
| 101 CommandMapping(kDelete, "session/:sessionId", | |
| 102 base::Bind(&ExecuteQuit, false, &session_map_)), | |
| 48 CommandMapping(kGet, "session/:sessionId/window_handle", | 103 CommandMapping(kGet, "session/:sessionId/window_handle", |
| 49 CommandNames::kGetCurrentWindowHandle), | 104 WrapToNonSessionCommand( |
| 105 base::Bind(&ExecuteGetCurrentWindowHandle))), | |
| 50 CommandMapping(kGet, "session/:sessionId/window_handles", | 106 CommandMapping(kGet, "session/:sessionId/window_handles", |
| 51 CommandNames::kGetWindowHandles), | 107 WrapToNonSessionCommand( |
| 52 CommandMapping(kPost, "session/:sessionId/url", CommandNames::kGet), | 108 base::Bind(&ExecuteGetWindowHandles))), |
| 53 CommandMapping(kGet, "session/:sessionId/alert", CommandNames::kGetAlert), | 109 CommandMapping(kPost, "session/:sessionId/url", |
| 110 WrapToNonSessionCommand(base::Bind(&ExecuteGet))), | |
| 111 CommandMapping(kGet, "session/:sessionId/alert", | |
| 112 WrapToNonSessionCommand(base::Bind(&ExecuteGetAlert))), | |
| 54 CommandMapping(kPost, "session/:sessionId/dismiss_alert", | 113 CommandMapping(kPost, "session/:sessionId/dismiss_alert", |
| 55 CommandNames::kDismissAlert), | 114 WrapToNonSessionCommand(base::Bind(&ExecuteDismissAlert))), |
| 56 CommandMapping(kPost, "session/:sessionId/accept_alert", | 115 CommandMapping(kPost, "session/:sessionId/accept_alert", |
| 57 CommandNames::kAcceptAlert), | 116 WrapToNonSessionCommand(base::Bind(&ExecuteAcceptAlert))), |
| 58 CommandMapping(kGet, "session/:sessionId/alert_text", | 117 CommandMapping(kGet, "session/:sessionId/alert_text", |
| 59 CommandNames::kGetAlertText), | 118 WrapToNonSessionCommand(base::Bind(&ExecuteGetAlertText))), |
|
kkania
2013/07/02 01:57:08
alert stuff should use ExecuteAlertCommand
chrisgao (Use stgao instead)
2013/07/02 18:13:04
Done.
| |
| 60 CommandMapping(kPost, "session/:sessionId/alert_text", | 119 CommandMapping(kPost, "session/:sessionId/alert_text", |
| 61 CommandNames::kSetAlertValue), | 120 WrapToNonSessionCommand( |
| 121 base::Bind(&ExecuteSetAlertValue))), | |
| 62 CommandMapping(kPost, "session/:sessionId/forward", | 122 CommandMapping(kPost, "session/:sessionId/forward", |
| 63 CommandNames::kGoForward), | 123 WrapToNonSessionCommand(base::Bind(&ExecuteGoForward))), |
| 64 CommandMapping(kPost, "session/:sessionId/back", CommandNames::kGoBack), | 124 CommandMapping(kPost, "session/:sessionId/back", |
| 125 WrapToNonSessionCommand(base::Bind(&ExecuteGoBack))), | |
| 65 CommandMapping(kPost, "session/:sessionId/refresh", | 126 CommandMapping(kPost, "session/:sessionId/refresh", |
| 66 CommandNames::kRefresh), | 127 WrapToNonSessionCommand(base::Bind(&ExecuteRefresh))), |
| 67 CommandMapping(kPost, "session/:sessionId/execute", | 128 CommandMapping(kPost, "session/:sessionId/execute", |
| 68 CommandNames::kExecuteScript), | 129 WrapToNonSessionCommand(base::Bind( |
| 130 &ExecuteExecuteScript))), | |
| 69 CommandMapping(kPost, "session/:sessionId/execute_async", | 131 CommandMapping(kPost, "session/:sessionId/execute_async", |
| 70 CommandNames::kExecuteAsyncScript), | 132 WrapToNonSessionCommand( |
| 133 base::Bind(&ExecuteExecuteAsyncScript))), | |
| 71 CommandMapping(kGet, "session/:sessionId/url", | 134 CommandMapping(kGet, "session/:sessionId/url", |
| 72 CommandNames::kGetCurrentUrl), | 135 WrapToNonSessionCommand( |
| 73 CommandMapping(kGet, "session/:sessionId/title", CommandNames::kGetTitle), | 136 base::Bind(&ExecuteGetCurrentUrl))), |
| 137 CommandMapping(kGet, "session/:sessionId/title", | |
| 138 WrapToNonSessionCommand(base::Bind(&ExecuteGetTitle))), | |
| 74 CommandMapping(kGet, "session/:sessionId/source", | 139 CommandMapping(kGet, "session/:sessionId/source", |
| 75 CommandNames::kGetPageSource), | 140 WrapToNonSessionCommand( |
| 141 base::Bind(&ExecuteGetPageSource))), | |
| 76 CommandMapping(kGet, "session/:sessionId/screenshot", | 142 CommandMapping(kGet, "session/:sessionId/screenshot", |
| 77 CommandNames::kScreenshot), | 143 WrapToNonSessionCommand(base::Bind(&ExecuteScreenshot))), |
| 78 CommandMapping(kPost, "session/:sessionId/visible", | 144 CommandMapping(kPost, "session/:sessionId/visible", |
| 79 CommandNames::kSetBrowserVisible), | 145 base::Bind(&UnimplementedCommand)), |
|
chrisgao (Use stgao instead)
2013/07/02 01:31:40
Remove unimplemented command mappings or add a stu
chrisgao (Use stgao instead)
2013/07/02 18:13:04
Done.
| |
| 80 CommandMapping(kGet, "session/:sessionId/visible", | 146 CommandMapping(kGet, "session/:sessionId/visible", |
| 81 CommandNames::kIsBrowserVisible), | 147 base::Bind(&UnimplementedCommand)), |
| 82 CommandMapping(kPost, "session/:sessionId/element", | 148 CommandMapping(kPost, "session/:sessionId/element", |
| 83 CommandNames::kFindElement), | 149 WrapToNonSessionCommand( |
| 150 base::Bind(&ExecuteFindElement, 50))), | |
| 84 CommandMapping(kPost, "session/:sessionId/elements", | 151 CommandMapping(kPost, "session/:sessionId/elements", |
| 85 CommandNames::kFindElements), | 152 WrapToNonSessionCommand( |
| 153 base::Bind(&ExecuteFindElements, 50))), | |
| 86 CommandMapping(kPost, "session/:sessionId/element/active", | 154 CommandMapping(kPost, "session/:sessionId/element/active", |
| 87 CommandNames::kGetActiveElement), | 155 WrapToNonSessionCommand( |
| 156 base::Bind(&ExecuteGetActiveElement))), | |
| 88 CommandMapping(kPost, "session/:sessionId/element/:id/element", | 157 CommandMapping(kPost, "session/:sessionId/element/:id/element", |
| 89 CommandNames::kFindChildElement), | 158 WrapToNonSessionCommand( |
| 159 base::Bind(&ExecuteFindChildElement, 50))), | |
| 90 CommandMapping(kPost, "session/:sessionId/element/:id/elements", | 160 CommandMapping(kPost, "session/:sessionId/element/:id/elements", |
| 91 CommandNames::kFindChildElements), | 161 WrapToNonSessionCommand( |
| 162 base::Bind(&ExecuteFindChildElements, 50))), | |
| 92 CommandMapping(kPost, "session/:sessionId/element/:id/click", | 163 CommandMapping(kPost, "session/:sessionId/element/:id/click", |
| 93 CommandNames::kClickElement), | 164 WrapToNonSessionCommand(base::Bind(&ExecuteClickElement))), |
| 94 CommandMapping(kPost, "session/:sessionId/element/:id/clear", | 165 CommandMapping(kPost, "session/:sessionId/element/:id/clear", |
| 95 CommandNames::kClearElement), | 166 WrapToNonSessionCommand(base::Bind(&ExecuteClearElement))), |
| 96 CommandMapping(kPost, "session/:sessionId/element/:id/submit", | 167 CommandMapping(kPost, "session/:sessionId/element/:id/submit", |
| 97 CommandNames::kSubmitElement), | 168 WrapToNonSessionCommand( |
| 169 base::Bind(&ExecuteSubmitElement))), | |
| 98 CommandMapping(kGet, "session/:sessionId/element/:id/text", | 170 CommandMapping(kGet, "session/:sessionId/element/:id/text", |
| 99 CommandNames::kGetElementText), | 171 WrapToNonSessionCommand( |
| 172 base::Bind(&ExecuteGetElementText))), | |
| 100 CommandMapping(kPost, "session/:sessionId/element/:id/value", | 173 CommandMapping(kPost, "session/:sessionId/element/:id/value", |
| 101 CommandNames::kSendKeysToElement), | 174 WrapToNonSessionCommand( |
| 175 base::Bind(&ExecuteSendKeysToElement))), | |
| 102 CommandMapping(kPost, "session/:sessionId/file", | 176 CommandMapping(kPost, "session/:sessionId/file", |
| 103 CommandNames::kUploadFile), | 177 WrapToNonSessionCommand(base::Bind(&ExecuteUploadFile))), |
| 104 CommandMapping(kGet, "session/:sessionId/element/:id/value", | 178 CommandMapping(kGet, "session/:sessionId/element/:id/value", |
| 105 CommandNames::kGetElementValue), | 179 WrapToNonSessionCommand( |
| 180 base::Bind(&ExecuteGetElementValue))), | |
| 106 CommandMapping(kGet, "session/:sessionId/element/:id/name", | 181 CommandMapping(kGet, "session/:sessionId/element/:id/name", |
| 107 CommandNames::kGetElementTagName), | 182 WrapToNonSessionCommand( |
| 183 base::Bind(&ExecuteGetElementTagName))), | |
| 108 CommandMapping(kGet, "session/:sessionId/element/:id/selected", | 184 CommandMapping(kGet, "session/:sessionId/element/:id/selected", |
| 109 CommandNames::kIsElementSelected), | 185 WrapToNonSessionCommand( |
| 186 base::Bind(&ExecuteIsElementSelected))), | |
| 110 CommandMapping(kGet, "session/:sessionId/element/:id/enabled", | 187 CommandMapping(kGet, "session/:sessionId/element/:id/enabled", |
| 111 CommandNames::kIsElementEnabled), | 188 WrapToNonSessionCommand( |
| 189 base::Bind(&ExecuteIsElementEnabled))), | |
| 112 CommandMapping(kGet, "session/:sessionId/element/:id/displayed", | 190 CommandMapping(kGet, "session/:sessionId/element/:id/displayed", |
| 113 CommandNames::kIsElementDisplayed), | 191 WrapToNonSessionCommand( |
| 192 base::Bind(&ExecuteIsElementDisplayed))), | |
| 114 CommandMapping(kPost, "session/:sessionId/element/:id/hover", | 193 CommandMapping(kPost, "session/:sessionId/element/:id/hover", |
| 115 CommandNames::kHoverOverElement), | 194 WrapToNonSessionCommand( |
| 195 base::Bind(&ExecuteHoverOverElement))), | |
| 116 CommandMapping(kGet, "session/:sessionId/element/:id/location", | 196 CommandMapping(kGet, "session/:sessionId/element/:id/location", |
| 117 CommandNames::kGetElementLocation), | 197 WrapToNonSessionCommand( |
| 198 base::Bind(&ExecuteGetElementLocation))), | |
| 118 CommandMapping(kGet, "session/:sessionId/element/:id/location_in_view", | 199 CommandMapping(kGet, "session/:sessionId/element/:id/location_in_view", |
| 119 CommandNames::kGetElementLocationOnceScrolledIntoView), | 200 WrapToNonSessionCommand( |
| 201 base::Bind( | |
| 202 &ExecuteGetElementLocationOnceScrolledIntoView))), | |
| 120 CommandMapping(kGet, "session/:sessionId/element/:id/size", | 203 CommandMapping(kGet, "session/:sessionId/element/:id/size", |
| 121 CommandNames::kGetElementSize), | 204 WrapToNonSessionCommand( |
| 205 base::Bind(&ExecuteGetElementSize))), | |
| 122 CommandMapping(kGet, "session/:sessionId/element/:id/attribute/:name", | 206 CommandMapping(kGet, "session/:sessionId/element/:id/attribute/:name", |
| 123 CommandNames::kGetElementAttribute), | 207 WrapToNonSessionCommand( |
| 208 base::Bind(&ExecuteGetElementAttribute))), | |
| 124 CommandMapping(kGet, "session/:sessionId/element/:id/equals/:other", | 209 CommandMapping(kGet, "session/:sessionId/element/:id/equals/:other", |
| 125 CommandNames::kElementEquals), | 210 WrapToNonSessionCommand( |
| 211 base::Bind(&ExecuteElementEquals))), | |
| 126 CommandMapping(kGet, "session/:sessionId/cookie", | 212 CommandMapping(kGet, "session/:sessionId/cookie", |
| 127 CommandNames::kGetCookies), | 213 WrapToNonSessionCommand(base::Bind(&ExecuteGetCookies))), |
| 128 CommandMapping(kPost, "session/:sessionId/cookie", | 214 CommandMapping(kPost, "session/:sessionId/cookie", |
| 129 CommandNames::kAddCookie), | 215 WrapToNonSessionCommand(base::Bind(&ExecuteAddCookie))), |
| 130 CommandMapping(kDelete, "session/:sessionId/cookie", | 216 CommandMapping(kDelete, "session/:sessionId/cookie", |
| 131 CommandNames::kDeleteAllCookies), | 217 WrapToNonSessionCommand( |
| 218 base::Bind(&ExecuteDeleteAllCookies))), | |
| 132 CommandMapping(kDelete, "session/:sessionId/cookie/:name", | 219 CommandMapping(kDelete, "session/:sessionId/cookie/:name", |
| 133 CommandNames::kDeleteCookie), | 220 WrapToNonSessionCommand(base::Bind(&ExecuteDeleteCookie))), |
| 134 CommandMapping(kPost, "session/:sessionId/frame", | 221 CommandMapping(kPost, "session/:sessionId/frame", |
| 135 CommandNames::kSwitchToFrame), | 222 WrapToNonSessionCommand( |
| 223 base::Bind(&ExecuteSwitchToFrame))), | |
| 136 CommandMapping(kPost, "session/:sessionId/window", | 224 CommandMapping(kPost, "session/:sessionId/window", |
| 137 CommandNames::kSwitchToWindow), | 225 WrapToNonSessionCommand( |
| 226 base::Bind(&ExecuteSwitchToWindow))), | |
| 138 CommandMapping(kGet, "session/:sessionId/window/:windowHandle/size", | 227 CommandMapping(kGet, "session/:sessionId/window/:windowHandle/size", |
| 139 CommandNames::kGetWindowSize), | 228 WrapToNonSessionCommand( |
| 229 base::Bind(&ExecuteGetWindowSize))), | |
| 140 CommandMapping(kGet, "session/:sessionId/window/:windowHandle/position", | 230 CommandMapping(kGet, "session/:sessionId/window/:windowHandle/position", |
| 141 CommandNames::kGetWindowPosition), | 231 WrapToNonSessionCommand( |
| 232 base::Bind(&ExecuteGetWindowPosition))), | |
| 142 CommandMapping(kPost, "session/:sessionId/window/:windowHandle/size", | 233 CommandMapping(kPost, "session/:sessionId/window/:windowHandle/size", |
| 143 CommandNames::kSetWindowSize), | 234 WrapToNonSessionCommand( |
| 235 base::Bind(&ExecuteSetWindowSize))), | |
| 144 CommandMapping(kPost, "session/:sessionId/window/:windowHandle/position", | 236 CommandMapping(kPost, "session/:sessionId/window/:windowHandle/position", |
| 145 CommandNames::kSetWindowPosition), | 237 WrapToNonSessionCommand( |
| 238 base::Bind(&ExecuteSetWindowPosition))), | |
| 146 CommandMapping(kPost, "session/:sessionId/window/:windowHandle/maximize", | 239 CommandMapping(kPost, "session/:sessionId/window/:windowHandle/maximize", |
| 147 CommandNames::kMaximizeWindow), | 240 WrapToNonSessionCommand( |
| 241 base::Bind(&ExecuteMaximizeWindow))), | |
| 148 CommandMapping(kDelete, "session/:sessionId/window", | 242 CommandMapping(kDelete, "session/:sessionId/window", |
| 149 CommandNames::kClose), | 243 WrapToNonSessionCommand( |
| 244 base::Bind(&ExecuteClose, &session_map_))), | |
| 150 CommandMapping(kPost, "session/:sessionId/element/:id/drag", | 245 CommandMapping(kPost, "session/:sessionId/element/:id/drag", |
| 151 CommandNames::kDragElement), | 246 base::Bind(&UnimplementedCommand)), |
| 152 CommandMapping(kGet, "session/:sessionId/element/:id/css/:propertyName", | 247 CommandMapping(kGet, "session/:sessionId/element/:id/css/:propertyName", |
| 153 CommandNames::kGetElementValueOfCssProperty), | 248 WrapToNonSessionCommand( |
| 249 base::Bind(&ExecuteGetElementValueOfCSSProperty))), | |
| 154 CommandMapping(kPost, "session/:sessionId/timeouts/implicit_wait", | 250 CommandMapping(kPost, "session/:sessionId/timeouts/implicit_wait", |
| 155 CommandNames::kImplicitlyWait), | 251 WrapToNonSessionCommand( |
| 252 base::Bind(&ExecuteImplicitlyWait))), | |
| 156 CommandMapping(kPost, "session/:sessionId/timeouts/async_script", | 253 CommandMapping(kPost, "session/:sessionId/timeouts/async_script", |
| 157 CommandNames::kSetScriptTimeout), | 254 WrapToNonSessionCommand( |
| 255 base::Bind(&ExecuteSetScriptTimeout))), | |
| 158 CommandMapping(kPost, "session/:sessionId/timeouts", | 256 CommandMapping(kPost, "session/:sessionId/timeouts", |
| 159 CommandNames::kSetTimeout), | 257 WrapToNonSessionCommand(base::Bind(&ExecuteSetTimeout))), |
| 160 CommandMapping(kPost, "session/:sessionId/execute_sql", | 258 CommandMapping(kPost, "session/:sessionId/execute_sql", |
| 161 CommandNames::kExecuteSQL), | 259 base::Bind(&UnimplementedCommand)), |
| 162 CommandMapping(kGet, "session/:sessionId/location", | 260 CommandMapping(kGet, "session/:sessionId/location", |
| 163 CommandNames::kGetLocation), | 261 WrapToNonSessionCommand(base::Bind(&ExecuteGetLocation))), |
| 164 CommandMapping(kPost, "session/:sessionId/location", | 262 CommandMapping(kPost, "session/:sessionId/location", |
| 165 CommandNames::kSetLocation), | 263 WrapToNonSessionCommand(base::Bind(&ExecuteSetLocation))), |
| 166 CommandMapping(kGet, "session/:sessionId/application_cache/status", | 264 CommandMapping(kGet, "session/:sessionId/application_cache/status", |
| 167 CommandNames::kGetStatus), | 265 base::Bind(&ExecuteGetStatus)), |
| 168 CommandMapping(kGet, "session/:sessionId/browser_connection", | 266 CommandMapping(kGet, "session/:sessionId/browser_connection", |
| 169 CommandNames::kIsBrowserOnline), | 267 base::Bind(&UnimplementedCommand)), |
| 170 CommandMapping(kPost, "session/:sessionId/browser_connection", | 268 CommandMapping(kPost, "session/:sessionId/browser_connection", |
| 171 CommandNames::kSetBrowserOnline), | 269 base::Bind(&UnimplementedCommand)), |
| 172 CommandMapping(kGet, "session/:sessionId/local_storage/key/:key", | 270 CommandMapping(kGet, "session/:sessionId/local_storage/key/:key", |
| 173 CommandNames::kGetLocalStorageItem), | 271 WrapToNonSessionCommand( |
| 272 base::Bind(&ExecuteGetStorageItem, kLocalStorage))), | |
| 174 CommandMapping(kDelete, "session/:sessionId/local_storage/key/:key", | 273 CommandMapping(kDelete, "session/:sessionId/local_storage/key/:key", |
| 175 CommandNames::kRemoveLocalStorageItem), | 274 WrapToNonSessionCommand( |
| 275 base::Bind(&ExecuteRemoveStorageItem, kLocalStorage))), | |
| 176 CommandMapping(kGet, "session/:sessionId/local_storage", | 276 CommandMapping(kGet, "session/:sessionId/local_storage", |
| 177 CommandNames::kGetLocalStorageKeys), | 277 WrapToNonSessionCommand( |
| 278 base::Bind(&ExecuteGetStorageKeys, kLocalStorage))), | |
| 178 CommandMapping(kPost, "session/:sessionId/local_storage", | 279 CommandMapping(kPost, "session/:sessionId/local_storage", |
| 179 CommandNames::kSetLocalStorageItem), | 280 WrapToNonSessionCommand( |
| 281 base::Bind(&ExecuteSetStorageItem, kLocalStorage))), | |
| 180 CommandMapping(kDelete, "session/:sessionId/local_storage", | 282 CommandMapping(kDelete, "session/:sessionId/local_storage", |
| 181 CommandNames::kClearLocalStorage), | 283 WrapToNonSessionCommand( |
| 284 base::Bind(&ExecuteClearStorage, kLocalStorage))), | |
| 182 CommandMapping(kGet, "session/:sessionId/local_storage/size", | 285 CommandMapping(kGet, "session/:sessionId/local_storage/size", |
| 183 CommandNames::kGetLocalStorageSize), | 286 WrapToNonSessionCommand( |
| 287 base::Bind(&ExecuteGetStorageSize, kLocalStorage))), | |
| 184 CommandMapping(kGet, "session/:sessionId/session_storage/key/:key", | 288 CommandMapping(kGet, "session/:sessionId/session_storage/key/:key", |
| 185 CommandNames::kGetSessionStorageItem), | 289 WrapToNonSessionCommand( |
| 290 base::Bind(&ExecuteGetStorageItem, kSessionStorage))), | |
| 186 CommandMapping(kDelete, "session/:sessionId/session_storage/key/:key", | 291 CommandMapping(kDelete, "session/:sessionId/session_storage/key/:key", |
| 187 CommandNames::kRemoveSessionStorageItem), | 292 WrapToNonSessionCommand( |
| 293 base::Bind( | |
| 294 &ExecuteRemoveStorageItem, kSessionStorage))), | |
| 188 CommandMapping(kGet, "session/:sessionId/session_storage", | 295 CommandMapping(kGet, "session/:sessionId/session_storage", |
| 189 CommandNames::kGetSessionStorageKey), | 296 WrapToNonSessionCommand( |
| 297 base::Bind(&ExecuteGetStorageKeys, kSessionStorage))), | |
| 190 CommandMapping(kPost, "session/:sessionId/session_storage", | 298 CommandMapping(kPost, "session/:sessionId/session_storage", |
| 191 CommandNames::kSetSessionStorageItem), | 299 WrapToNonSessionCommand( |
| 300 base::Bind(&ExecuteSetStorageItem, kSessionStorage))), | |
| 192 CommandMapping(kDelete, "session/:sessionId/session_storage", | 301 CommandMapping(kDelete, "session/:sessionId/session_storage", |
| 193 CommandNames::kClearSessionStorage), | 302 WrapToNonSessionCommand( |
| 303 base::Bind(&ExecuteClearStorage, kSessionStorage))), | |
| 194 CommandMapping(kGet, "session/:sessionId/session_storage/size", | 304 CommandMapping(kGet, "session/:sessionId/session_storage/size", |
| 195 CommandNames::kGetSessionStorageSize), | 305 WrapToNonSessionCommand( |
| 306 base::Bind(&ExecuteGetStorageSize, kSessionStorage))), | |
| 196 CommandMapping(kGet, "session/:sessionId/orientation", | 307 CommandMapping(kGet, "session/:sessionId/orientation", |
| 197 CommandNames::kGetScreenOrientation), | 308 base::Bind(&UnimplementedCommand)), |
| 198 CommandMapping(kPost, "session/:sessionId/orientation", | 309 CommandMapping(kPost, "session/:sessionId/orientation", |
| 199 CommandNames::kSetScreenOrientation), | 310 base::Bind(&UnimplementedCommand)), |
| 200 CommandMapping(kPost, "session/:sessionId/click", | 311 CommandMapping(kPost, "session/:sessionId/click", |
| 201 CommandNames::kMouseClick), | 312 WrapToNonSessionCommand(base::Bind(&ExecuteMouseClick))), |
| 202 CommandMapping(kPost, "session/:sessionId/doubleclick", | 313 CommandMapping(kPost, "session/:sessionId/doubleclick", |
| 203 CommandNames::kMouseDoubleClick), | 314 WrapToNonSessionCommand( |
| 315 base::Bind(&ExecuteMouseDoubleClick))), | |
| 204 CommandMapping(kPost, "session/:sessionId/buttondown", | 316 CommandMapping(kPost, "session/:sessionId/buttondown", |
| 205 CommandNames::kMouseButtonDown), | 317 WrapToNonSessionCommand( |
| 318 base::Bind(&ExecuteMouseButtonDown))), | |
| 206 CommandMapping(kPost, "session/:sessionId/buttonup", | 319 CommandMapping(kPost, "session/:sessionId/buttonup", |
| 207 CommandNames::kMouseButtonUp), | 320 WrapToNonSessionCommand( |
| 321 base::Bind(&ExecuteMouseButtonUp))), | |
| 208 CommandMapping(kPost, "session/:sessionId/moveto", | 322 CommandMapping(kPost, "session/:sessionId/moveto", |
| 209 CommandNames::kMouseMoveTo), | 323 WrapToNonSessionCommand(base::Bind(&ExecuteMouseMoveTo))), |
| 210 CommandMapping(kPost, "session/:sessionId/keys", | 324 CommandMapping(kPost, "session/:sessionId/keys", |
| 211 CommandNames::kSendKeysToActiveElement), | 325 WrapToNonSessionCommand( |
| 326 base::Bind(&ExecuteSendKeysToActiveElement))), | |
| 212 CommandMapping(kGet, "session/:sessionId/ime/available_engines", | 327 CommandMapping(kGet, "session/:sessionId/ime/available_engines", |
| 213 CommandNames::kImeGetAvailableEngines), | 328 base::Bind(&UnimplementedCommand)), |
| 214 CommandMapping(kGet, "session/:sessionId/ime/active_engine", | 329 CommandMapping(kGet, "session/:sessionId/ime/active_engine", |
| 215 CommandNames::kImeGetActiveEngine), | 330 base::Bind(&UnimplementedCommand)), |
| 216 CommandMapping(kGet, "session/:sessionId/ime/activated", | 331 CommandMapping(kGet, "session/:sessionId/ime/activated", |
| 217 CommandNames::kImeIsActivated), | 332 base::Bind(&UnimplementedCommand)), |
| 218 CommandMapping(kPost, "session/:sessionId/ime/deactivate", | 333 CommandMapping(kPost, "session/:sessionId/ime/deactivate", |
| 219 CommandNames::kImeDeactivate), | 334 base::Bind(&UnimplementedCommand)), |
| 220 CommandMapping(kPost, "session/:sessionId/ime/activate", | 335 CommandMapping(kPost, "session/:sessionId/ime/activate", |
| 221 CommandNames::kImeActivateEngine), | 336 base::Bind(&UnimplementedCommand)), |
| 222 CommandMapping(kPost, "session/:sessionId/touch/click", | 337 CommandMapping(kPost, "session/:sessionId/touch/click", |
| 223 CommandNames::kTouchSingleTap), | 338 WrapToNonSessionCommand( |
| 339 base::Bind(&ExecuteTouchSingleTap))), | |
| 224 CommandMapping(kPost, "session/:sessionId/touch/down", | 340 CommandMapping(kPost, "session/:sessionId/touch/down", |
| 225 CommandNames::kTouchDown), | 341 base::Bind(&UnimplementedCommand)), |
| 226 CommandMapping(kPost, "session/:sessionId/touch/up", | 342 CommandMapping(kPost, "session/:sessionId/touch/up", |
| 227 CommandNames::kTouchUp), | 343 base::Bind(&UnimplementedCommand)), |
| 228 CommandMapping(kPost, "session/:sessionId/touch/move", | 344 CommandMapping(kPost, "session/:sessionId/touch/move", |
| 229 CommandNames::kTouchMove), | 345 base::Bind(&UnimplementedCommand)), |
| 230 CommandMapping(kPost, "session/:sessionId/touch/scroll", | 346 CommandMapping(kPost, "session/:sessionId/touch/scroll", |
| 231 CommandNames::kTouchScroll), | 347 base::Bind(&UnimplementedCommand)), |
| 232 CommandMapping(kPost, "session/:sessionId/touch/doubleclick", | 348 CommandMapping(kPost, "session/:sessionId/touch/doubleclick", |
| 233 CommandNames::kTouchDoubleTap), | 349 base::Bind(&UnimplementedCommand)), |
| 234 CommandMapping(kPost, "session/:sessionId/touch/longclick", | 350 CommandMapping(kPost, "session/:sessionId/touch/longclick", |
| 235 CommandNames::kTouchLongPress), | 351 base::Bind(&UnimplementedCommand)), |
| 236 CommandMapping(kPost, "session/:sessionId/touch/flick", | 352 CommandMapping(kPost, "session/:sessionId/touch/flick", |
| 237 CommandNames::kTouchFlick), | 353 base::Bind(&UnimplementedCommand)), |
| 238 CommandMapping(kPost, "session/:sessionId/log", CommandNames::kGetLog), | 354 CommandMapping(kPost, "session/:sessionId/log", |
| 355 WrapToNonSessionCommand(base::Bind(&ExecuteGetLog))), | |
| 239 CommandMapping(kGet, "session/:sessionId/log/types", | 356 CommandMapping(kGet, "session/:sessionId/log/types", |
| 240 CommandNames::kGetAvailableLogTypes), | 357 WrapToNonSessionCommand( |
| 241 CommandMapping(kPost, "logs", CommandNames::kGetSessionLogs), | 358 base::Bind(&ExecuteGetAvailableLogTypes))), |
| 242 CommandMapping(kGet, "status", CommandNames::kStatus), | 359 CommandMapping(kPost, "logs", base::Bind(&UnimplementedCommand)), |
| 360 CommandMapping(kGet, "status", base::Bind(&ExecuteGetStatus)), | |
| 243 | 361 |
| 244 // Custom Chrome commands: | 362 // Custom Chrome commands: |
| 245 // Allow quit all to be called with GET or POST. | 363 // Allow quit all to be called with GET or POST. |
| 246 CommandMapping(kGet, kShutdownPath, CommandNames::kQuitAll), | 364 CommandMapping(kGet, kShutdownPath, |
| 247 CommandMapping(kPost, kShutdownPath, CommandNames::kQuitAll), | 365 base::Bind(&ExecuteQuitAll, |
| 366 base::Bind(&ExecuteQuit, true, &session_map_), | |
| 367 &session_map_)), | |
| 368 CommandMapping(kPost, kShutdownPath, | |
| 369 base::Bind(&ExecuteQuitAll, | |
| 370 base::Bind(&ExecuteQuit, true, &session_map_), | |
| 371 &session_map_)), | |
| 248 CommandMapping(kGet, "session/:sessionId/is_loading", | 372 CommandMapping(kGet, "session/:sessionId/is_loading", |
| 249 CommandNames::kIsLoading), | 373 WrapToNonSessionCommand(base::Bind(&ExecuteIsLoading))), |
| 250 }; | 374 }; |
| 251 return scoped_ptr<CommandMap>( | 375 this->command_map_ = scoped_ptr<CommandMap>( |
|
kkania
2013/07/02 01:57:08
command_map_.reset(new CommandMap(commands, comman
chrisgao (Use stgao instead)
2013/07/02 18:13:04
Done.
| |
| 252 new CommandMap(commands, commands + arraysize(commands))); | 376 new CommandMap(commands, commands + arraysize(commands))); |
| 253 } | 377 } |
| 254 | 378 |
| 255 HttpHandler::HttpHandler(Log* log, | |
| 256 scoped_ptr<CommandExecutor> executor, | |
| 257 scoped_ptr<CommandMap> command_map, | |
| 258 const std::string& url_base) | |
| 259 : log_(log), | |
| 260 executor_(executor.Pass()), | |
| 261 command_map_(command_map.Pass()), | |
| 262 url_base_(url_base) { | |
| 263 executor_->Init(); | |
| 264 } | |
| 265 | |
| 266 HttpHandler::~HttpHandler() {} | |
| 267 | |
| 268 void HttpHandler::Handle(const HttpRequest& request, | 379 void HttpHandler::Handle(const HttpRequest& request, |
| 269 HttpResponse* response) { | 380 HttpResponse* response) { |
| 270 const char* method = "GET"; | 381 const char* method = "GET"; |
| 271 if (request.method == kPost) | 382 if (request.method == kPost) |
| 272 method = "POST"; | 383 method = "POST"; |
| 273 else if (request.method == kDelete) | 384 else if (request.method == kDelete) |
| 274 method = "DELETE"; | 385 method = "DELETE"; |
| 275 log_->AddEntry( | 386 log_->AddEntry( |
| 276 Log::kLog, | 387 Log::kLog, |
| 277 base::StringPrintf("received WebDriver request: %s %s %s", | 388 base::StringPrintf("received WebDriver request: %s %s %s", |
| 278 method, | 389 method, |
| 279 request.path.c_str(), | 390 request.path.c_str(), |
| 280 request.body.c_str())); | 391 request.body.c_str())); |
| 281 | 392 |
| 282 HandleInternal(request, response); | 393 HandleInternal(request, response); |
| 283 | 394 |
| 284 log_->AddEntry( | 395 log_->AddEntry( |
| 285 Log::kLog, | 396 Log::kLog, |
| 286 base::StringPrintf("sending WebDriver response: %d %s", | 397 base::StringPrintf("sending WebDriver response: %d %s", |
| 287 response->status(), | 398 response->status(), |
| 288 response->body().c_str())); | 399 response->body().c_str())); |
| 289 } | 400 } |
| 290 | 401 |
| 291 bool HttpHandler::ShouldShutdown(const HttpRequest& request) { | 402 bool HttpHandler::ShouldShutdown(const HttpRequest& request) { |
| 292 return request.path == url_base_ + kShutdownPath; | 403 return request.path == url_base_ + kShutdownPath; |
| 293 } | 404 } |
| 294 | 405 |
| 406 Command HttpHandler::WrapToNonSessionCommand( | |
|
kkania
2013/07/02 01:57:08
How about just call these WrapToCommand?
chrisgao (Use stgao instead)
2013/07/02 18:13:04
Done.
| |
| 407 const SessionCommand& session_command) { | |
| 408 return base::Bind(&ExecuteSessionCommand, &session_map_, session_command); | |
| 409 } | |
| 410 | |
| 411 Command HttpHandler::WrapToNonSessionCommand( | |
| 412 const WindowCommand& window_command) { | |
| 413 return WrapToNonSessionCommand( | |
| 414 base::Bind(&ExecuteWindowCommand, window_command)); | |
| 415 } | |
| 416 | |
| 417 Command HttpHandler::WrapToNonSessionCommand( | |
| 418 const ElementCommand& element_command) { | |
| 419 return WrapToNonSessionCommand( | |
| 420 base::Bind(&ExecuteElementCommand, element_command)); | |
| 421 } | |
| 422 | |
| 295 void HttpHandler::HandleInternal(const HttpRequest& request, | 423 void HttpHandler::HandleInternal(const HttpRequest& request, |
| 296 HttpResponse* response) { | 424 HttpResponse* response) { |
| 297 std::string path = request.path; | 425 std::string path = request.path; |
| 298 if (!StartsWithASCII(path, url_base_, true)) { | 426 if (!StartsWithASCII(path, url_base_, true)) { |
| 299 *response = HttpResponse(HttpResponse::kBadRequest); | 427 *response = HttpResponse(HttpResponse::kBadRequest); |
| 300 response->set_body("unhandled request"); | 428 response->set_body("unhandled request"); |
| 301 return; | 429 return; |
| 302 } | 430 } |
| 303 | 431 |
| 304 path.erase(0, url_base_.length()); | 432 path.erase(0, url_base_.length()); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 332 base::DictionaryValue* body_params; | 460 base::DictionaryValue* body_params; |
| 333 scoped_ptr<base::Value> parsed_body(base::JSONReader::Read(request.body)); | 461 scoped_ptr<base::Value> parsed_body(base::JSONReader::Read(request.body)); |
| 334 if (!parsed_body || !parsed_body->GetAsDictionary(&body_params)) { | 462 if (!parsed_body || !parsed_body->GetAsDictionary(&body_params)) { |
| 335 *response = HttpResponse(HttpResponse::kBadRequest); | 463 *response = HttpResponse(HttpResponse::kBadRequest); |
| 336 response->set_body("missing command parameters"); | 464 response->set_body("missing command parameters"); |
| 337 return true; | 465 return true; |
| 338 } | 466 } |
| 339 params.MergeDictionary(body_params); | 467 params.MergeDictionary(body_params); |
| 340 } | 468 } |
| 341 | 469 |
| 342 StatusCode status = kOk; | |
| 343 scoped_ptr<base::Value> value; | 470 scoped_ptr<base::Value> value; |
| 344 std::string out_session_id; | 471 std::string out_session_id; |
| 345 executor_->ExecuteCommand( | 472 Status status = iter->command.Run( |
| 346 iter->name, params, session_id, &status, &value, &out_session_id); | 473 params, session_id, &value, &out_session_id); |
| 347 | 474 |
| 348 if (status == kUnknownCommand) { | 475 if (status.code() == kUnknownCommand) { |
| 349 *response = HttpResponse(HttpResponse::kNotImplemented); | 476 *response = HttpResponse(HttpResponse::kNotImplemented); |
| 350 response->set_body("unimplemented command: " + iter->name); | 477 response->set_body("unimplemented command: " + trimmed_path); |
| 351 return true; | 478 return true; |
| 352 } | 479 } |
| 353 | 480 |
| 354 if (iter->name == CommandNames::kNewSession && status == kOk) { | 481 if (iter->path_pattern == internal::kNewSessionPathPattern && status.IsOk()) { |
| 355 // Creating a session involves a HTTP request to /session, which is | 482 // Creating a session involves a HTTP request to /session, which is |
| 356 // supposed to redirect to /session/:sessionId, which returns the | 483 // supposed to redirect to /session/:sessionId, which returns the |
| 357 // session info. | 484 // session info. |
| 358 *response = HttpResponse(HttpResponse::kSeeOther); | 485 *response = HttpResponse(HttpResponse::kSeeOther); |
| 359 response->AddHeader("Location", url_base_ + "session/" + out_session_id); | 486 response->AddHeader("Location", url_base_ + "session/" + out_session_id); |
| 360 return true; | 487 return true; |
| 488 } else if (status.IsError()) { | |
| 489 status.AddDetails(base::StringPrintf( | |
| 490 "Driver info: chromedriver=%s,platform=%s %s %s", | |
| 491 kChromeDriverVersion, | |
| 492 base::SysInfo::OperatingSystemName().c_str(), | |
| 493 base::SysInfo::OperatingSystemVersion().c_str(), | |
| 494 base::SysInfo::OperatingSystemArchitecture().c_str())); | |
| 495 scoped_ptr<base::DictionaryValue> error(new base::DictionaryValue()); | |
| 496 error->SetString("message", status.message()); | |
| 497 value.reset(error.release()); | |
| 361 } | 498 } |
| 499 if (!value) | |
| 500 value.reset(base::Value::CreateNullValue()); | |
| 362 | 501 |
| 363 base::DictionaryValue body_params; | 502 base::DictionaryValue body_params; |
| 364 body_params.SetInteger("status", status); | 503 body_params.SetInteger("status", status.code()); |
| 365 body_params.Set("value", value.release()); | 504 body_params.Set("value", value.release()); |
| 366 body_params.SetString("sessionId", out_session_id); | 505 body_params.SetString("sessionId", out_session_id); |
| 367 std::string body; | 506 std::string body; |
| 368 base::JSONWriter::WriteWithOptions( | 507 base::JSONWriter::WriteWithOptions( |
| 369 &body_params, base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION, | 508 &body_params, base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION, |
| 370 &body); | 509 &body); |
| 371 *response = HttpResponse(HttpResponse::kOk); | 510 *response = HttpResponse(HttpResponse::kOk); |
| 372 response->SetMimeType("application/json; charset=utf-8"); | 511 response->SetMimeType("application/json; charset=utf-8"); |
| 373 response->set_body(body); | 512 response->set_body(body); |
| 374 return true; | 513 return true; |
| 375 } | 514 } |
| 376 | 515 |
| 377 namespace internal { | 516 namespace internal { |
| 378 | 517 |
| 518 const char kNewSessionPathPattern[] = "session"; | |
| 519 | |
| 379 bool MatchesCommand(HttpMethod method, | 520 bool MatchesCommand(HttpMethod method, |
| 380 const std::string& path, | 521 const std::string& path, |
| 381 const CommandMapping& command, | 522 const CommandMapping& command, |
| 382 std::string* session_id, | 523 std::string* session_id, |
| 383 base::DictionaryValue* out_params) { | 524 base::DictionaryValue* out_params) { |
| 384 if (method != command.method) | 525 if (method != command.method) |
| 385 return false; | 526 return false; |
| 386 | 527 |
| 387 std::vector<std::string> path_parts; | 528 std::vector<std::string> path_parts; |
| 388 base::SplitString(path, '/', &path_parts); | 529 base::SplitString(path, '/', &path_parts); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 403 else | 544 else |
| 404 params.SetString(name, path_parts[i]); | 545 params.SetString(name, path_parts[i]); |
| 405 } else if (command_path_parts[i] != path_parts[i]) { | 546 } else if (command_path_parts[i] != path_parts[i]) { |
| 406 return false; | 547 return false; |
| 407 } | 548 } |
| 408 } | 549 } |
| 409 out_params->MergeDictionary(¶ms); | 550 out_params->MergeDictionary(¶ms); |
| 410 return true; | 551 return true; |
| 411 } | 552 } |
| 412 | 553 |
| 413 } // namespace | 554 } // namespace internal |
| OLD | NEW |