| // Copyright 2011 Software Freedom Conservancy | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // 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 "IECommandExecutor.h" | |
| #include "logging.h" | |
| #include "CommandHandlers/AcceptAlertCommandHandler.h" | |
| #include "CommandHandlers/AddCookieCommandHandler.h" | |
| #include "CommandHandlers/ClickElementCommandHandler.h" | |
| #include "CommandHandlers/ClearElementCommandHandler.h" | |
| #include "CommandHandlers/CloseWindowCommandHandler.h" | |
| #include "CommandHandlers/DeleteAllCookiesCommandHandler.h" | |
| #include "CommandHandlers/DeleteCookieCommandHandler.h" | |
| #include "CommandHandlers/DismissAlertCommandHandler.h" | |
| #include "CommandHandlers/ElementEqualsCommandHandler.h" | |
| #include "CommandHandlers/ExecuteAsyncScriptCommandHandler.h" | |
| #include "CommandHandlers/ExecuteScriptCommandHandler.h" | |
| #include "CommandHandlers/FindChildElementCommandHandler.h" | |
| #include "CommandHandlers/FindChildElementsCommandHandler.h" | |
| #include "CommandHandlers/FindElementCommandHandler.h" | |
| #include "CommandHandlers/FindElementsCommandHandler.h" | |
| #include "CommandHandlers/GetActiveElementCommandHandler.h" | |
| #include "CommandHandlers/GetAlertTextCommandHandler.h" | |
| #include "CommandHandlers/GetAllCookiesCommandHandler.h" | |
| #include "CommandHandlers/GetAllWindowHandlesCommandHandler.h" | |
| #include "CommandHandlers/GetCurrentUrlCommandHandler.h" | |
| #include "CommandHandlers/GetCurrentWindowHandleCommandHandler.h" | |
| #include "CommandHandlers/GetElementAttributeCommandHandler.h" | |
| #include "CommandHandlers/GetElementLocationCommandHandler.h" | |
| #include "CommandHandlers/GetElementLocationOnceScrolledIntoViewCommandHandler.h" | |
| #include "CommandHandlers/GetElementSizeCommandHandler.h" | |
| #include "CommandHandlers/GetElementTagNameCommandHandler.h" | |
| #include "CommandHandlers/GetElementTextCommandHandler.h" | |
| #include "CommandHandlers/GetElementValueOfCssPropertyCommandHandler.h" | |
| #include "CommandHandlers/GetSessionCapabilitiesCommandHandler.h" | |
| #include "CommandHandlers/GetPageSourceCommandHandler.h" | |
| #include "CommandHandlers/GetTitleCommandHandler.h" | |
| #include "CommandHandlers/GetWindowPositionCommandHandler.h" | |
| #include "CommandHandlers/GetWindowSizeCommandHandler.h" | |
| #include "CommandHandlers/GoBackCommandHandler.h" | |
| #include "CommandHandlers/GoForwardCommandHandler.h" | |
| #include "CommandHandlers/GoToUrlCommandHandler.h" | |
| #include "CommandHandlers/IsElementDisplayedCommandHandler.h" | |
| #include "CommandHandlers/IsElementEnabledCommandHandler.h" | |
| #include "CommandHandlers/IsElementSelectedCommandHandler.h" | |
| #include "CommandHandlers/MaximizeWindowCommandHandler.h" | |
| #include "CommandHandlers/MouseMoveToCommandHandler.h" | |
| #include "CommandHandlers/MouseClickCommandHandler.h" | |
| #include "CommandHandlers/MouseDoubleClickCommandHandler.h" | |
| #include "CommandHandlers/MouseButtonDownCommandHandler.h" | |
| #include "CommandHandlers/MouseButtonUpCommandHandler.h" | |
| #include "CommandHandlers/NewSessionCommandHandler.h" | |
| #include "CommandHandlers/QuitCommandHandler.h" | |
| #include "CommandHandlers/RefreshCommandHandler.h" | |
| #include "CommandHandlers/ScreenshotCommandHandler.h" | |
| #include "CommandHandlers/SendKeysCommandHandler.h" | |
| #include "CommandHandlers/SendKeysToActiveElementCommandHandler.h" | |
| #include "CommandHandlers/SendKeysToAlertCommandHandler.h" | |
| #include "CommandHandlers/SetAsyncScriptTimeoutCommandHandler.h" | |
| #include "CommandHandlers/SetImplicitWaitTimeoutCommandHandler.h" | |
| #include "CommandHandlers/SetTimeoutCommandHandler.h" | |
| #include "CommandHandlers/SetWindowPositionCommandHandler.h" | |
| #include "CommandHandlers/SetWindowSizeCommandHandler.h" | |
| #include "CommandHandlers/SubmitElementCommandHandler.h" | |
| #include "CommandHandlers/SwitchToFrameCommandHandler.h" | |
| #include "CommandHandlers/SwitchToWindowCommandHandler.h" | |
| namespace webdriver { | |
| LRESULT IECommandExecutor::OnInit(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnInit"; | |
| // If we wanted to be a little more clever, we could create a struct | |
| // containing the HWND and the port number and pass them into the | |
| // ThreadProc via lpParameter and avoid this message handler altogether. | |
| this->port_ = (int)wParam; | |
| return 0; | |
| } | |
| LRESULT IECommandExecutor::OnCreate(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnCreate"; | |
| // NOTE: COM should be initialized on this thread, so we | |
| // could use CoCreateGuid() and StringFromGUID2() instead. | |
| UUID guid; | |
| RPC_WSTR guid_string = NULL; | |
| RPC_STATUS status = ::UuidCreate(&guid); | |
| status = ::UuidToString(&guid, &guid_string); | |
| // RPC_WSTR is currently typedef'd in RpcDce.h (pulled in by rpc.h) | |
| // as unsigned short*. It needs to be typedef'd as wchar_t* | |
| wchar_t* cast_guid_string = reinterpret_cast<wchar_t*>(guid_string); | |
| this->SetWindowText(cast_guid_string); | |
| std::string session_id = CW2A(cast_guid_string, CP_UTF8); | |
| this->session_id_ = session_id; | |
| this->is_valid_ = true; | |
| ::RpcStringFree(&guid_string); | |
| this->PopulateCommandHandlers(); | |
| this->PopulateElementFinderMethods(); | |
| this->current_browser_id_ = ""; | |
| this->serialized_response_ = ""; | |
| this->initial_browser_url_ = ""; | |
| this->ignore_protected_mode_settings_ = false; | |
| this->ignore_zoom_setting_ = false; | |
| this->enable_element_cache_cleanup_ = true; | |
| this->enable_persistent_hover_ = true; | |
| this->unexpected_alert_behavior_ = IGNORE_UNEXPECTED_ALERTS; | |
| this->speed_ = 0; | |
| this->implicit_wait_timeout_ = 0; | |
| this->async_script_timeout_ = -1; | |
| this->page_load_timeout_ = -1; | |
| this->input_manager_ = new InputManager(); | |
| this->input_manager_->Initialize(&this->managed_elements_); | |
| // Only execute atoms on a separate thread for IE 9 or below. | |
| // Attempting this on IE 10 crashes unpredictably at the moment | |
| // on Windows 8, and no one has a development environment available | |
| // to debug the issue. | |
| this->allow_asynchronous_javascript_ = this->factory_.browser_version() <= 9; | |
| return 0; | |
| } | |
| LRESULT IECommandExecutor::OnClose(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnClose"; | |
| this->managed_elements_.Clear(); | |
| delete this->input_manager_; | |
| this->DestroyWindow(); | |
| return 0; | |
| } | |
| LRESULT IECommandExecutor::OnDestroy(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnDestroy"; | |
| ::PostQuitMessage(0); | |
| return 0; | |
| } | |
| LRESULT IECommandExecutor::OnSetCommand(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnSetCommand"; | |
| LPCSTR json_command = reinterpret_cast<LPCSTR>(lParam); | |
| this->current_command_.Populate(json_command); | |
| return 0; | |
| } | |
| LRESULT IECommandExecutor::OnExecCommand(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnExecCommand"; | |
| this->DispatchCommand(); | |
| return 0; | |
| } | |
| LRESULT IECommandExecutor::OnGetResponseLength(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnGetResponseLength"; | |
| size_t response_length = 0; | |
| if (!this->is_waiting_) { | |
| response_length = this->serialized_response_.size(); | |
| } | |
| return response_length; | |
| } | |
| LRESULT IECommandExecutor::OnGetResponse(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnGetResponse"; | |
| LPSTR str = reinterpret_cast<LPSTR>(lParam); | |
| strcpy_s(str, | |
| this->serialized_response_.size() + 1, | |
| this->serialized_response_.c_str()); | |
| // Reset the serialized response for the next command. | |
| this->serialized_response_ = ""; | |
| return 0; | |
| } | |
| LRESULT IECommandExecutor::OnWait(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnWait"; | |
| BrowserHandle browser; | |
| int status_code = this->GetCurrentBrowser(&browser); | |
| if (status_code == SUCCESS && !browser->is_closing()) { | |
| if (this->page_load_timeout_ >= 0 && this->wait_timeout_ < clock()) { | |
| Response timeout_response; | |
| timeout_response.SetErrorResponse(ETIMEOUT, "Timed out waiting for page to load."); | |
| this->serialized_response_ = timeout_response.Serialize(); | |
| this->is_waiting_ = false; | |
| browser->set_wait_required(false); | |
| } else { | |
| this->is_waiting_ = !(browser->Wait()); | |
| if (this->is_waiting_) { | |
| // If we are still waiting, we need to wait a bit then post a message to | |
| // ourselves to run the wait again. However, we can't wait using Sleep() | |
| // on this thread. This call happens in a message loop, and we would be | |
| // unable to process the COM events in the browser if we put this thread | |
| // to sleep. | |
| unsigned int thread_id = 0; | |
| HANDLE thread_handle = reinterpret_cast<HANDLE>(_beginthreadex(NULL, | |
| 0, | |
| &IECommandExecutor::WaitThreadProc, | |
| (void *)this->m_hWnd, | |
| 0, | |
| &thread_id)); | |
| if (thread_handle != NULL) { | |
| ::CloseHandle(thread_handle); | |
| } | |
| } | |
| } | |
| } else { | |
| this->is_waiting_ = false; | |
| } | |
| return 0; | |
| } | |
| LRESULT IECommandExecutor::OnBrowserNewWindow(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnBrowserNewWindow"; | |
| IWebBrowser2* browser = this->factory_.CreateBrowser(); | |
| BrowserHandle new_window_wrapper(new Browser(browser, NULL, this->m_hWnd)); | |
| this->AddManagedBrowser(new_window_wrapper); | |
| LPSTREAM* stream = reinterpret_cast<LPSTREAM*>(lParam); | |
| HRESULT hr = ::CoMarshalInterThreadInterfaceInStream(IID_IWebBrowser2, | |
| browser, | |
| stream); | |
| return 0; | |
| } | |
| LRESULT IECommandExecutor::OnBrowserQuit(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnBrowserQuit"; | |
| LPCSTR str = reinterpret_cast<LPCSTR>(lParam); | |
| std::string browser_id(str); | |
| delete[] str; | |
| BrowserMap::iterator found_iterator = this->managed_browsers_.find(browser_id); | |
| if (found_iterator != this->managed_browsers_.end()) { | |
| this->managed_browsers_.erase(browser_id); | |
| if (this->managed_browsers_.size() == 0) { | |
| this->current_browser_id_ = ""; | |
| } | |
| } else { | |
| LOG(WARN) << "Unable to find browser to quit with ID " << browser_id; | |
| } | |
| return 0; | |
| } | |
| LRESULT IECommandExecutor::OnIsSessionValid(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnIsSessionValid"; | |
| return this->is_valid_ ? 1 : 0; | |
| } | |
| LRESULT IECommandExecutor::OnNewHtmlDialog(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandles) { | |
| LOG(TRACE) << "Entering IECommandExecutor::OnNewHtmlDialog"; | |
| HWND dialog_handle = reinterpret_cast<HWND>(lParam); | |
| BrowserMap::const_iterator it = this->managed_browsers_.begin(); | |
| for (; it != this->managed_browsers_.end(); ++it) { | |
| if (dialog_handle == it->second->window_handle()) { | |
| LOG(DEBUG) << "Dialog is equal to one managed browser"; | |
| return 0; | |
| } | |
| } | |
| CComPtr<IHTMLDocument2> document; | |
| if (this->factory_.GetDocumentFromWindowHandle(dialog_handle, &document)) { | |
| CComPtr<IHTMLWindow2> window; | |
| document->get_parentWindow(&window); | |
| this->AddManagedBrowser(BrowserHandle(new HtmlDialog(window, | |
| dialog_handle, | |
| this->m_hWnd))); | |
| } else { | |
| LOG(WARN) << "Unable to get document from dialog"; | |
| } | |
| return 0; | |
| } | |
| LRESULT IECommandExecutor::OnGetQuitStatus(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| return this->is_quitting_ && this->managed_browsers_.size() > 0 ? 1 : 0; | |
| } | |
| LRESULT IECommandExecutor::OnRefreshManagedElements(UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam, | |
| BOOL& bHandled) { | |
| if (this->enable_element_cache_cleanup_) { | |
| this->managed_elements_.ClearCache(); | |
| } | |
| return 0; | |
| } | |
| unsigned int WINAPI IECommandExecutor::WaitThreadProc(LPVOID lpParameter) { | |
| HWND window_handle = reinterpret_cast<HWND>(lpParameter); | |
| ::Sleep(WAIT_TIME_IN_MILLISECONDS); | |
| ::PostMessage(window_handle, WD_WAIT, NULL, NULL); | |
| return 0; | |
| } | |
| unsigned int WINAPI IECommandExecutor::ThreadProc(LPVOID lpParameter) { | |
| // Optional TODO: Create a struct to pass in via lpParameter | |
| // instead of just a pointer to an HWND. That way, we could | |
| // pass the mongoose server port via a single call, rather than | |
| // having to send an init message after the window is created. | |
| HWND *window_handle = reinterpret_cast<HWND*>(lpParameter); | |
| DWORD error = 0; | |
| HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); | |
| IECommandExecutor new_session; | |
| HWND session_window_handle = new_session.Create(HWND_MESSAGE, | |
| CWindow::rcDefault); | |
| if (session_window_handle == NULL) { | |
| error = ::GetLastError(); | |
| LOG(WARN) << "Unable to create new session: " << error; | |
| } | |
| MSG msg; | |
| ::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); | |
| // Return the HWND back through lpParameter, and signal that the | |
| // window is ready for messages. | |
| *window_handle = session_window_handle; | |
| HANDLE event_handle = ::OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME); | |
| if (event_handle != NULL) { | |
| ::SetEvent(event_handle); | |
| ::CloseHandle(event_handle); | |
| } | |
| // Run the message loop | |
| while (::GetMessage(&msg, NULL, 0, 0) > 0) { | |
| ::TranslateMessage(&msg); | |
| ::DispatchMessage(&msg); | |
| } | |
| ::CoUninitialize(); | |
| return 0; | |
| } | |
| void IECommandExecutor::DispatchCommand() { | |
| LOG(TRACE) << "Entering IECommandExecutor::DispatchCommand"; | |
| Response response(this->session_id_); | |
| CommandHandlerMap::const_iterator found_iterator = | |
| this->command_handlers_.find(this->current_command_.command_type()); | |
| if (found_iterator == this->command_handlers_.end()) { | |
| LOG(WARN) << "Unable to find command handler for " << this->current_command_.command_type(); | |
| response.SetErrorResponse(501, "Command not implemented"); | |
| } else { | |
| BrowserHandle browser; | |
| int status_code = SUCCESS; | |
| if (this->current_command_.command_type() != webdriver::CommandType::NewSession) { | |
| // There should never be a modal dialog or alert to check for if the command | |
| // is the "newSession" command. | |
| status_code = this->GetCurrentBrowser(&browser); | |
| if (status_code == SUCCESS) { | |
| bool alert_is_active = false; | |
| HWND alert_handle = browser->GetActiveDialogWindowHandle(); | |
| if (alert_handle != NULL) { | |
| // Found a window handle, make sure it's an actual alert, | |
| // and not a showModalDialog() window. | |
| vector<char> window_class_name(34); | |
| ::GetClassNameA(alert_handle, &window_class_name[0], 34); | |
| if (strcmp(ALERT_WINDOW_CLASS, &window_class_name[0]) == 0) { | |
| alert_is_active = true; | |
| } else { | |
| LOG(WARN) << "Found alert handle does not have a window class consistent with an alert"; | |
| } | |
| } else { | |
| LOG(DEBUG) << "No alert handle is found"; | |
| } | |
| if (alert_is_active) { | |
| Alert dialog(browser, alert_handle); | |
| std::string command_type = this->current_command_.command_type(); | |
| if (command_type == webdriver::CommandType::GetAlertText || | |
| command_type == webdriver::CommandType::SendKeysToAlert || | |
| command_type == webdriver::CommandType::AcceptAlert || | |
| command_type == webdriver::CommandType::DismissAlert) { | |
| LOG(DEBUG) << "Alert is detected, and the sent command is valid"; | |
| } else { | |
| LOG(DEBUG) << "Unexpected alert is detected, and the sent command is invalid when an alert is present"; | |
| std::string alert_text = dialog.GetText(); | |
| if (this->unexpected_alert_behavior_ == ACCEPT_UNEXPECTED_ALERTS) { | |
| LOG(DEBUG) << "Automatically accepting the alert"; | |
| dialog.Accept(); | |
| } else if (this->unexpected_alert_behavior_ == DISMISS_UNEXPECTED_ALERTS || command_type == webdriver::CommandType::Quit) { | |
| // If a quit command was issued, we should not ignore an unhandled | |
| // alert, even if the alert behavior is set to "ignore". | |
| LOG(DEBUG) << "Automatically dismissing the alert"; | |
| if (dialog.is_standard_alert()) { | |
| dialog.Dismiss(); | |
| } else { | |
| // The dialog was non-standard. The most common case of this is | |
| // an onBeforeUnload dialog, which must be accepted to continue. | |
| dialog.Accept(); | |
| } | |
| } | |
| if (command_type != webdriver::CommandType::Quit) { | |
| // To keep pace with what Firefox does, we'll return the text of the | |
| // alert in the error response. | |
| Json::Value response_value; | |
| response_value["message"] = "Modal dialog present"; | |
| response_value["alert"]["text"] = alert_text; | |
| response.SetResponse(EMODALDIALOGOPENED, response_value); | |
| this->serialized_response_ = response.Serialize(); | |
| return; | |
| } else { | |
| LOG(DEBUG) << "Quit command was issued. Continuing with command after automatically closing alert."; | |
| } | |
| } | |
| } | |
| } else { | |
| LOG(WARN) << "Unable to find current browser"; | |
| } | |
| } | |
| CommandHandlerHandle command_handler = found_iterator->second; | |
| command_handler->Execute(*this, this->current_command_, &response); | |
| status_code = this->GetCurrentBrowser(&browser); | |
| if (status_code == SUCCESS) { | |
| this->is_waiting_ = browser->wait_required(); | |
| if (this->is_waiting_) { | |
| if (this->page_load_timeout_ >= 0) { | |
| this->wait_timeout_ = clock() + (this->page_load_timeout_ / 1000 * CLOCKS_PER_SEC); | |
| } | |
| ::PostMessage(this->m_hWnd, WD_WAIT, NULL, NULL); | |
| } | |
| } else { | |
| if (this->current_command_.command_type() != webdriver::CommandType::Quit) { | |
| LOG(WARN) << "Unable to get current browser"; | |
| } | |
| } | |
| } | |
| this->serialized_response_ = response.Serialize(); | |
| } | |
| int IECommandExecutor::GetCurrentBrowser(BrowserHandle* browser_wrapper) const { | |
| LOG(TRACE) << "Entering IECommandExecutor::GetCurrentBrowser"; | |
| return this->GetManagedBrowser(this->current_browser_id_, browser_wrapper); | |
| } | |
| int IECommandExecutor::GetManagedBrowser(const std::string& browser_id, | |
| BrowserHandle* browser_wrapper) const { | |
| LOG(TRACE) << "Entering IECommandExecutor::GetManagedBrowser"; | |
| if (!this->is_valid()) { | |
| return ENOSUCHDRIVER; | |
| } | |
| if (browser_id == "") { | |
| LOG(WARN) << "Browser ID requested was an empty string"; | |
| return ENOSUCHWINDOW; | |
| } | |
| BrowserMap::const_iterator found_iterator = | |
| this->managed_browsers_.find(browser_id); | |
| if (found_iterator == this->managed_browsers_.end()) { | |
| LOG(WARN) << "Unable to find managed browser with id " << browser_id; | |
| return ENOSUCHWINDOW; | |
| } | |
| *browser_wrapper = found_iterator->second; | |
| return SUCCESS; | |
| } | |
| void IECommandExecutor::GetManagedBrowserHandles(std::vector<std::string>* managed_browser_handles) const { | |
| LOG(TRACE) << "Entering IECommandExecutor::GetManagedBrowserHandles"; | |
| BrowserMap::const_iterator it = this->managed_browsers_.begin(); | |
| for (; it != this->managed_browsers_.end(); ++it) { | |
| managed_browser_handles->push_back(it->first); | |
| // Look for browser windows created by showModalDialog(). | |
| it->second->GetActiveDialogWindowHandle(); | |
| } | |
| } | |
| void IECommandExecutor::AddManagedBrowser(BrowserHandle browser_wrapper) { | |
| LOG(TRACE) << "Entering IECommandExecutor::AddManagedBrowser"; | |
| this->managed_browsers_[browser_wrapper->browser_id()] = browser_wrapper; | |
| if (this->current_browser_id_ == "") { | |
| LOG(TRACE) << "Setting current browser id to " << browser_wrapper->browser_id(); | |
| this->current_browser_id_ = browser_wrapper->browser_id(); | |
| } | |
| } | |
| int IECommandExecutor::CreateNewBrowser(std::string* error_message) { | |
| LOG(TRACE) << "Entering IECommandExecutor::CreateNewBrowser"; | |
| vector<char> port_buffer(10); | |
| _itoa_s(this->port_, &port_buffer[0], 10, 10); | |
| std::string port(&port_buffer[0]); | |
| std::string initial_url = this->initial_browser_url_; | |
| if (this->initial_browser_url_ == "") { | |
| initial_url = "http://localhost:" + port + "/"; | |
| } | |
| DWORD process_id = this->factory_.LaunchBrowserProcess(initial_url, | |
| this->ignore_protected_mode_settings_, error_message); | |
| if (process_id == NULL) { | |
| LOG(WARN) << "Unable to launch browser, received NULL process ID"; | |
| this->is_waiting_ = false; | |
| return ENOSUCHDRIVER; | |
| } | |
| ProcessWindowInfo process_window_info; | |
| process_window_info.dwProcessId = process_id; | |
| process_window_info.hwndBrowser = NULL; | |
| process_window_info.pBrowser = NULL; | |
| bool attached = this->factory_.AttachToBrowser(&process_window_info, | |
| this->ignore_zoom_setting_, | |
| error_message); | |
| if (!attached) { | |
| LOG(WARN) << "Unable to attach to browser COM object"; | |
| this->is_waiting_ = false; | |
| return ENOSUCHDRIVER; | |
| } | |
| // Set persistent hover functionality in the interactions implementation. | |
| setEnablePersistentHover(this->enable_persistent_hover_); | |
| LOG(INFO) << "Persistent hovering set to: " << this->enable_persistent_hover_; | |
| if (!this->enable_persistent_hover_) { | |
| LOG(INFO) << "Stopping previously-running persistent event thread."; | |
| stopPersistentEventFiring(); | |
| } | |
| BrowserHandle wrapper(new Browser(process_window_info.pBrowser, | |
| process_window_info.hwndBrowser, | |
| this->m_hWnd)); | |
| this->AddManagedBrowser(wrapper); | |
| return SUCCESS; | |
| } | |
| int IECommandExecutor::GetManagedElement(const std::string& element_id, | |
| ElementHandle* element_wrapper) const { | |
| LOG(TRACE) << "Entering IECommandExecutor::GetManagedElement"; | |
| return this->managed_elements_.GetManagedElement(element_id, element_wrapper); | |
| } | |
| void IECommandExecutor::AddManagedElement(IHTMLElement* element, | |
| ElementHandle* element_wrapper) { | |
| LOG(TRACE) << "Entering IECommandExecutor::AddManagedElement"; | |
| BrowserHandle current_browser; | |
| this->GetCurrentBrowser(¤t_browser); | |
| this->managed_elements_.AddManagedElement(current_browser, element, element_wrapper); | |
| } | |
| void IECommandExecutor::RemoveManagedElement(const std::string& element_id) { | |
| LOG(TRACE) << "Entering IECommandExecutor::RemoveManagedElement"; | |
| this->managed_elements_.RemoveManagedElement(element_id); | |
| } | |
| void IECommandExecutor::ListManagedElements() { | |
| LOG(TRACE) << "Entering IECommandExecutor::ListManagedElements"; | |
| this->managed_elements_.ListManagedElements(); | |
| } | |
| int IECommandExecutor::GetElementFindMethod(const std::string& mechanism, | |
| std::wstring* translation) const { | |
| LOG(TRACE) << "Entering IECommandExecutor::GetElementFindMethod"; | |
| ElementFindMethodMap::const_iterator found_iterator = | |
| this->element_find_methods_.find(mechanism); | |
| if (found_iterator == this->element_find_methods_.end()) { | |
| LOG(WARN) << "Unable to determine find method " << mechanism; | |
| return EUNHANDLEDERROR; | |
| } | |
| *translation = found_iterator->second; | |
| return SUCCESS; | |
| } | |
| int IECommandExecutor::LocateElement(const ElementHandle parent_wrapper, | |
| const std::string& mechanism, | |
| const std::string& criteria, | |
| Json::Value* found_element) const { | |
| LOG(TRACE) << "Entering IECommandExecutor::LocateElement"; | |
| std::wstring mechanism_translation = L""; | |
| int status_code = this->GetElementFindMethod(mechanism, | |
| &mechanism_translation); | |
| if (status_code != SUCCESS) { | |
| LOG(WARN) << "Unable to determine mechanism translation for " << mechanism; | |
| return status_code; | |
| } | |
| std::wstring wide_criteria = CA2W(criteria.c_str(), CP_UTF8); | |
| return this->element_finder().FindElement(*this, | |
| parent_wrapper, | |
| mechanism_translation, | |
| wide_criteria, | |
| found_element); | |
| } | |
| int IECommandExecutor::LocateElements(const ElementHandle parent_wrapper, | |
| const std::string& mechanism, | |
| const std::string& criteria, | |
| Json::Value* found_elements) const { | |
| LOG(TRACE) << "Entering IECommandExecutor::LocateElements"; | |
| std::wstring mechanism_translation = L""; | |
| int status_code = this->GetElementFindMethod(mechanism, | |
| &mechanism_translation); | |
| if (status_code != SUCCESS) { | |
| LOG(WARN) << "Unable to determine mechanism translation for " << mechanism; | |
| return status_code; | |
| } | |
| std::wstring wide_criteria = CA2W(criteria.c_str(), CP_UTF8); | |
| return this->element_finder().FindElements(*this, | |
| parent_wrapper, | |
| mechanism_translation, | |
| wide_criteria, | |
| found_elements); | |
| } | |
| void IECommandExecutor::PopulateElementFinderMethods(void) { | |
| LOG(TRACE) << "Entering IECommandExecutor::PopulateElementFinderMethods"; | |
| this->element_find_methods_["id"] = L"id"; | |
| this->element_find_methods_["name"] = L"name"; | |
| this->element_find_methods_["tag name"] = L"tagName"; | |
| this->element_find_methods_["link text"] = L"linkText"; | |
| this->element_find_methods_["partial link text"] = L"partialLinkText"; | |
| this->element_find_methods_["class name"] = L"className"; | |
| this->element_find_methods_["xpath"] = L"xpath"; | |
| this->element_find_methods_["css selector"] = L"css"; | |
| } | |
| void IECommandExecutor::PopulateCommandHandlers() { | |
| LOG(TRACE) << "Entering IECommandExecutor::PopulateCommandHandlers"; | |
| this->command_handlers_[webdriver::CommandType::NoCommand] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetCurrentWindowHandle] = CommandHandlerHandle(new GetCurrentWindowHandleCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetWindowHandles] = CommandHandlerHandle(new GetAllWindowHandlesCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::SwitchToWindow] = CommandHandlerHandle(new SwitchToWindowCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::SwitchToFrame] = CommandHandlerHandle(new SwitchToFrameCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::Get] = CommandHandlerHandle(new GoToUrlCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GoForward] = CommandHandlerHandle(new GoForwardCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GoBack] = CommandHandlerHandle(new GoBackCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::Refresh] = CommandHandlerHandle(new RefreshCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::ImplicitlyWait] = CommandHandlerHandle(new SetImplicitWaitTimeoutCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::SetAsyncScriptTimeout] = CommandHandlerHandle(new SetAsyncScriptTimeoutCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::SetTimeout] = CommandHandlerHandle(new SetTimeoutCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::NewSession] = CommandHandlerHandle(new NewSessionCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetSessionCapabilities] = CommandHandlerHandle(new GetSessionCapabilitiesCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::Close] = CommandHandlerHandle(new CloseWindowCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::Quit] = CommandHandlerHandle(new QuitCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetTitle] = CommandHandlerHandle(new GetTitleCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetPageSource] = CommandHandlerHandle(new GetPageSourceCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetCurrentUrl] = CommandHandlerHandle(new GetCurrentUrlCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::ExecuteAsyncScript] = CommandHandlerHandle(new ExecuteAsyncScriptCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::ExecuteScript] = CommandHandlerHandle(new ExecuteScriptCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetActiveElement] = CommandHandlerHandle(new GetActiveElementCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::FindElement] = CommandHandlerHandle(new FindElementCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::FindElements] = CommandHandlerHandle(new FindElementsCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::FindChildElement] = CommandHandlerHandle(new FindChildElementCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::FindChildElements] = CommandHandlerHandle(new FindChildElementsCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetElementTagName] = CommandHandlerHandle(new GetElementTagNameCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetElementLocation] = CommandHandlerHandle(new GetElementLocationCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetElementSize] = CommandHandlerHandle(new GetElementSizeCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetElementLocationOnceScrolledIntoView] = CommandHandlerHandle(new GetElementLocationOnceScrolledIntoViewCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetElementAttribute] = CommandHandlerHandle(new GetElementAttributeCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetElementText] = CommandHandlerHandle(new GetElementTextCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetElementValueOfCssProperty] = CommandHandlerHandle(new GetElementValueOfCssPropertyCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::ClickElement] = CommandHandlerHandle(new ClickElementCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::ClearElement] = CommandHandlerHandle(new ClearElementCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::SubmitElement] = CommandHandlerHandle(new SubmitElementCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::IsElementDisplayed] = CommandHandlerHandle(new IsElementDisplayedCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::IsElementSelected] = CommandHandlerHandle(new IsElementSelectedCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::IsElementEnabled] = CommandHandlerHandle(new IsElementEnabledCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::SendKeysToElement] = CommandHandlerHandle(new SendKeysCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::ElementEquals] = CommandHandlerHandle(new ElementEqualsCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::AddCookie] = CommandHandlerHandle(new AddCookieCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetAllCookies] = CommandHandlerHandle(new GetAllCookiesCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::DeleteCookie] = CommandHandlerHandle(new DeleteCookieCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::DeleteAllCookies] = CommandHandlerHandle(new DeleteAllCookiesCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::Screenshot] = CommandHandlerHandle(new ScreenshotCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::AcceptAlert] = CommandHandlerHandle(new AcceptAlertCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::DismissAlert] = CommandHandlerHandle(new DismissAlertCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetAlertText] = CommandHandlerHandle(new GetAlertTextCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::SendKeysToAlert] = CommandHandlerHandle(new SendKeysToAlertCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::MouseMoveTo] = CommandHandlerHandle(new MouseMoveToCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::MouseClick] = CommandHandlerHandle(new MouseClickCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::MouseDoubleClick] = CommandHandlerHandle(new MouseDoubleClickCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::MouseButtonDown] = CommandHandlerHandle(new MouseButtonDownCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::MouseButtonUp] = CommandHandlerHandle(new MouseButtonUpCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::SendKeysToActiveElement] = CommandHandlerHandle(new SendKeysToActiveElementCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetWindowSize] = CommandHandlerHandle(new GetWindowSizeCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::SetWindowSize] = CommandHandlerHandle(new SetWindowSizeCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetWindowPosition] = CommandHandlerHandle(new GetWindowPositionCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::SetWindowPosition] = CommandHandlerHandle(new SetWindowPositionCommandHandler); | |
| this->command_handlers_[webdriver::CommandType::MaximizeWindow] = CommandHandlerHandle(new MaximizeWindowCommandHandler); | |
| // As-yet unimplemented commands | |
| this->command_handlers_[webdriver::CommandType::GetOrientation] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::SetOrientation] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::ListAvailableImeEngines] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetActiveImeEngine] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::IsImeActivated] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::ActivateImeEngine] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::DeactivateImeEngine] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::TouchClick] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::TouchDown] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::TouchUp] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::TouchMove] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::TouchScroll] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::TouchDoubleClick] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::TouchLongClick] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::TouchFlick] = CommandHandlerHandle(new IECommandHandler); | |
| // Commands intercepted by the server before reaching the command executor | |
| this->command_handlers_[webdriver::CommandType::Status] = CommandHandlerHandle(new IECommandHandler); | |
| this->command_handlers_[webdriver::CommandType::GetSessionList] = CommandHandlerHandle(new IECommandHandler); | |
| } | |
| } // namespace webdriver |