diff options
44 files changed, 1481 insertions, 1570 deletions
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 05c5876..3fae730 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -801,7 +801,6 @@ 'test/webdriver/cookie.cc', 'test/webdriver/dispatch.h', 'test/webdriver/dispatch.cc', - 'test/webdriver/error_codes.h', 'test/webdriver/frame_path.h', 'test/webdriver/frame_path.cc', 'test/webdriver/http_response.h', @@ -818,6 +817,8 @@ 'test/webdriver/session_manager.cc', 'test/webdriver/utility_functions.h', 'test/webdriver/utility_functions.cc', + 'test/webdriver/webdriver_error.h', + 'test/webdriver/webdriver_error.cc', 'test/webdriver/webdriver_key_converter.h', 'test/webdriver/webdriver_key_converter.cc', 'test/webdriver/web_element_id.h', @@ -850,8 +851,6 @@ 'test/webdriver/commands/set_timeout_commands.cc', 'test/webdriver/commands/source_command.h', 'test/webdriver/commands/source_command.cc', - 'test/webdriver/commands/speed_command.h', - 'test/webdriver/commands/speed_command.cc', 'test/webdriver/commands/target_locator_commands.h', 'test/webdriver/commands/target_locator_commands.cc', 'test/webdriver/commands/title_command.h', diff --git a/chrome/test/automation/automation_json_requests.cc b/chrome/test/automation/automation_json_requests.cc index fe664ec..b679691 100644 --- a/chrome/test/automation/automation_json_requests.cc +++ b/chrome/test/automation/automation_json_requests.cc @@ -18,7 +18,8 @@ namespace { bool SendAutomationJSONRequest(AutomationMessageSender* sender, const DictionaryValue& request_dict, - DictionaryValue* reply_dict) { + DictionaryValue* reply_dict, + std::string* error_msg) { std::string request, reply; base::JSONWriter::Write(&request_dict, false, &request); bool success = false; @@ -37,6 +38,7 @@ bool SendAutomationJSONRequest(AutomationMessageSender* sender, std::string command, error; request_dict.GetString("command", &command); dict->GetString("error", &error); + *error_msg = error; LOG(ERROR) << "JSON request failed: " << command << "\n" << " with error: " << error; return false; @@ -71,12 +73,13 @@ bool SendGetIndicesFromTabIdJSONRequest( AutomationMessageSender* sender, int tab_id, int* browser_index, - int* tab_index) { + int* tab_index, + std::string* error_msg) { DictionaryValue request_dict; request_dict.SetString("command", "GetIndicesFromTab"); request_dict.SetInteger("tab_id", tab_id); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, request_dict, &reply_dict)) + if (!SendAutomationJSONRequest(sender, request_dict, &reply_dict, error_msg)) return false; if (!reply_dict.GetInteger("windex", browser_index)) return false; @@ -89,12 +92,13 @@ bool SendGetIndicesFromTabHandleJSONRequest( AutomationMessageSender* sender, int tab_handle, int* browser_index, - int* tab_index) { + int* tab_index, + std::string* error_msg) { DictionaryValue request_dict; request_dict.SetString("command", "GetIndicesFromTab"); request_dict.SetInteger("tab_handle", tab_handle); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, request_dict, &reply_dict)) + if (!SendAutomationJSONRequest(sender, request_dict, &reply_dict, error_msg)) return false; if (!reply_dict.GetInteger("windex", browser_index)) return false; @@ -109,7 +113,8 @@ bool SendNavigateToURLJSONRequest( int tab_index, const GURL& url, int navigation_count, - AutomationMsg_NavigationResponseValues* nav_response) { + AutomationMsg_NavigationResponseValues* nav_response, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "NavigateToURL"); dict.SetInteger("windex", browser_index); @@ -117,7 +122,7 @@ bool SendNavigateToURLJSONRequest( dict.SetString("url", url.possibly_invalid_spec()); dict.SetInteger("navigation_count", navigation_count); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, dict, &reply_dict)) + if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) return false; int response = 0; if (!reply_dict.GetInteger("result", &response)) @@ -132,7 +137,8 @@ bool SendExecuteJavascriptJSONRequest( int tab_index, const std::string& frame_xpath, const std::string& javascript, - Value** result) { + Value** result, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "ExecuteJavascript"); dict.SetInteger("windex", browser_index); @@ -140,7 +146,7 @@ bool SendExecuteJavascriptJSONRequest( dict.SetString("frame_xpath", frame_xpath); dict.SetString("javascript", javascript); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, dict, &reply_dict)) + if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) return false; std::string json; @@ -166,44 +172,48 @@ bool SendExecuteJavascriptJSONRequest( bool SendGoForwardJSONRequest( AutomationMessageSender* sender, int browser_index, - int tab_index) { + int tab_index, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "GoForward"); dict.SetInteger("windex", browser_index); dict.SetInteger("tab_index", tab_index); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendGoBackJSONRequest( AutomationMessageSender* sender, int browser_index, - int tab_index) { + int tab_index, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "GoBack"); dict.SetInteger("windex", browser_index); dict.SetInteger("tab_index", tab_index); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendReloadJSONRequest( AutomationMessageSender* sender, int browser_index, - int tab_index) { + int tab_index, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "Reload"); dict.SetInteger("windex", browser_index); dict.SetInteger("tab_index", tab_index); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendCaptureEntirePageJSONRequest( AutomationMessageSender* sender, int browser_index, int tab_index, - const FilePath& path) { + const FilePath& path, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "CaptureEntirePage"); dict.SetInteger("windex", browser_index); @@ -211,20 +221,21 @@ bool SendCaptureEntirePageJSONRequest( dict.SetString("path", path.value()); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendGetTabURLJSONRequest( AutomationMessageSender* sender, int browser_index, int tab_index, - std::string* url) { + std::string* url, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "GetTabURL"); dict.SetInteger("windex", browser_index); dict.SetInteger("tab_index", tab_index); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, dict, &reply_dict)) + if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) return false; return reply_dict.GetString("url", url); } @@ -233,13 +244,14 @@ bool SendGetTabTitleJSONRequest( AutomationMessageSender* sender, int browser_index, int tab_index, - std::string* tab_title) { + std::string* tab_title, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "GetTabTitle"); dict.SetInteger("windex", browser_index); dict.SetInteger("tab_index", tab_index); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, dict, &reply_dict)) + if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) return false; return reply_dict.GetString("title", tab_title); } @@ -247,12 +259,13 @@ bool SendGetTabTitleJSONRequest( bool SendGetCookiesJSONRequest( AutomationMessageSender* sender, const std::string& url, - ListValue** cookies) { + ListValue** cookies, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "GetCookies"); dict.SetString("url", url); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, dict, &reply_dict)) + if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) return false; Value* cookies_unscoped_value; if (!reply_dict.Remove("cookies", &cookies_unscoped_value)) @@ -274,7 +287,8 @@ bool SendGetCookiesJSONRequestDeprecated( dict.SetInteger("windex", browser_index); dict.SetString("url", url); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, dict, &reply_dict)) + std::string error_msg; + if (!SendAutomationJSONRequest(sender, dict, &reply_dict, &error_msg)) return false; return reply_dict.GetString("cookies", cookies); } @@ -282,13 +296,14 @@ bool SendGetCookiesJSONRequestDeprecated( bool SendDeleteCookieJSONRequest( AutomationMessageSender* sender, const std::string& url, - const std::string& cookie_name) { + const std::string& cookie_name, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "DeleteCookie"); dict.SetString("url", url); dict.SetString("name", cookie_name); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendDeleteCookieJSONRequestDeprecated( @@ -302,19 +317,21 @@ bool SendDeleteCookieJSONRequestDeprecated( dict.SetString("url", url); dict.SetString("name", cookie_name); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + std::string error_msg; + return SendAutomationJSONRequest(sender, dict, &reply_dict, &error_msg); } bool SendSetCookieJSONRequest( AutomationMessageSender* sender, const std::string& url, - DictionaryValue* cookie_dict) { + DictionaryValue* cookie_dict, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "SetCookie"); dict.SetString("url", url); dict.Set("cookie", cookie_dict->DeepCopy()); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendSetCookieJSONRequestDeprecated( @@ -328,15 +345,18 @@ bool SendSetCookieJSONRequestDeprecated( dict.SetString("url", url); dict.SetString("cookie", cookie); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + std::string error_msg; + return SendAutomationJSONRequest(sender, dict, &reply_dict, &error_msg); } bool SendGetTabIdsJSONRequest( - AutomationMessageSender* sender, std::vector<int>* tab_ids) { + AutomationMessageSender* sender, + std::vector<int>* tab_ids, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "GetTabIds"); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, dict, &reply_dict)) + if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) return false; ListValue* id_list; if (!reply_dict.GetList("ids", &id_list)) { @@ -357,24 +377,30 @@ bool SendGetTabIdsJSONRequest( } bool SendIsTabIdValidJSONRequest( - AutomationMessageSender* sender, int tab_id, bool* is_valid) { + AutomationMessageSender* sender, + int tab_id, + bool* is_valid, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "IsTabIdValid"); dict.SetInteger("id", tab_id); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, dict, &reply_dict)) + if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) return false; return reply_dict.GetBoolean("is_valid", is_valid); } bool SendCloseTabJSONRequest( - AutomationMessageSender* sender, int browser_index, int tab_index) { + AutomationMessageSender* sender, + int browser_index, + int tab_index, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "CloseTab"); dict.SetInteger("windex", browser_index); dict.SetInteger("tab_index", tab_index); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendMouseMoveJSONRequest( @@ -382,7 +408,8 @@ bool SendMouseMoveJSONRequest( int browser_index, int tab_index, int x, - int y) { + int y, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "WebkitMouseMove"); dict.SetInteger("windex", browser_index); @@ -390,7 +417,7 @@ bool SendMouseMoveJSONRequest( dict.SetInteger("x", x); dict.SetInteger("y", y); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendMouseClickJSONRequest( @@ -399,8 +426,8 @@ bool SendMouseClickJSONRequest( int tab_index, automation::MouseButton button, int x, - int y) { - // TODO get rid of the evil flags. + int y, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "WebkitMouseClick"); dict.SetInteger("windex", browser_index); @@ -409,7 +436,7 @@ bool SendMouseClickJSONRequest( dict.SetInteger("x", x); dict.SetInteger("y", y); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendMouseDragJSONRequest( @@ -419,7 +446,8 @@ bool SendMouseDragJSONRequest( int start_x, int start_y, int end_x, - int end_y) { + int end_y, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "WebkitMouseDrag"); dict.SetInteger("windex", browser_index); @@ -429,7 +457,7 @@ bool SendMouseDragJSONRequest( dict.SetInteger("end_x", end_x); dict.SetInteger("end_y", end_y); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendMouseButtonDownJSONRequest( @@ -437,7 +465,8 @@ bool SendMouseButtonDownJSONRequest( int browser_index, int tab_index, int x, - int y) { + int y, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "WebkitMouseButtonDown"); dict.SetInteger("windex", browser_index); @@ -445,7 +474,7 @@ bool SendMouseButtonDownJSONRequest( dict.SetInteger("x", x); dict.SetInteger("y", y); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendMouseButtonUpJSONRequest( @@ -453,7 +482,8 @@ bool SendMouseButtonUpJSONRequest( int browser_index, int tab_index, int x, - int y) { + int y, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "WebkitMouseButtonUp"); dict.SetInteger("windex", browser_index); @@ -461,7 +491,7 @@ bool SendMouseButtonUpJSONRequest( dict.SetInteger("x", x); dict.SetInteger("y", y); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendMouseDoubleClickJSONRequest( @@ -469,7 +499,8 @@ bool SendMouseDoubleClickJSONRequest( int browser_index, int tab_index, int x, - int y) { + int y, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "WebkitMouseDoubleClick"); dict.SetInteger("windex", browser_index); @@ -477,14 +508,15 @@ bool SendMouseDoubleClickJSONRequest( dict.SetInteger("x", x); dict.SetInteger("y", y); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendWebKeyEventJSONRequest( AutomationMessageSender* sender, int browser_index, int tab_index, - const WebKeyEvent& key_event) { + const WebKeyEvent& key_event, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "SendWebkitKeyEvent"); dict.SetInteger("windex", browser_index); @@ -497,7 +529,7 @@ bool SendWebKeyEventJSONRequest( dict.SetInteger("modifiers", key_event.modifiers); dict.SetBoolean("isSystemKey", false); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendNativeKeyEventJSONRequest( @@ -505,7 +537,8 @@ bool SendNativeKeyEventJSONRequest( int browser_index, int tab_index, ui::KeyboardCode key_code, - int modifiers) { + int modifiers, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "SendOSLevelKeyEventToTab"); dict.SetInteger("windex", browser_index); @@ -513,55 +546,61 @@ bool SendNativeKeyEventJSONRequest( dict.SetInteger("keyCode", key_code); dict.SetInteger("modifiers", modifiers); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendGetAppModalDialogMessageJSONRequest( AutomationMessageSender* sender, - std::string* message) { + std::string* message, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "GetAppModalDialogMessage"); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, dict, &reply_dict)) + if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) return false; return reply_dict.GetString("message", message); } bool SendAcceptOrDismissAppModalDialogJSONRequest( AutomationMessageSender* sender, - bool accept) { + bool accept, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "AcceptOrDismissAppModalDialog"); dict.SetBoolean("accept", accept); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendAcceptPromptAppModalDialogJSONRequest( AutomationMessageSender* sender, - const std::string& prompt_text) { + const std::string& prompt_text, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "AcceptOrDismissAppModalDialog"); dict.SetBoolean("accept", true); dict.SetString("prompt_text", prompt_text); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendWaitForAllTabsToStopLoadingJSONRequest( - AutomationMessageSender* sender) { + AutomationMessageSender* sender, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "WaitForAllTabsToStopLoading"); DictionaryValue reply_dict; - return SendAutomationJSONRequest(sender, dict, &reply_dict); + return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); } bool SendGetChromeDriverAutomationVersion( - AutomationMessageSender* sender, int* version) { + AutomationMessageSender* sender, + int* version, + std::string* error_msg) { DictionaryValue dict; dict.SetString("command", "GetChromeDriverAutomationVersion"); DictionaryValue reply_dict; - if (!SendAutomationJSONRequest(sender, dict, &reply_dict)) + if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) return false; return reply_dict.GetInteger("version", version); } diff --git a/chrome/test/automation/automation_json_requests.h b/chrome/test/automation/automation_json_requests.h index 816445b..afa1937 100644 --- a/chrome/test/automation/automation_json_requests.h +++ b/chrome/test/automation/automation_json_requests.h @@ -50,7 +50,8 @@ bool SendGetIndicesFromTabIdJSONRequest( AutomationMessageSender* sender, int tab_id, int* browser_index, - int* tab_index) WARN_UNUSED_RESULT; + int* tab_index, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests the current browser and tab indices for the given |TabProxy| // handle. Returns true on success. @@ -58,7 +59,8 @@ bool SendGetIndicesFromTabHandleJSONRequest( AutomationMessageSender* sender, int tab_proxy_handle, int* browser_index, - int* tab_index) WARN_UNUSED_RESULT; + int* tab_index, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to navigate to the given url and wait for the given number of // navigations to complete. Returns true on success. @@ -68,7 +70,8 @@ bool SendNavigateToURLJSONRequest( int tab_index, const GURL& url, int navigation_count, - AutomationMsg_NavigationResponseValues* nav_response) WARN_UNUSED_RESULT; + AutomationMsg_NavigationResponseValues* nav_response, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests the given javascript to be executed in the frame specified by the // given xpath. Returns true on success. If true, |result| will be set to the @@ -79,28 +82,32 @@ bool SendExecuteJavascriptJSONRequest( int tab_index, const std::string& frame_xpath, const std::string& javascript, - Value** result) WARN_UNUSED_RESULT; + Value** result, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests the specified tab to go forward. Waits for the load to complete. // Returns true on success. bool SendGoForwardJSONRequest( AutomationMessageSender* sender, int browser_index, - int tab_index) WARN_UNUSED_RESULT; + int tab_index, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests the specified tab to go back. Waits for the load to complete. // Returns true on success. bool SendGoBackJSONRequest( AutomationMessageSender* sender, int browser_index, - int tab_index) WARN_UNUSED_RESULT; + int tab_index, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests the specified tab to reload. Waits for the load to complete. // Returns true on success. bool SendReloadJSONRequest( AutomationMessageSender* sender, int browser_index, - int tab_index) WARN_UNUSED_RESULT; + int tab_index, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests a snapshot of the entire page to be saved to the given path // in PNG format. @@ -109,21 +116,24 @@ bool SendCaptureEntirePageJSONRequest( AutomationMessageSender* sender, int browser_index, int tab_index, - const FilePath& path) WARN_UNUSED_RESULT; + const FilePath& path, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests the url of the specified tab. Returns true on success. bool SendGetTabURLJSONRequest( AutomationMessageSender* sender, int browser_index, int tab_index, - std::string* url) WARN_UNUSED_RESULT; + std::string* url, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests the title of the specified tab. Returns true on success. bool SendGetTabTitleJSONRequest( AutomationMessageSender* sender, int browser_index, int tab_index, - std::string* tab_title) WARN_UNUSED_RESULT; + std::string* tab_title, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests all the cookies for the given URL. On success returns true and // caller takes ownership of |cookies|, which is a list of all the cookies in @@ -131,7 +141,8 @@ bool SendGetTabTitleJSONRequest( bool SendGetCookiesJSONRequest( AutomationMessageSender* sender, const std::string& url, - ListValue** cookies) WARN_UNUSED_RESULT; + ListValue** cookies, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests all the cookies for the given URL. Returns true on success. // Use |SendGetCookiesJSONRequest| for chrome versions greater than 11. @@ -147,7 +158,8 @@ bool SendGetCookiesJSONRequestDeprecated( bool SendDeleteCookieJSONRequest( AutomationMessageSender* sender, const std::string& url, - const std::string& cookie_name) WARN_UNUSED_RESULT; + const std::string& cookie_name, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests deletion of the cookie with the given name and URL. Returns true // on success. Use |SendDeleteCookieJSONRequest| for chrome versions greater @@ -164,7 +176,8 @@ bool SendDeleteCookieJSONRequestDeprecated( bool SendSetCookieJSONRequest( AutomationMessageSender* sender, const std::string& url, - DictionaryValue* cookie_dict) WARN_UNUSED_RESULT; + DictionaryValue* cookie_dict, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests setting the given cookie for the given URL. Returns true on // success. Use |SendSetCookieJSONRequest| instead for chrome versions greater @@ -179,19 +192,22 @@ bool SendSetCookieJSONRequestDeprecated( // Requests the IDs for all open tabs. Returns true on success. bool SendGetTabIdsJSONRequest( AutomationMessageSender* sender, - std::vector<int>* tab_ids) WARN_UNUSED_RESULT; + std::vector<int>* tab_ids, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests whether the given tab ID is valid. Returns true on success. bool SendIsTabIdValidJSONRequest( AutomationMessageSender* sender, int tab_id, - bool* is_valid) WARN_UNUSED_RESULT; + bool* is_valid, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to close the given tab. Returns true on success. bool SendCloseTabJSONRequest( AutomationMessageSender* sender, int browser_index, - int tab_index) WARN_UNUSED_RESULT; + int tab_index, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to send the WebKit event for a mouse move to the given // coordinate in the specified tab. Returns true on success. @@ -200,7 +216,8 @@ bool SendMouseMoveJSONRequest( int browser_index, int tab_index, int x, - int y) WARN_UNUSED_RESULT; + int y, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to send the WebKit events for a mouse click at the given // coordinate in the specified tab. Returns true on success. @@ -210,7 +227,8 @@ bool SendMouseClickJSONRequest( int tab_index, automation::MouseButton button, int x, - int y) WARN_UNUSED_RESULT; + int y, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to send the WebKit events for a mouse drag from the start to end // coordinates given in the specified tab. Returns true on success. @@ -221,7 +239,8 @@ bool SendMouseDragJSONRequest( int start_x, int start_y, int end_x, - int end_y) WARN_UNUSED_RESULT; + int end_y, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to send the WebKit event for a mouse button down at the given // coordinate in the specified tab. Returns true on success. @@ -230,7 +249,8 @@ bool SendMouseButtonDownJSONRequest( int browser_index, int tab_index, int x, - int y) WARN_UNUSED_RESULT; + int y, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to send the WebKit event for a mouse button up at the given // coordinate in the specified tab. Returns true on success. @@ -239,7 +259,8 @@ bool SendMouseButtonUpJSONRequest( int browser_index, int tab_index, int x, - int y) WARN_UNUSED_RESULT; + int y, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to send the WebKit event for a mouse double click at the given // coordinate in the specified tab. Returns true on success. @@ -248,7 +269,8 @@ bool SendMouseDoubleClickJSONRequest( int browser_index, int tab_index, int x, - int y) WARN_UNUSED_RESULT; + int y, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to send the WebKit event for the given |WebKeyEvent| in a // specified tab. Returns true on success. @@ -256,7 +278,8 @@ bool SendWebKeyEventJSONRequest( AutomationMessageSender* sender, int browser_index, int tab_index, - const WebKeyEvent& key_event) WARN_UNUSED_RESULT; + const WebKeyEvent& key_event, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to send the key event for the given keycode+modifiers to a // browser window containing the specified tab. Returns true on success. @@ -265,34 +288,40 @@ bool SendNativeKeyEventJSONRequest( int browser_index, int tab_index, ui::KeyboardCode key_code, - int modifiers) WARN_UNUSED_RESULT; + int modifiers, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to get the active JavaScript modal dialog's message. Returns true // on success. bool SendGetAppModalDialogMessageJSONRequest( AutomationMessageSender* sender, - std::string* message) WARN_UNUSED_RESULT; + std::string* message, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to accept or dismiss the active JavaScript modal dialog. // Returns true on success. bool SendAcceptOrDismissAppModalDialogJSONRequest( AutomationMessageSender* sender, - bool accept) WARN_UNUSED_RESULT; + bool accept, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to accept the active JavaScript modal dialog with the given prompt // text. Returns true on success. bool SendAcceptPromptAppModalDialogJSONRequest( AutomationMessageSender* sender, - const std::string& prompt_text) WARN_UNUSED_RESULT; + const std::string& prompt_text, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests to wait for all tabs to stop loading. Returns true on success. bool SendWaitForAllTabsToStopLoadingJSONRequest( - AutomationMessageSender* sender) WARN_UNUSED_RESULT; + AutomationMessageSender* sender, + std::string* error_msg) WARN_UNUSED_RESULT; // Requests the version of ChromeDriver automation supported by the automation // server. Returns true on success. bool SendGetChromeDriverAutomationVersion( AutomationMessageSender* sender, - int* version) WARN_UNUSED_RESULT; + int* version, + std::string* error_msg) WARN_UNUSED_RESULT; #endif // CHROME_TEST_AUTOMATION_AUTOMATION_JSON_REQUESTS_H_ diff --git a/chrome/test/automation/tab_proxy.cc b/chrome/test/automation/tab_proxy.cc index ffc6db2..49cd00c 100644 --- a/chrome/test/automation/tab_proxy.cc +++ b/chrome/test/automation/tab_proxy.cc @@ -739,13 +739,14 @@ bool TabProxy::CaptureEntirePageAsPNG(const FilePath& path) { return false; int browser_index, tab_index; + std::string error_msg; if (!SendGetIndicesFromTabHandleJSONRequest( - sender_, handle_, &browser_index, &tab_index)) { + sender_, handle_, &browser_index, &tab_index, &error_msg)) { return false; } return SendCaptureEntirePageJSONRequest(sender_, browser_index, - tab_index, path); + tab_index, path, &error_msg); } #if defined(OS_WIN) diff --git a/chrome/test/webdriver/automation.cc b/chrome/test/webdriver/automation.cc index 8e53342..1a0f9d2 100644 --- a/chrome/test/webdriver/automation.cc +++ b/chrome/test/webdriver/automation.cc @@ -16,6 +16,7 @@ #include "base/json/json_writer.h" #include "base/logging.h" #include "base/path_service.h" +#include "base/stringprintf.h" #include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/common/automation_constants.h" @@ -26,6 +27,7 @@ #include "chrome/test/automation/automation_proxy.h" #include "chrome/test/automation/proxy_launcher.h" #include "chrome/test/webdriver/frame_path.h" +#include "chrome/test/webdriver/webdriver_error.h" #include "googleurl/src/gurl.h" #include "ui/gfx/point.h" @@ -119,21 +121,24 @@ Automation::Automation() {} Automation::~Automation() {} void Automation::Init(const CommandLine& options, - ErrorCode* code) { + Error** error) { FilePath browser_exe; if (!GetDefaultChromeExe(&browser_exe)) { - *code = kBrowserCouldNotBeFound; + *error = new Error(kUnknownError, "Could not find default Chrome binary"); return; } - InitWithBrowserPath(browser_exe, options, code); + InitWithBrowserPath(browser_exe, options, error); } void Automation::InitWithBrowserPath(const FilePath& browser_exe, const CommandLine& options, - ErrorCode* code) { + Error** error) { if (!file_util::PathExists(browser_exe)) { - *code = kBrowserCouldNotBeFound; + std::string message = base::StringPrintf( + "Could not find Chrome binary at: %" PRFilePath, + browser_exe.value().c_str()); + *error = new Error(kUnknownError, message); return; } @@ -160,17 +165,26 @@ void Automation::InitWithBrowserPath(const FilePath& browser_exe, }; if (!launcher_->LaunchBrowserAndServer(launch_props, true)) { - *code = kBrowserFailedToStart; + *error = new Error( + kUnknownError, + "Unable to either launch or connect to Chrome. Please check that " + "ChromeDriver is up-to-date"); return; } int version = 0; - if (!SendGetChromeDriverAutomationVersion(automation(), &version) || - version > automation::kChromeDriverAutomationVersion) { - *code = kIncompatibleBrowserVersion; + std::string error_msg; + if (!SendGetChromeDriverAutomationVersion( + automation(), &version, &error_msg)) { + *error = CreateChromeError(error_msg); + return; + } + if (version > automation::kChromeDriverAutomationVersion) { + *error = new Error( + kUnknownError, + "ChromeDriver is not compatible with this version of Chrome."); return; } - *code = kSuccess; } void Automation::Terminate() { @@ -183,194 +197,225 @@ void Automation::ExecuteScript(int tab_id, const FramePath& frame_path, const std::string& script, std::string* result, - bool* success) { + Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } Value* unscoped_value; + std::string error_msg; if (!SendExecuteJavascriptJSONRequest(automation(), windex, tab_index, frame_path.value(), script, - &unscoped_value)) { - *success = false; + &unscoped_value, &error_msg)) { + *error = CreateChromeError(error_msg); return; } scoped_ptr<Value> value(unscoped_value); - *success = value->GetAsString(result); + if (!value->GetAsString(result)) + *error = CreateChromeError("Execute script did not return string"); } void Automation::MouseMove(int tab_id, const gfx::Point& p, - bool* success) { + Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } - *success = SendMouseMoveJSONRequest( - automation(), windex, tab_index, p.x(), p.y()); + std::string error_msg; + if (!SendMouseMoveJSONRequest( + automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { + *error = CreateChromeError(error_msg); + } } void Automation::MouseClick(int tab_id, const gfx::Point& p, automation::MouseButton button, - bool* success) { + Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } - *success = SendMouseClickJSONRequest( - automation(), windex, tab_index, button, p.x(), p.y()); + std::string error_msg; + if (!SendMouseClickJSONRequest( + automation(), windex, tab_index, button, p.x(), p.y(), &error_msg)) { + *error = CreateChromeError(error_msg); + } } void Automation::MouseDrag(int tab_id, const gfx::Point& start, const gfx::Point& end, - bool* success) { + Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } - *success = SendMouseDragJSONRequest( - automation(), windex, tab_index, start.x(), start.y(), end.x(), end.y()); + std::string error_msg; + if (!SendMouseDragJSONRequest(automation(), windex, tab_index, start.x(), + start.y(), end.x(), end.y(), &error_msg)) { + *error = CreateChromeError(error_msg); + } } void Automation::MouseButtonUp(int tab_id, const gfx::Point& p, - bool* success) { + Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } - *success = SendMouseButtonUpJSONRequest( - automation(), windex, tab_index, p.x(), p.y()); + std::string error_msg; + if (!SendMouseButtonUpJSONRequest( + automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { + *error = CreateChromeError(error_msg); + } } void Automation::MouseButtonDown(int tab_id, const gfx::Point& p, - bool* success) { + Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } - *success = SendMouseButtonDownJSONRequest( - automation(), windex, tab_index, p.x(), p.y()); + std::string error_msg; + if (!SendMouseButtonDownJSONRequest( + automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { + *error = CreateChromeError(error_msg); + } } void Automation::MouseDoubleClick(int tab_id, const gfx::Point& p, - bool* success) { + Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } - *success = SendMouseDoubleClickJSONRequest( - automation(), windex, tab_index, p.x(), p.y()); + std::string error_msg; + if (!SendMouseDoubleClickJSONRequest( + automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { + *error = CreateChromeError(error_msg); + } } void Automation::SendWebKeyEvent(int tab_id, const WebKeyEvent& key_event, - bool* success) { + Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; + + std::string error_msg; + if (!SendWebKeyEventJSONRequest( + automation(), windex, tab_index, key_event, &error_msg)) { + *error = CreateChromeError(error_msg); } - *success = SendWebKeyEventJSONRequest( - automation(), windex, tab_index, key_event); } void Automation::SendNativeKeyEvent(int tab_id, ui::KeyboardCode key_code, int modifiers, - bool* success) { + Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; + + std::string error_msg; + if (!SendNativeKeyEventJSONRequest( + automation(), windex, tab_index, key_code, modifiers, &error_msg)) { + *error = CreateChromeError(error_msg); } - *success = SendNativeKeyEventJSONRequest( - automation(), windex, tab_index, key_code, modifiers); } void Automation::CaptureEntirePageAsPNG(int tab_id, const FilePath& path, - bool* success) { + Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } - *success = SendCaptureEntirePageJSONRequest( - automation(), windex, tab_index, path); + std::string error_msg; + if (!SendCaptureEntirePageJSONRequest( + automation(), windex, tab_index, path, &error_msg)) { + *error = CreateChromeError(error_msg); + } } void Automation::NavigateToURL(int tab_id, const std::string& url, - bool* success) { - int browser_index = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &browser_index, &tab_index)) { - *success = false; + Error** error) { + int windex = 0, tab_index = 0; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } AutomationMsg_NavigationResponseValues navigate_response; - if (!SendNavigateToURLJSONRequest(automation(), browser_index, tab_index, - GURL(url), 1, &navigate_response)) { - *success = false; + std::string error_msg; + if (!SendNavigateToURLJSONRequest(automation(), windex, tab_index, + GURL(url), 1, &navigate_response, + &error_msg)) { + *error = CreateChromeError(error_msg); return; } - *success = navigate_response != AUTOMATION_MSG_NAVIGATION_ERROR; + // TODO(kkania): Do not rely on this enum. + if (navigate_response == AUTOMATION_MSG_NAVIGATION_ERROR) + *error = new Error(kUnknownError, "Navigation error occurred"); } -void Automation::GoForward(int tab_id, bool* success) { +void Automation::GoForward(int tab_id, Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } - *success = SendGoForwardJSONRequest(automation(), windex, tab_index); + std::string error_msg; + if (!SendGoForwardJSONRequest( + automation(), windex, tab_index, &error_msg)) { + *error = CreateChromeError(error_msg); + } } -void Automation::GoBack(int tab_id, bool* success) { +void Automation::GoBack(int tab_id, Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } - *success = SendGoBackJSONRequest(automation(), windex, tab_index); + std::string error_msg; + if (!SendGoBackJSONRequest(automation(), windex, tab_index, &error_msg)) + *error = CreateChromeError(error_msg); } -void Automation::Reload(int tab_id, bool* success) { +void Automation::Reload(int tab_id, Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } - *success = SendReloadJSONRequest(automation(), windex, tab_index); + std::string error_msg; + if (!SendReloadJSONRequest(automation(), windex, tab_index, &error_msg)) + *error = CreateChromeError(error_msg); } void Automation::GetCookies(const std::string& url, ListValue** cookies, - bool* success) { - *success = SendGetCookiesJSONRequest(automation(), url, cookies); + Error** error) { + std::string error_msg; + if (!SendGetCookiesJSONRequest(automation(), url, cookies, &error_msg)) + *error = CreateChromeError(error_msg); } void Automation::GetCookiesDeprecated(int tab_id, @@ -378,7 +423,8 @@ void Automation::GetCookiesDeprecated(int tab_id, std::string* cookies, bool* success) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { + scoped_ptr<Error> error(GetIndicesForTab(tab_id, &windex, &tab_index)); + if (error.get()) { *success = false; return; } @@ -389,8 +435,12 @@ void Automation::GetCookiesDeprecated(int tab_id, void Automation::DeleteCookie(const std::string& url, const std::string& cookie_name, - bool* success) { - *success = SendDeleteCookieJSONRequest(automation(), url, cookie_name); + Error** error) { + std::string error_msg; + if (!SendDeleteCookieJSONRequest( + automation(), url, cookie_name, &error_msg)) { + *error = CreateChromeError(error_msg); + } } void Automation::DeleteCookieDeprecated(int tab_id, @@ -398,7 +448,8 @@ void Automation::DeleteCookieDeprecated(int tab_id, const std::string& cookie_name, bool* success) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { + scoped_ptr<Error> error(GetIndicesForTab(tab_id, &windex, &tab_index)); + if (error.get()) { *success = false; return; } @@ -412,8 +463,10 @@ void Automation::DeleteCookieDeprecated(int tab_id, void Automation::SetCookie(const std::string& url, DictionaryValue* cookie_dict, - bool* success) { - *success = SendSetCookieJSONRequest(automation(), url, cookie_dict); + Error** error) { + std::string error_msg; + if (!SendSetCookieJSONRequest(automation(), url, cookie_dict, &error_msg)) + *error = CreateChromeError(error_msg); } void Automation::SetCookieDeprecated(int tab_id, @@ -421,7 +474,8 @@ void Automation::SetCookieDeprecated(int tab_id, const std::string& cookie, bool* success) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { + scoped_ptr<Error> error(GetIndicesForTab(tab_id, &windex, &tab_index)); + if (error.get()) { *success = false; return; } @@ -434,63 +488,88 @@ void Automation::SetCookieDeprecated(int tab_id, } void Automation::GetTabIds(std::vector<int>* tab_ids, - bool* success) { - *success = SendGetTabIdsJSONRequest(automation(), tab_ids); + Error** error) { + std::string error_msg; + if (!SendGetTabIdsJSONRequest(automation(), tab_ids, &error_msg)) + *error = CreateChromeError(error_msg); } -void Automation::DoesTabExist(int tab_id, bool* does_exist, bool* success) { - *success = SendIsTabIdValidJSONRequest(automation(), tab_id, does_exist); +void Automation::DoesTabExist(int tab_id, bool* does_exist, Error** error) { + std::string error_msg; + if (!SendIsTabIdValidJSONRequest( + automation(), tab_id, does_exist, &error_msg)) { + *error = CreateChromeError(error_msg); + } } -void Automation::CloseTab(int tab_id, bool* success) { +void Automation::CloseTab(int tab_id, Error** error) { int windex = 0, tab_index = 0; - if (!GetIndicesForTab(tab_id, &windex, &tab_index)) { - *success = false; + *error = GetIndicesForTab(tab_id, &windex, &tab_index); + if (*error) return; - } - *success = SendCloseTabJSONRequest(automation(), windex, tab_index); + std::string error_msg; + if (!SendCloseTabJSONRequest(automation(), windex, tab_index, &error_msg)) + *error = CreateChromeError(error_msg); } -void Automation::GetAppModalDialogMessage(std::string* message, bool* success) { - *success = SendGetAppModalDialogMessageJSONRequest(automation(), message); +void Automation::GetAppModalDialogMessage(std::string* message, Error** error) { + std::string error_msg; + if (!SendGetAppModalDialogMessageJSONRequest( + automation(), message, &error_msg)) { + *error = CreateChromeError(error_msg); + } } -void Automation::AcceptOrDismissAppModalDialog(bool accept, bool* success) { - *success = SendAcceptOrDismissAppModalDialogJSONRequest( - automation(), accept); +void Automation::AcceptOrDismissAppModalDialog(bool accept, Error** error) { + std::string error_msg; + if (!SendAcceptOrDismissAppModalDialogJSONRequest( + automation(), accept, &error_msg)) { + *error = CreateChromeError(error_msg); + } } void Automation::AcceptPromptAppModalDialog(const std::string& prompt_text, - bool* success) { - *success = SendAcceptPromptAppModalDialogJSONRequest( - automation(), prompt_text); + Error** error) { + std::string error_msg; + if (!SendAcceptPromptAppModalDialogJSONRequest( + automation(), prompt_text, &error_msg)) { + *error = CreateChromeError(error_msg); + } } void Automation::GetBrowserVersion(std::string* version) { *version = automation()->server_version(); } -void Automation::GetChromeDriverAutomationVersion(int* version, bool* success) { - *success = SendGetChromeDriverAutomationVersion(automation(), version); +void Automation::GetChromeDriverAutomationVersion(int* version, Error** error) { + std::string error_msg; + if (!SendGetChromeDriverAutomationVersion(automation(), version, &error_msg)) + *error = CreateChromeError(error_msg); } -void Automation::WaitForAllTabsToStopLoading(bool* success) { - *success = SendWaitForAllTabsToStopLoadingJSONRequest(automation()); +void Automation::WaitForAllTabsToStopLoading(Error** error) { + std::string error_msg; + if (!SendWaitForAllTabsToStopLoadingJSONRequest(automation(), &error_msg)) + *error = CreateChromeError(error_msg); } AutomationProxy* Automation::automation() const { return launcher_->automation(); } -bool Automation::GetIndicesForTab( +Error* Automation::GetIndicesForTab( int tab_id, int* browser_index, int* tab_index) { - if (!SendGetIndicesFromTabIdJSONRequest(automation(), tab_id, - browser_index, tab_index)) { - LOG(ERROR) << "Could not get browser and tab indices for WebDriver tab id"; - return false; + std::string error_msg; + if (!SendGetIndicesFromTabIdJSONRequest( + automation(), tab_id, browser_index, tab_index, &error_msg)) { + return CreateChromeError(error_msg); } - return true; + return NULL; +} + +Error* Automation::CreateChromeError(const std::string& message) { + return new Error(kUnknownError, "Internal Chrome error: " + message); } } // namespace webdriver diff --git a/chrome/test/webdriver/automation.h b/chrome/test/webdriver/automation.h index 6b70f63..37d46fd 100644 --- a/chrome/test/webdriver/automation.h +++ b/chrome/test/webdriver/automation.h @@ -13,7 +13,6 @@ #include "base/memory/scoped_ptr.h" #include "base/task.h" #include "chrome/common/automation_constants.h" -#include "chrome/test/webdriver/error_codes.h" #include "ui/base/keycodes/keyboard_codes.h" class AutomationProxy; @@ -31,6 +30,7 @@ class Point; namespace webdriver { +class Error; class FramePath; // Creates and controls the Chrome instance. @@ -45,11 +45,10 @@ class Automation { // Creates a browser, using the specified |browser_exe|. void InitWithBrowserPath(const FilePath& browser_exe, const CommandLine& options, - ErrorCode* code); + Error** error); // Start the system's default Chrome binary. - void Init(const CommandLine& options, - ErrorCode* code); + void Init(const CommandLine& options, Error** error); // Terminates this session and disconnects its automation proxy. After // invoking this method, the Automation can safely be deleted. @@ -61,92 +60,93 @@ class Automation { const FramePath& frame_path, const std::string& script, std::string* result, - bool* success); + Error** error); // Sends a webkit key event to the current browser. Waits until the key has // been processed by the web page. void SendWebKeyEvent(int tab_id, const WebKeyEvent& key_event, - bool* success); + Error** error); // Sends an OS level key event to the current browser. Waits until the key // has been processed by the browser. void SendNativeKeyEvent(int tab_id, ui::KeyboardCode key_code, int modifiers, - bool* success); + Error** error); // Captures a snapshot of the tab to the specified path. The PNG will // contain the entire page, including what is not in the current view // on the screen. - void CaptureEntirePageAsPNG(int tab_id, const FilePath& path, bool* success); + void CaptureEntirePageAsPNG(int tab_id, const FilePath& path, Error** error); - void NavigateToURL(int tab_id, const std::string& url, bool* success); - void GoForward(int tab_id, bool* success); - void GoBack(int tab_id, bool* success); - void Reload(int tab_id, bool* success); + void NavigateToURL(int tab_id, const std::string& url, Error** error); + void GoForward(int tab_id, Error** error); + void GoBack(int tab_id, Error** error); + void Reload(int tab_id, Error** error); - void GetCookies(const std::string& url, ListValue** cookies, bool* success); + void GetCookies(const std::string& url, ListValue** cookies, Error** error); void GetCookiesDeprecated( int tab_id, const GURL& gurl, std::string* cookies, bool* success); void DeleteCookie(const std::string& url, const std::string& cookie_name, - bool* success); + Error** error); void DeleteCookieDeprecated(int tab_id, const GURL& gurl, const std::string& cookie_name, bool* success); void SetCookie( - const std::string& url, DictionaryValue* cookie_dict, bool* success); + const std::string& url, DictionaryValue* cookie_dict, Error** error); void SetCookieDeprecated( int tab_id, const GURL& gurl, const std::string& cookie, bool* success); - void MouseMove(int tab_id, const gfx::Point& p, bool* success); + void MouseMove(int tab_id, const gfx::Point& p, Error** error); void MouseClick(int tab_id, const gfx::Point& p, automation::MouseButton button, - bool* success); + Error** error); void MouseDrag(int tab_id, const gfx::Point& start, const gfx::Point& end, - bool* success); - void MouseButtonDown(int tab_id, const gfx::Point& p, bool* success); - void MouseButtonUp(int tab_id, const gfx::Point& p, bool* success); - void MouseDoubleClick(int tab_id, const gfx::Point& p, bool* success); + Error** error); + void MouseButtonDown(int tab_id, const gfx::Point& p, Error** error); + void MouseButtonUp(int tab_id, const gfx::Point& p, Error** error); + void MouseDoubleClick(int tab_id, const gfx::Point& p, Error** error); // Get persistent IDs for all the tabs currently open. These IDs can be used // to identify the tab as long as the tab exists. - void GetTabIds(std::vector<int>* tab_ids, bool* success); + void GetTabIds(std::vector<int>* tab_ids, Error** error); // Check if the given tab exists currently. - void DoesTabExist(int tab_id, bool* does_exist, bool* success); + void DoesTabExist(int tab_id, bool* does_exist, Error** error); - void CloseTab(int tab_id, bool* success); + void CloseTab(int tab_id, Error** error); // Gets the active JavaScript modal dialog's message. - void GetAppModalDialogMessage(std::string* message, bool* success); + void GetAppModalDialogMessage(std::string* message, Error** error); // Accepts or dismisses the active JavaScript modal dialog. - void AcceptOrDismissAppModalDialog(bool accept, bool* success); + void AcceptOrDismissAppModalDialog(bool accept, Error** error); // Accepts an active prompt JavaScript modal dialog, using the given // prompt text as the result of the prompt. void AcceptPromptAppModalDialog(const std::string& prompt_text, - bool* success); + Error** error); // Gets the version of the runing browser. void GetBrowserVersion(std::string* version); // Gets the ChromeDriver automation version supported by the automation // server. - void GetChromeDriverAutomationVersion(int* version, bool* success); + void GetChromeDriverAutomationVersion(int* version, Error** error); // Waits for all tabs to stop loading. - void WaitForAllTabsToStopLoading(bool* success); + void WaitForAllTabsToStopLoading(Error** error); private: AutomationProxy* automation() const; - bool GetIndicesForTab(int tab_id, int* browser_index, int* tab_index); + Error* GetIndicesForTab(int tab_id, int* browser_index, int* tab_index); + Error* CreateChromeError(const std::string& message); scoped_ptr<ProxyLauncher> launcher_; diff --git a/chrome/test/webdriver/commands/alert_commands.cc b/chrome/test/webdriver/commands/alert_commands.cc index 9fb7464..5b0df47 100644 --- a/chrome/test/webdriver/commands/alert_commands.cc +++ b/chrome/test/webdriver/commands/alert_commands.cc @@ -6,8 +6,8 @@ #include "base/values.h" #include "chrome/test/webdriver/commands/response.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { @@ -30,19 +30,24 @@ bool AlertTextCommand::DoesPost() { void AlertTextCommand::ExecuteGet(Response* const response) { std::string text; - ErrorCode code = session_->GetAlertMessage(&text); - if (code == kSuccess) - response->SetValue(Value::CreateStringValue(text)); - response->SetStatus(code); + Error* error = session_->GetAlertMessage(&text); + if (error) { + response->SetError(error); + return; + } + response->SetValue(Value::CreateStringValue(text)); } void AlertTextCommand::ExecutePost(Response* const response) { std::string text; if (!GetStringParameter("text", &text)) { - SET_WEBDRIVER_ERROR(response, "'text' is missing or invalid", kBadRequest); + response->SetError(new Error( + kBadRequest, "'text' is missing or invalid")); return; } - response->SetStatus(session_->SetAlertPromptText(text)); + Error* error = session_->SetAlertPromptText(text); + if (error) + response->SetError(error); } AcceptAlertCommand::AcceptAlertCommand( @@ -59,7 +64,9 @@ bool AcceptAlertCommand::DoesPost() { } void AcceptAlertCommand::ExecutePost(Response* const response) { - response->SetStatus(session_->AcceptOrDismissAlert(true)); + Error* error = session_->AcceptOrDismissAlert(true); + if (error) + response->SetError(error); } DismissAlertCommand::DismissAlertCommand( @@ -76,7 +83,9 @@ bool DismissAlertCommand::DoesPost() { } void DismissAlertCommand::ExecutePost(Response* const response) { - response->SetStatus(session_->AcceptOrDismissAlert(false)); + Error* error = session_->AcceptOrDismissAlert(false); + if (error) + response->SetError(error); } } // namespace webdriver diff --git a/chrome/test/webdriver/commands/cookie_commands.cc b/chrome/test/webdriver/commands/cookie_commands.cc index 3b6c725..657cd9f 100644 --- a/chrome/test/webdriver/commands/cookie_commands.cc +++ b/chrome/test/webdriver/commands/cookie_commands.cc @@ -33,16 +33,16 @@ CookieCommand::~CookieCommand() {} bool CookieCommand::Init(Response* const response) { if (!WebDriverCommand::Init(response)) return false; - if (!session_->CompareBrowserVersion(kNewInterfaceBuildNo, 0, - &uses_new_interface_)) { - SET_WEBDRIVER_ERROR(response, "Failed to check Chrome version number", - kUnknownError); + + Error* error = session_->CompareBrowserVersion( + kNewInterfaceBuildNo, 0, &uses_new_interface_); + if (error) { + response->SetError(error); return false; } - ErrorCode code = session_->GetURL(¤t_url_); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Failed to query current page URL", - code); + error = session_->GetURL(¤t_url_); + if (error) { + response->SetError(error); return false; } return true; @@ -63,9 +63,10 @@ bool CookieCommand::DoesPost() { void CookieCommand::ExecuteGet(Response* const response) { if (uses_new_interface_) { ListValue* cookies; - if (!session_->GetCookies(current_url_.possibly_invalid_spec(), &cookies)) { - SET_WEBDRIVER_ERROR(response, "Failed to fetch cookies", - kUnknownError); + Error* error = session_->GetCookies(current_url_.possibly_invalid_spec(), + &cookies); + if (error) { + response->SetError(error); return; } response->SetStatus(kSuccess); @@ -74,8 +75,7 @@ void CookieCommand::ExecuteGet(Response* const response) { std::string cookies; std::vector<std::string> tokens; if (!session_->GetCookiesDeprecated(current_url_, &cookies)) { - SET_WEBDRIVER_ERROR(response, "Failed to fetch cookies", - kUnknownError); + response->SetError(new Error(kUnknownError, "Failed to fetch cookies")); return; } // Note that ';' separates cookies while ':' separates name/value pairs. @@ -87,9 +87,7 @@ void CookieCommand::ExecuteGet(Response* const response) { if (cookie.valid()) { cookie_list->Append(cookie.ToDictionary()); } else { - LOG(ERROR) << "Failed to parse cookie: " << *i; - SET_WEBDRIVER_ERROR(response, "Could not get all cookies", - kInternalServerError); + response->SetError(new Error(kUnknownError, "Failed to parse cookies")); return; } } @@ -104,9 +102,7 @@ void CookieCommand::ExecutePost(Response* const response) { // Check to see if the cookie was passed in as a JSON onject. if (!GetDictionaryParameter("cookie", &cookie_dict)) { - // No valid cookie sent. - SET_WEBDRIVER_ERROR(response, "Cookie key not found", - kBadRequest); + response->SetError(new Error(kBadRequest, "Cookie key not found")); return; } @@ -116,18 +112,18 @@ void CookieCommand::ExecutePost(Response* const response) { std::vector<std::string> split_domain; base::SplitString(domain, ':', &split_domain); if (split_domain.size() > 2) { - SET_WEBDRIVER_ERROR(response, "Cookie domain has too many colons", - kInvalidCookieDomain); + response->SetError(new Error( + kInvalidCookieDomain, "Cookie domain has too many colons")); return; } else if (split_domain.size() == 2) { // Remove the port number. cookie_dict->SetString("domain", split_domain[0]); } } - if (!session_->SetCookie(current_url_.possibly_invalid_spec(), - cookie_dict)) { - SET_WEBDRIVER_ERROR(response, "Failed to set cookie", - kUnableToSetCookie); + Error* error = session_->SetCookie( + current_url_.possibly_invalid_spec(), cookie_dict); + if (error) { + response->SetError(error); return; } } else { @@ -135,14 +131,12 @@ void CookieCommand::ExecutePost(Response* const response) { // Make sure the cookie is formated preoperly. if (!cookie.valid()) { - SET_WEBDRIVER_ERROR(response, "Invalid cookie", - kBadRequest); + response->SetError(new Error(kBadRequest, "Invalid cookie")); return; } if (!session_->SetCookieDeprecated(current_url_, cookie.ToString())) { - SET_WEBDRIVER_ERROR(response, "Failed to set cookie", - kUnableToSetCookie); + response->SetError(new Error(kUnableToSetCookie, "Failed to set cookie")); return; } response->SetValue(new StringValue(cookie.ToString())); @@ -153,32 +147,31 @@ void CookieCommand::ExecutePost(Response* const response) { void CookieCommand::ExecuteDelete(Response* const response) { if (uses_new_interface_) { ListValue* unscoped_cookies; - if (!session_->GetCookies(current_url_.possibly_invalid_spec(), - &unscoped_cookies)) { - SET_WEBDRIVER_ERROR(response, "Failed to fetch cookies", - kUnknownError); + Error* error = session_->GetCookies( + current_url_.possibly_invalid_spec(), &unscoped_cookies); + if (error) { + response->SetError(error); return; } scoped_ptr<ListValue> cookies(unscoped_cookies); for (size_t i = 0; i < cookies->GetSize(); ++i) { DictionaryValue* cookie_dict; if (!cookies->GetDictionary(i, &cookie_dict)) { - SET_WEBDRIVER_ERROR(response, "GetCookies returned non-dict type", - kUnknownError); + response->SetError(new Error( + kUnknownError, "GetCookies returned non-dict type")); return; } std::string name; if (!cookie_dict->GetString("name", &name)) { - SET_WEBDRIVER_ERROR( - response, - "GetCookies returned cookie with missing or invalid 'name'", - kUnknownError); + response->SetError(new Error( + kUnknownError, + "GetCookies returned cookie with missing or invalid 'name'")); return; } - if (!session_->DeleteCookie(current_url_.possibly_invalid_spec(), - name)) { - SET_WEBDRIVER_ERROR(response, "Could not delete all cookies", - kUnknownError); + Error* error = session_->DeleteCookie( + current_url_.possibly_invalid_spec(), name); + if (error) { + response->SetError(error); return; } } @@ -187,8 +180,8 @@ void CookieCommand::ExecuteDelete(Response* const response) { std::vector<std::string> tokens; if (!session_->GetCookiesDeprecated(current_url_, &cookies)) { - SET_WEBDRIVER_ERROR(response, "Failed to fetch cookies", - kUnableToSetCookie); + response->SetError(new Error( + kUnableToSetCookie, "Failed to fetch cookies")); return; } @@ -199,16 +192,12 @@ void CookieCommand::ExecuteDelete(Response* const response) { if (cookie.valid()) { if (!session_->DeleteCookie(current_url_.possibly_invalid_spec(), cookie.name())) { - VLOG(1) << "Could not delete cookie: " << cookie.name() << "\n" - << "Contents of cookie: " << cookie.ToString(); - SET_WEBDRIVER_ERROR(response, "Could not delete all cookies", - kInternalServerError); + response->SetError(new Error( + kUnknownError, "Could not delete all cookies")); return; } } else { - LOG(ERROR) << "Failed to parse cookie: " << *i; - SET_WEBDRIVER_ERROR(response, "Could not delete all cookies", - kInternalServerError); + response->SetError(new Error(kUnknownError, "Failed to parse cookie")); return; } } @@ -228,17 +217,16 @@ bool NamedCookieCommand::Init(Response* const response) { if (!WebDriverCommand::Init(response)) return false; - if (!session_->CompareBrowserVersion(kNewInterfaceBuildNo, 0, - &uses_new_interface_)) { - SET_WEBDRIVER_ERROR(response, "Failed to check Chrome version number", - kUnknownError); + Error* error = session_->CompareBrowserVersion( + kNewInterfaceBuildNo, 0, &uses_new_interface_); + if (error) { + response->SetError(error); return false; } - ErrorCode code = session_->GetURL(¤t_url_); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Failed to query current page URL", - code); + error = session_->GetURL(¤t_url_); + if (error) { + response->SetError(error); return false; } @@ -246,8 +234,7 @@ bool NamedCookieCommand::Init(Response* const response) { // /session/:sessionId/cookie/:name cookie_name_ = GetPathVariable(4); if (cookie_name_ == "") { - SET_WEBDRIVER_ERROR(response, "No cookie name specified", - kBadRequest); + response->SetError(new Error(kBadRequest, "No cookie name specified")); return false; } @@ -260,17 +247,15 @@ bool NamedCookieCommand::DoesDelete() { void NamedCookieCommand::ExecuteDelete(Response* const response) { if (uses_new_interface_) { - if (!session_->DeleteCookie(current_url_.possibly_invalid_spec(), - cookie_name_)) { - SET_WEBDRIVER_ERROR(response, - "Failed to delete cookie", - kUnknownError); + Error* error = session_->DeleteCookie( + current_url_.possibly_invalid_spec(), cookie_name_); + if (error) { + response->SetError(error); return; } } else { if (!session_->DeleteCookieDeprecated(current_url_, cookie_name_)) { - SET_WEBDRIVER_ERROR(response, "Failed to delete cookie", - kUnknownError); + response->SetError(new Error(kUnknownError, "Failed to delete cookie")); return; } } diff --git a/chrome/test/webdriver/commands/create_session.cc b/chrome/test/webdriver/commands/create_session.cc index c2f37e2..d6bab1c 100644 --- a/chrome/test/webdriver/commands/create_session.cc +++ b/chrome/test/webdriver/commands/create_session.cc @@ -16,12 +16,10 @@ #include "chrome/test/webdriver/commands/response.h" #include "chrome/test/webdriver/session.h" #include "chrome/test/webdriver/session_manager.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { -// The minimum supported version of Chrome for this version of ChromeDriver. -const int kMinSupportedChromeVersion = 12; - CreateSession::CreateSession(const std::vector<std::string>& path_segments, const DictionaryValue* const parameters) : Command(path_segments, parameters) {} @@ -46,9 +44,8 @@ void CreateSession::ExecutePost(Response* const response) { while (i != added_options->end_keys()) { FilePath::StringType value; if (!added_options->GetString(*i, &value)) { - SET_WEBDRIVER_ERROR(response, - "Invalid format for added options to browser", - kBadRequest); + response->SetError(new Error( + kBadRequest, "Invalid format for added options to browser")); return; } else { if (!value.empty()) { @@ -57,7 +54,7 @@ void CreateSession::ExecutePost(Response* const response) { options.AppendSwitch(*i); } } - ++i; + ++i; } FilePath::StringType path; desiredCapabilities->GetString("chrome.binary", &path); @@ -66,33 +63,9 @@ void CreateSession::ExecutePost(Response* const response) { // Session manages its own liftime, so do not call delete. Session* session = new Session(); - ErrorCode code = session->Init(user_browser_exe, options); - - if (code == kBrowserCouldNotBeFound) { - SET_WEBDRIVER_ERROR(response, - "Chrome could not be found.", - kUnknownError); - return; - } else if (code == kBrowserFailedToStart) { - std::string error_msg = base::StringPrintf( - "Chrome could not be started successfully. " - "Please update ChromeDriver and ensure you are using Chrome %d+.", - kMinSupportedChromeVersion); - SET_WEBDRIVER_ERROR(response, error_msg, kUnknownError); - return; - } else if (code == kIncompatibleBrowserVersion) { - std::string error_msg = base::StringPrintf( - "Version of Chrome is incompatible with version of ChromeDriver. " - "Please update ChromeDriver and ensure you are using Chrome %d+.", - kMinSupportedChromeVersion); - SET_WEBDRIVER_ERROR(response, error_msg, kUnknownError); - return; - } else if (code != kSuccess) { - std::string error_msg = base::StringPrintf( - "Unknown error while initializing session. " - "Ensure ChromeDriver is up-to-date and Chrome is version %d+.", - kMinSupportedChromeVersion); - SET_WEBDRIVER_ERROR(response, error_msg, kUnknownError); + Error* error = session->Init(user_browser_exe, options); + if (error) { + response->SetError(error); return; } diff --git a/chrome/test/webdriver/commands/create_session.h b/chrome/test/webdriver/commands/create_session.h index d401a7f..6595ae2 100644 --- a/chrome/test/webdriver/commands/create_session.h +++ b/chrome/test/webdriver/commands/create_session.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,7 +9,6 @@ #include <vector> #include "chrome/test/webdriver/commands/command.h" -#include "chrome/test/webdriver/commands/webdriver_command.h" namespace webdriver { @@ -37,4 +36,3 @@ class CreateSession : public Command { } // namespace webdriver #endif // CHROME_TEST_WEBDRIVER_COMMANDS_CREATE_SESSION_H_ - diff --git a/chrome/test/webdriver/commands/execute_async_script_command.cc b/chrome/test/webdriver/commands/execute_async_script_command.cc index 9d5e370..747640e 100644 --- a/chrome/test/webdriver/commands/execute_async_script_command.cc +++ b/chrome/test/webdriver/commands/execute_async_script_command.cc @@ -6,8 +6,8 @@ #include "base/values.h" #include "chrome/test/webdriver/commands/response.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { @@ -25,24 +25,26 @@ bool ExecuteAsyncScriptCommand::DoesPost() { void ExecuteAsyncScriptCommand::ExecutePost(Response* const response) { std::string script; if (!GetStringParameter("script", &script)) { - SET_WEBDRIVER_ERROR(response, "No script to execute specified", - kBadRequest); + response->SetError(new Error( + kBadRequest, "No script to execute specified")); return; } ListValue* args; if (!GetListParameter("args", &args)) { - SET_WEBDRIVER_ERROR(response, "No script arguments specified", - kBadRequest); + response->SetError(new Error( + kBadRequest, "No script arguments specified")); return; } Value* result = NULL; - ErrorCode status = session_->ExecuteAsyncScript( + Error* error = session_->ExecuteAsyncScript( session_->current_target(), script, args, &result); - response->SetStatus(status); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } } // namspace webdriver - diff --git a/chrome/test/webdriver/commands/execute_command.cc b/chrome/test/webdriver/commands/execute_command.cc index e22264b..89bec72 100644 --- a/chrome/test/webdriver/commands/execute_command.cc +++ b/chrome/test/webdriver/commands/execute_command.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,15 +7,12 @@ #include <string> #include "base/values.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" #include "chrome/test/webdriver/commands/response.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { -const char kArgs[] = "args"; -const char kScript[] = "script"; - ExecuteCommand::ExecuteCommand(const std::vector<std::string>& path_segments, const DictionaryValue* const parameters) : WebDriverCommand(path_segments, parameters) {} @@ -28,28 +25,25 @@ bool ExecuteCommand::DoesPost() { void ExecuteCommand::ExecutePost(Response* const response) { std::string script; - if (!GetStringParameter(kScript, &script)) { - SET_WEBDRIVER_ERROR(response, "No script to execute specified", - kBadRequest); + if (!GetStringParameter("script", &script)) { + response->SetError(new Error(kBadRequest, "No script specified")); return; } ListValue* args; - if (!GetListParameter(kArgs, &args)) { - SET_WEBDRIVER_ERROR(response, "No script arguments specified", - kBadRequest); + if (!GetListParameter("args", &args)) { + response->SetError(new Error( + kBadRequest, "No script arguments specified")); return; } Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, args, &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } -bool ExecuteCommand::RequiresValidTab() { - return true; -} - } // namspace webdriver - diff --git a/chrome/test/webdriver/commands/execute_command.h b/chrome/test/webdriver/commands/execute_command.h index a9f3fa2..c164b78 100644 --- a/chrome/test/webdriver/commands/execute_command.h +++ b/chrome/test/webdriver/commands/execute_command.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -30,12 +30,9 @@ class ExecuteCommand : public WebDriverCommand { virtual void ExecutePost(Response* const response); private: - virtual bool RequiresValidTab(); - DISALLOW_COPY_AND_ASSIGN(ExecuteCommand); }; } // namespace webdriver #endif // CHROME_TEST_WEBDRIVER_COMMANDS_EXECUTE_COMMAND_H_ - diff --git a/chrome/test/webdriver/commands/find_element_commands.cc b/chrome/test/webdriver/commands/find_element_commands.cc index a40be0b..b0589bd 100644 --- a/chrome/test/webdriver/commands/find_element_commands.cc +++ b/chrome/test/webdriver/commands/find_element_commands.cc @@ -6,9 +6,9 @@ #include "base/values.h" #include "chrome/test/webdriver/commands/response.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" #include "chrome/test/webdriver/web_element_id.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { @@ -29,12 +29,12 @@ void FindElementCommand::ExecutePost(Response* const response) { std::string locator, query; if (!GetStringParameter("using", &locator) || !GetStringParameter("value", &query)) { - SET_WEBDRIVER_ERROR(response, - "Request is missing required 'using' and/or 'value' data", kBadRequest); + response->SetError(new Error( + kBadRequest, + "Request is missing required 'using' and/or 'value' data")); return; } - // TODO(jmikhail): The findElement(s) atom should handle this conversion. if (locator == "class name") { locator = LocatorType::kClassName; } else if (locator == "css selector") { @@ -53,25 +53,29 @@ void FindElementCommand::ExecutePost(Response* const response) { // "/session/$session/element/$id/element(s)" WebElementId root_element(GetPathVariable(4)); - ErrorCode code = kUnknownError; if (find_one_element_) { WebElementId element; - code = session_->FindElement( + Error* error = session_->FindElement( session_->current_target(), root_element, locator, query, &element); - if (code == kSuccess) - response->SetValue(element.ToValue()); + if (error) { + response->SetError(error); + return; + } + response->SetValue(element.ToValue()); } else { std::vector<WebElementId> elements; - code = session_->FindElements( + Error* error = session_->FindElements( session_->current_target(), root_element, locator, query, &elements); - if (code == kSuccess) { - ListValue* element_list = new ListValue(); - for (size_t i = 0; i < elements.size(); ++i) - element_list->Append(elements[i].ToValue()); - response->SetValue(element_list); + if (error) { + response->SetError(error); + return; } + ListValue* element_list = new ListValue(); + for (size_t i = 0; i < elements.size(); ++i) + element_list->Append(elements[i].ToValue()); + response->SetValue(element_list); } - response->SetStatus(code); + response->SetStatus(kSuccess); } } // namespace webdriver diff --git a/chrome/test/webdriver/commands/find_element_commands.h b/chrome/test/webdriver/commands/find_element_commands.h index 4cf987e..46dfbae 100644 --- a/chrome/test/webdriver/commands/find_element_commands.h +++ b/chrome/test/webdriver/commands/find_element_commands.h @@ -8,7 +8,6 @@ #include <string> #include <vector> -#include "chrome/test/webdriver/commands/command.h" #include "chrome/test/webdriver/commands/webdriver_command.h" namespace webdriver { @@ -68,4 +67,3 @@ class FindManyElementsCommand : public FindElementCommand { } // namespace webdriver #endif // CHROME_TEST_WEBDRIVER_COMMANDS_FIND_ELEMENT_COMMANDS_H_ - diff --git a/chrome/test/webdriver/commands/mouse_commands.cc b/chrome/test/webdriver/commands/mouse_commands.cc index 34281b1..c331cbc 100644 --- a/chrome/test/webdriver/commands/mouse_commands.cc +++ b/chrome/test/webdriver/commands/mouse_commands.cc @@ -7,17 +7,19 @@ #include "base/values.h" #include "chrome/common/automation_constants.h" #include "chrome/test/webdriver/commands/response.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" #include "chrome/test/webdriver/web_element_id.h" +#include "chrome/test/webdriver/webdriver_error.h" #include "ui/gfx/point.h" #include "ui/gfx/size.h" namespace { -static const int kLeftButton = 0; -static const int kMiddleButton = 1; -static const int kRightButton = 2; -} + +const int kLeftButton = 0; +const int kMiddleButton = 1; +const int kRightButton = 2; + +} // namespace namespace webdriver { @@ -33,40 +35,32 @@ bool ElementMouseCommand::DoesPost() { } void ElementMouseCommand::ExecutePost(Response* response) { - bool is_displayed; - ErrorCode code = session_->IsElementDisplayed( - session_->current_target(), element, &is_displayed); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Failed to determine element visibility", - code); - return; - } - if (!is_displayed) { - SET_WEBDRIVER_ERROR(response, "Element must be displayed", - kElementNotVisible); + Error* error = session_->CheckElementPreconditionsForClicking(element); + if (error) { + response->SetError(error); return; } gfx::Point location; - code = session_->GetElementLocationInView(element, &location); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Failed to compute element location.", - code); + error = session_->GetElementLocationInView(element, &location); + if (error) { + response->SetError(error); return; } gfx::Size size; - code = session_->GetElementSize(session_->current_target(), element, &size); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Failed to compute element size.", code); + error = session_->GetElementSize(session_->current_target(), element, &size); + if (error) { + response->SetError(error); return; } location.Offset(size.width() / 2, size.height() / 2); - if (!Action(location, response)) + error = Action(location); + if (error) { + response->SetError(error); return; - - response->SetStatus(kSuccess); + } } MoveAndClickCommand::MoveAndClickCommand( @@ -76,17 +70,8 @@ MoveAndClickCommand::MoveAndClickCommand( MoveAndClickCommand::~MoveAndClickCommand() {} -bool MoveAndClickCommand::Action(const gfx::Point& location, - Response* const response) { - VLOG(1) << "Mouse click at: (" << location.x() << ", " - << location.y() << ")" << std::endl; - if (!session_->MouseMoveAndClick(location, automation::kLeftButton)) { - SET_WEBDRIVER_ERROR(response, "Performing mouse operation failed", - kUnknownError); - return false; - } - - return true; +Error* MoveAndClickCommand::Action(const gfx::Point& location) { + return session_->MouseMoveAndClick(location, automation::kLeftButton); } HoverCommand::HoverCommand(const std::vector<std::string>& path_segments, @@ -95,17 +80,8 @@ HoverCommand::HoverCommand(const std::vector<std::string>& path_segments, HoverCommand::~HoverCommand() {} -bool HoverCommand::Action(const gfx::Point& location, - Response* const response) { - VLOG(1) << "Mouse hover at: (" << location.x() << ", " - << location.y() << ")" << std::endl; - if (!session_->MouseMove(location)) { - SET_WEBDRIVER_ERROR(response, "Performing mouse operation failed", - kUnknownError); - return false; - } - - return true; +Error* HoverCommand::Action(const gfx::Point& location) { + return session_->MouseMove(location); } DragCommand::DragCommand(const std::vector<std::string>& path_segments, @@ -120,37 +96,21 @@ bool DragCommand::Init(Response* const response) { if (!GetIntegerParameter("x", &drag_x_) || !GetIntegerParameter("y", &drag_y_)) { - SET_WEBDRIVER_ERROR(response, - "Request is missing the required positional data", - kBadRequest); + response->SetError(new Error(kBadRequest, "Missing (x,y) coordinates")); return false; } return true; } -bool DragCommand::Action(const gfx::Point& location, Response* const response) { +Error* DragCommand::Action(const gfx::Point& location) { gfx::Point drag_from(location); gfx::Point drag_to(drag_from); drag_to.Offset(drag_x_, drag_y_); - if (drag_to.x() < 0 || drag_to.y() < 0) { - SET_WEBDRIVER_ERROR(response, "Invalid pos to drag to", kBadRequest); - return false; - } + if (drag_to.x() < 0 || drag_to.y() < 0) + return new Error(kBadRequest, "Invalid (x,y) coordinates"); - // click on the element - VLOG(1) << "Dragging mouse from: " - << "(" << location.x() << ", " << location.y() << ") " - << "to: (" << drag_to.x() << ", " << drag_to.y() << ")" - << std::endl; - if (!session_->MouseDrag(location, drag_to)) { - SET_WEBDRIVER_ERROR(response, - "Request is missing the required positional data", - kBadRequest); - return false; - } - - return true; + return session_->MouseDrag(location, drag_to); } AdvancedMouseCommand::AdvancedMouseCommand( @@ -187,9 +147,8 @@ bool MoveToCommand::Init(Response* const response) { GetIntegerParameter("yoffset", &y_offset_); if (!has_element_ && !has_offset_) { - SET_WEBDRIVER_ERROR(response, - "Request is missing the required data", - kBadRequest); + response->SetError(new Error( + kBadRequest, "Invalid command arguments")); return false; } @@ -201,63 +160,45 @@ void MoveToCommand::ExecutePost(Response* const response) { if (has_element_) { // If an element is specified, calculate the coordinate. - bool is_displayed; - ErrorCode code = session_->IsElementDisplayed(session_->current_target(), - element_, &is_displayed); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Failed to determine element visibility", - code); + Error* error = session_->CheckElementPreconditionsForClicking(element_); + if (error) { + response->SetError(error); return; } - if (!is_displayed) { - SET_WEBDRIVER_ERROR(response, "Element must be displayed", - kElementNotVisible); + error = session_->GetElementLocationInView(element_, &location); + if (error) { + response->SetError(error); return; } - - code = session_->GetElementLocationInView(element_, &location); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Failed to compute element location.", - code); - return; - } - - VLOG(1) << "An element requested. x:" << location.x() << " y:" - << location.y(); - } else { // If not, use the current mouse position. - VLOG(1) << "No element requested, using current mouse position"; location = session_->get_mouse_position(); } if (has_offset_) { // If an offset is specified, translate by the offset. location.Offset(x_offset_, y_offset_); - - VLOG(1) << "An offset requested. x:" << x_offset_ << " y:" << y_offset_; - } else { DCHECK(has_element_); // If not, calculate the half of the element size and translate by it. gfx::Size size; - ErrorCode code = session_->GetElementSize(session_->current_target(), - element_, &size); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Failed to compute element size.", code); + Error* error = session_->GetElementSize(session_->current_target(), + element_, &size); + if (error) { + response->SetError(error); return; } location.Offset(size.width() / 2, size.height() / 2); - - VLOG(1) << "No offset requested. The element size is " << size.width() - << "x" << size.height(); } - VLOG(1) << "Mouse moved to: (" << location.x() << ", " << location.y() << ")"; - session_->MouseMove(location); + Error* error = session_->MouseMove(location); + if (error) { + response->SetError(error); + return; + } } ClickCommand::ClickCommand(const std::vector<std::string>& path_segments, @@ -271,9 +212,7 @@ bool ClickCommand::Init(Response* const response) { return false; if (!GetIntegerParameter("button", &button_)) { - SET_WEBDRIVER_ERROR(response, - "Request is missing the required button data", - kBadRequest); + response->SetError(new Error(kBadRequest, "Missing mouse button argument")); return false; } @@ -290,11 +229,15 @@ void ClickCommand::ExecutePost(Response* const response) { } else if (button_ == kRightButton) { button = automation::kRightButton; } else { - SET_WEBDRIVER_ERROR(response, "Invalid button", kBadRequest); + response->SetError(new Error(kBadRequest, "Invalid mouse button")); return; } - session_->MouseClick(button); + Error* error = session_->MouseClick(button); + if (error) { + response->SetError(error); + return; + } } ButtonDownCommand::ButtonDownCommand( @@ -326,7 +269,11 @@ DoubleClickCommand::DoubleClickCommand( DoubleClickCommand::~DoubleClickCommand() {} void DoubleClickCommand::ExecutePost(Response* const response) { - session_->MouseDoubleClick(); + Error* error = session_->MouseDoubleClick(); + if (error) { + response->SetError(error); + return; + } } } // namespace webdriver diff --git a/chrome/test/webdriver/commands/mouse_commands.h b/chrome/test/webdriver/commands/mouse_commands.h index 4510ccf..cc6f931 100644 --- a/chrome/test/webdriver/commands/mouse_commands.h +++ b/chrome/test/webdriver/commands/mouse_commands.h @@ -9,11 +9,17 @@ #include <vector> #include "chrome/test/webdriver/commands/webelement_commands.h" +#include "chrome/test/webdriver/web_element_id.h" class DictionaryValue; +namespace gfx { +class Point; +} + namespace webdriver { +class Error; class Response; // Base class for the following API command classes. @@ -28,7 +34,7 @@ class ElementMouseCommand : public WebElementCommand { virtual bool DoesPost(); virtual void ExecutePost(Response* const response); - virtual bool Action(const gfx::Point& location, Response* const response) = 0; + virtual Error* Action(const gfx::Point& location) = 0; private: DISALLOW_COPY_AND_ASSIGN(ElementMouseCommand); @@ -46,7 +52,7 @@ class MoveAndClickCommand : public ElementMouseCommand { const DictionaryValue* const parameters); virtual ~MoveAndClickCommand(); - virtual bool Action(const gfx::Point& location, Response* const response); + virtual Error* Action(const gfx::Point& location); private: DISALLOW_COPY_AND_ASSIGN(MoveAndClickCommand); @@ -60,7 +66,7 @@ class HoverCommand : public ElementMouseCommand { const DictionaryValue* const parameters); virtual ~HoverCommand(); - virtual bool Action(const gfx::Point& location, Response* const response); + virtual Error* Action(const gfx::Point& location); private: DISALLOW_COPY_AND_ASSIGN(HoverCommand); @@ -76,7 +82,7 @@ class DragCommand : public ElementMouseCommand { virtual ~DragCommand(); virtual bool Init(Response* const response); - virtual bool Action(const gfx::Point& location, Response* const response); + virtual Error* Action(const gfx::Point& location); private: int drag_x_, drag_y_; diff --git a/chrome/test/webdriver/commands/navigate_commands.cc b/chrome/test/webdriver/commands/navigate_commands.cc index ffc5396..f61ed85 100644 --- a/chrome/test/webdriver/commands/navigate_commands.cc +++ b/chrome/test/webdriver/commands/navigate_commands.cc @@ -1,10 +1,12 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/test/webdriver/commands/navigate_commands.h" #include "chrome/test/webdriver/commands/response.h" +#include "chrome/test/webdriver/session.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { @@ -19,16 +21,9 @@ bool ForwardCommand::DoesPost() { } void ForwardCommand::ExecutePost(Response* const response) { - if (!session_->GoForward()) { - SET_WEBDRIVER_ERROR(response, "GoForward failed", kInternalServerError); - return; - } - - response->SetStatus(kSuccess); -} - -bool ForwardCommand::RequiresValidTab() { - return true; + Error* error = session_->GoForward(); + if (error) + response->SetError(error); } BackCommand::BackCommand(const std::vector<std::string>& path_segments, @@ -42,16 +37,9 @@ bool BackCommand::DoesPost() { } void BackCommand::ExecutePost(Response* const response) { - if (!session_->GoBack()) { - SET_WEBDRIVER_ERROR(response, "GoBack failed", kInternalServerError); - return; - } - - response->SetStatus(kSuccess); -} - -bool BackCommand::RequiresValidTab() { - return true; + Error* error = session_->GoBack(); + if (error) + response->SetError(error); } RefreshCommand::RefreshCommand(const std::vector<std::string>& path_segments, @@ -65,16 +53,9 @@ bool RefreshCommand::DoesPost() { } void RefreshCommand::ExecutePost(Response* const response) { - if (!session_->Reload()) { - SET_WEBDRIVER_ERROR(response, "Reload failed", kInternalServerError); - return; - } - - response->SetStatus(kSuccess); -} - -bool RefreshCommand::RequiresValidTab() { - return true; + Error* error = session_->Reload(); + if (error) + response->SetError(error); } } // namespace webdriver diff --git a/chrome/test/webdriver/commands/navigate_commands.h b/chrome/test/webdriver/commands/navigate_commands.h index c4960f9..a5777b22 100644 --- a/chrome/test/webdriver/commands/navigate_commands.h +++ b/chrome/test/webdriver/commands/navigate_commands.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -26,8 +26,6 @@ class ForwardCommand : public WebDriverCommand { virtual void ExecutePost(Response* const response); private: - virtual bool RequiresValidTab(); - DISALLOW_COPY_AND_ASSIGN(ForwardCommand); }; @@ -43,8 +41,6 @@ class BackCommand : public WebDriverCommand { virtual void ExecutePost(Response* const response); private: - virtual bool RequiresValidTab(); - DISALLOW_COPY_AND_ASSIGN(BackCommand); }; @@ -60,12 +56,9 @@ class RefreshCommand : public WebDriverCommand { virtual void ExecutePost(Response* const response); private: - virtual bool RequiresValidTab(); - DISALLOW_COPY_AND_ASSIGN(RefreshCommand); }; } // namespace webdriver #endif // CHROME_TEST_WEBDRIVER_COMMANDS_NAVIGATE_COMMANDS_H_ - diff --git a/chrome/test/webdriver/commands/response.cc b/chrome/test/webdriver/commands/response.cc index bb711efa..0060fa0 100644 --- a/chrome/test/webdriver/commands/response.cc +++ b/chrome/test/webdriver/commands/response.cc @@ -57,49 +57,15 @@ void Response::SetValue(Value* value) { data_.Set(kValueKey, value); } -void Response::SetError(ErrorCode error_code, const std::string& message, - const std::string& file, int line) { - DictionaryValue* error = new DictionaryValue; - error->SetString(kMessageKey, message); - - DictionaryValue* stack = new DictionaryValue; - stack->SetString(kStackTraceFileNameKey, file); - stack->SetString(kStackTraceClassNameKey, ""); - stack->SetString(kStackTraceMethodNameKey, ""); - stack->SetInteger(kStackTraceLineNumberKey, line); - ListValue* stack_list = new ListValue; - stack_list->Append(stack); - error->Set(kStackTraceKey, stack_list); - - SetStatus(error_code); - SetValue(error); -} +void Response::SetError(Error* error) { + DictionaryValue* error_dict = new DictionaryValue(); + error_dict->SetString(kMessageKey, error->ToString()); -void Response::SetError(ErrorCode error_code, - const std::string& message, - const std::string& file, - int line, - const std::string& png) { - DictionaryValue* error = new DictionaryValue; - - error->SetString(kMessageKey, message); - error->SetString(kStackTraceFileNameKey, file); - error->SetInteger(kStackTraceLineNumberKey, line); - std::string base64_png; - - // Convert the raw binary data to base 64 encoding for webdriver. - if (!base::Base64Encode(png, &base64_png)) { - LOG(ERROR) << "Failed to encode screenshot to base64 " - << "sending back an empty string instead."; - } else { - error->SetString(kScreenKey, base64_png); - } - - SetStatus(error_code); - SetValue(error); + SetStatus(error->code()); + SetValue(error_dict); + delete error; } - void Response::SetField(const std::string& key, Value* value) { data_.Set(key, value); } diff --git a/chrome/test/webdriver/commands/response.h b/chrome/test/webdriver/commands/response.h index 678851f..9c44e60 100644 --- a/chrome/test/webdriver/commands/response.h +++ b/chrome/test/webdriver/commands/response.h @@ -9,23 +9,10 @@ #include <string> #include "base/values.h" -#include "chrome/test/webdriver/error_codes.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { -// All errors in webdriver must use this macro in order to send back -// a proper stack trace to the client. -#define SET_WEBDRIVER_ERROR(response, msg, err) \ - response->SetError(err, msg, __FILE__, __LINE__); \ - LOG(ERROR) << msg - -// Error which need to send back a screenshot should use this macro. -// |png| needs to be a string which contains the raw binary data of -// the PNG file. -#define SET_WEBDRIVER_ERROR_WITH_SCREENSHOT(response, msg, err , png) \ - response->SetError(err, msg, __FILE__, __LINE__, png); \ - LOG(ERROR) << msg - // A simple class that encapsulates the information describing the response to // a |Command|. In Webdriver all responses must be sent back as a JSON value, // conforming to the spec found at: @@ -47,21 +34,9 @@ class Response { // process. void SetValue(Value* value); - // Configures this response to report an error. The |file| and |line| - // parameters, which identify where in the source the error occurred, can be - // set using the |SET_WEBDRIVER_ERROR| macro above. - void SetError(ErrorCode error, const std::string& message, - const std::string& file, int line); - - // Configures this response to report an error. The |file| and |line| - // parameters, which identify where in the source the error occurred, can be - // set using the |SET_WEBDRIVER_ERROR_WITH_SCREENSHOT| macro above. Includes - // a screen shot of the tab which caused the error. - void SetError(ErrorCode error, - const std::string& message, - const std::string& file, - int line, - const std::string& png); + // Configures this response to report the given error. Ownership of the error + // is taken from the caller. + void SetError(Error* error); // Sets a JSON field in this response. The |key| may be a "." delimitted // string to indicate the value should be set in a nested object. Any @@ -81,4 +56,3 @@ class Response { } // namespace webdriver #endif // CHROME_TEST_WEBDRIVER_COMMANDS_RESPONSE_H_ - diff --git a/chrome/test/webdriver/commands/screenshot_command.cc b/chrome/test/webdriver/commands/screenshot_command.cc index bec6d98..352b062 100644 --- a/chrome/test/webdriver/commands/screenshot_command.cc +++ b/chrome/test/webdriver/commands/screenshot_command.cc @@ -10,8 +10,8 @@ #include "base/base64.h" #include "base/values.h" #include "chrome/test/webdriver/commands/response.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { @@ -27,23 +27,21 @@ bool ScreenshotCommand::DoesGet() { void ScreenshotCommand::ExecuteGet(Response* const response) { std::string raw_bytes; - if (!session_->GetScreenShot(&raw_bytes)) { - SET_WEBDRIVER_ERROR(response, "Screenshot of current page failed", - kInternalServerError); + Error* error = session_->GetScreenShot(&raw_bytes); + if (error) { + response->SetError(error); return; } // Convert the raw binary data to base 64 encoding for webdriver. std::string base64_screenshot; if (!base::Base64Encode(raw_bytes, &base64_screenshot)) { - SET_WEBDRIVER_ERROR(response, "Encoding the PNG to base64 format failed", - kInternalServerError); + response->SetError(new Error( + kUnknownError, "Encoding the PNG to base64 format failed")); return; } response->SetValue(new StringValue(base64_screenshot)); - response->SetStatus(kSuccess); } } // namespace webdriver - diff --git a/chrome/test/webdriver/commands/session_with_id.cc b/chrome/test/webdriver/commands/session_with_id.cc index 651a1cc..5889be4 100644 --- a/chrome/test/webdriver/commands/session_with_id.cc +++ b/chrome/test/webdriver/commands/session_with_id.cc @@ -11,7 +11,6 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/common/chrome_constants.h" #include "chrome/test/webdriver/commands/response.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" #include "chrome/test/webdriver/session_manager.h" @@ -56,18 +55,12 @@ void SessionWithID::ExecuteGet(Response* const response) { temp_value->SetString("chrome.automationVersion", chrome::kChromeVersion); temp_value->SetBoolean("chrome.nativeEvents", session_->use_native_events()); - response->SetStatus(kSuccess); response->SetValue(temp_value); } void SessionWithID::ExecuteDelete(Response* const response) { // Session manages its own lifetime, so do not call delete. session_->Terminate(); - response->SetStatus(kSuccess); -} - -bool SessionWithID::RequiresValidTab() { - return false; } } // namespace webdriver diff --git a/chrome/test/webdriver/commands/session_with_id.h b/chrome/test/webdriver/commands/session_with_id.h index 4b03cda..e634c65 100644 --- a/chrome/test/webdriver/commands/session_with_id.h +++ b/chrome/test/webdriver/commands/session_with_id.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -35,12 +35,9 @@ class SessionWithID : public WebDriverCommand { virtual void ExecuteDelete(Response* const response); private: - virtual bool RequiresValidTab(); - DISALLOW_COPY_AND_ASSIGN(SessionWithID); }; } // namespace webdriver #endif // CHROME_TEST_WEBDRIVER_COMMANDS_SESSION_WITH_ID_H_ - diff --git a/chrome/test/webdriver/commands/set_timeout_commands.cc b/chrome/test/webdriver/commands/set_timeout_commands.cc index 92f68f5..73d55aa 100644 --- a/chrome/test/webdriver/commands/set_timeout_commands.cc +++ b/chrome/test/webdriver/commands/set_timeout_commands.cc @@ -9,8 +9,8 @@ #include "base/stringprintf.h" #include "base/values.h" #include "chrome/test/webdriver/commands/response.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { @@ -30,7 +30,7 @@ void SetTimeoutCommand::ExecutePost(Response* const response) { const char kTimeoutMsKey[] = "ms"; if (!HasParameter(kTimeoutMsKey)) { - SET_WEBDRIVER_ERROR(response, "Request missing ms parameter", kBadRequest); + response->SetError(new Error(kBadRequest, "Request missing ms parameter")); return; } @@ -42,8 +42,8 @@ void SetTimeoutCommand::ExecutePost(Response* const response) { // we are safe to downcast. double ms; if (!GetDoubleParameter(kTimeoutMsKey, &ms)) { - SET_WEBDRIVER_ERROR(response, "ms parameter is not a number", - kBadRequest); + response->SetError(new Error( + kBadRequest, "ms parameter is not a number")); return; } ms_to_wait = static_cast<int>(ms); @@ -51,16 +51,11 @@ void SetTimeoutCommand::ExecutePost(Response* const response) { // Validate the wait time before setting it to the session. if (ms_to_wait < 0) { - SET_WEBDRIVER_ERROR( - response, - base::StringPrintf("timeout must be non-negative: %d", - ms_to_wait), - kBadRequest); + response->SetError(new Error(kBadRequest, "Timeout must be non-negative")); return; } SetTimeout(ms_to_wait); - response->SetStatus(kSuccess); } SetAsyncScriptTimeoutCommand::SetAsyncScriptTimeoutCommand( @@ -86,4 +81,3 @@ void ImplicitWaitCommand::SetTimeout(int timeout_ms) { } } // namespace webdriver - diff --git a/chrome/test/webdriver/commands/set_timeout_commands_unittest.cc b/chrome/test/webdriver/commands/set_timeout_commands_unittest.cc index 4df283b..5bc4554 100644 --- a/chrome/test/webdriver/commands/set_timeout_commands_unittest.cc +++ b/chrome/test/webdriver/commands/set_timeout_commands_unittest.cc @@ -9,8 +9,8 @@ #include "base/values.h" #include "chrome/test/webdriver/commands/set_timeout_commands.h" #include "chrome/test/webdriver/commands/response.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" +#include "chrome/test/webdriver/webdriver_error.h" #include "testing/gtest/include/gtest/gtest.h" namespace webdriver { diff --git a/chrome/test/webdriver/commands/source_command.cc b/chrome/test/webdriver/commands/source_command.cc index 94c5e8e..7030410 100644 --- a/chrome/test/webdriver/commands/source_command.cc +++ b/chrome/test/webdriver/commands/source_command.cc @@ -8,8 +8,8 @@ #include "base/values.h" #include "chrome/test/webdriver/commands/response.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { @@ -30,15 +30,12 @@ bool SourceCommand::DoesGet() { void SourceCommand::ExecuteGet(Response* const response) { ListValue args; Value* result = NULL; - ErrorCode code = session_->ExecuteScript(kSource, &args, &result); - - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "ExecuteAndExtractString failed", - kInternalServerError); + Error* error = session_->ExecuteScript(kSource, &args, &result); + if (error) { + response->SetError(error); return; } response->SetValue(result); - response->SetStatus(kSuccess); } } // namespace webdriver diff --git a/chrome/test/webdriver/commands/speed_command.cc b/chrome/test/webdriver/commands/speed_command.cc deleted file mode 100644 index 9755305..0000000 --- a/chrome/test/webdriver/commands/speed_command.cc +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/test/webdriver/commands/speed_command.h" - -#include <string> - -#include "base/utf_string_conversions.h" -#include "chrome/test/webdriver/commands/response.h" - -namespace webdriver { - -SpeedCommand::SpeedCommand(const std::vector<std::string>& path_segments, - const DictionaryValue* const parameters) - : WebDriverCommand(path_segments, parameters), - speed_(Session::kMedium) { -} - -SpeedCommand::~SpeedCommand() {} - -bool SpeedCommand::Init(Response* const response) { - std::string speed; - - if (!WebDriverCommand::Init(response)) { - SET_WEBDRIVER_ERROR(response, "Failure on Init for setting speed", - kInternalServerError); - return false; - } - - // The speed parameter must be passed in as SLOW, MEDIUM, or FAST. - // The command must also be in all upper case letters. - if (!GetStringASCIIParameter("speed", &speed)) { - SET_WEBDRIVER_ERROR(response, "Request missing speed parameter", - kBadRequest); - return false; - } - - if (speed.compare("SLOW") == 0) { - LOG(INFO) << "Speed set to slow"; - speed_ = Session::kSlow; - } else if (speed.compare("MEDIUM") == 0) { - LOG(INFO) << "Speed set to medium"; - speed_ = Session::kMedium; - } else if (speed.compare("FAST") == 0) { - LOG(INFO) << "Speed set to fast" << std::endl; - speed_ = Session::kFast; - } else { - // If the speed is invalid throw and error in the POST response. - LOG(INFO) << "Requested an unknown speed: " << speed; - speed_ = Session::kUnknown; - } - - return true; -} - -bool SpeedCommand::DoesGet() { - return true; -} - -bool SpeedCommand::DoesPost() { - return true; -} - -void SpeedCommand::ExecuteGet(Response* const response) { - switch (session_->speed()) { - case Session::kSlow: - response->SetValue(new StringValue("SLOW")); - response->SetStatus(kSuccess); - break; - - case Session::kMedium: - response->SetValue(new StringValue("MEDIUM")); - response->SetStatus(kSuccess); - break; - - case Session::kFast: - response->SetValue(new StringValue("FAST")); - response->SetStatus(kSuccess); - break; - - default: - // The speed should have never been set to unknown. - SET_WEBDRIVER_ERROR(response, "Unknown speed set", - kInternalServerError); - NOTREACHED(); - break; - } -} - -void SpeedCommand::ExecutePost(Response* const response) { - if (speed_ == Session::kUnknown) { - SET_WEBDRIVER_ERROR(response, "Invalid speed requested", - kInternalServerError); - return; - } - - session_->set_speed(speed_); - response->SetValue(new StringValue("success")); - response->SetStatus(kSuccess); -} - -bool SpeedCommand::RequiresValidTab() { - return true; -} - -} // namespace webdriver - diff --git a/chrome/test/webdriver/commands/speed_command.h b/chrome/test/webdriver/commands/speed_command.h deleted file mode 100644 index 9846fa5..0000000 --- a/chrome/test/webdriver/commands/speed_command.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_TEST_WEBDRIVER_COMMANDS_SPEED_COMMAND_H_ -#define CHROME_TEST_WEBDRIVER_COMMANDS_SPEED_COMMAND_H_ - -#include <string> -#include <vector> - -#include "chrome/test/webdriver/session.h" -#include "chrome/test/webdriver/commands/webdriver_command.h" - -namespace webdriver { - -class Response; - -// Controls how fast chrome should simulate user typing and mouse movements. -// By default the speed is set to medium however webdriver has not defined -// what this speed means accross browsers. Currently speed is ignored. -// See: http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/speed -class SpeedCommand : public WebDriverCommand { - public: - SpeedCommand(const std::vector<std::string>& path_segments, - const DictionaryValue* const parameters); - virtual ~SpeedCommand(); - - virtual bool Init(Response* const response); - - virtual bool DoesGet(); - virtual bool DoesPost(); - virtual void ExecuteGet(Response* const response); - virtual void ExecutePost(Response* const response); - - private: - virtual bool RequiresValidTab(); - - Session::Speed speed_; - - DISALLOW_COPY_AND_ASSIGN(SpeedCommand); -}; - -} // namespace webdriver - -#endif // CHROME_TEST_WEBDRIVER_COMMANDS_SPEED_COMMAND_H_ - diff --git a/chrome/test/webdriver/commands/target_locator_commands.cc b/chrome/test/webdriver/commands/target_locator_commands.cc index b0b7ff5..d738fe0 100644 --- a/chrome/test/webdriver/commands/target_locator_commands.cc +++ b/chrome/test/webdriver/commands/target_locator_commands.cc @@ -7,9 +7,9 @@ #include "base/string_number_conversions.h" #include "base/values.h" #include "chrome/test/webdriver/commands/response.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" #include "chrome/test/webdriver/web_element_id.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { @@ -25,7 +25,6 @@ bool WindowHandleCommand::DoesGet() { } void WindowHandleCommand::ExecuteGet(Response* const response) { - response->SetStatus(kSuccess); response->SetValue(new StringValue( base::IntToString(session_->current_target().window_id))); } @@ -43,15 +42,14 @@ bool WindowHandlesCommand::DoesGet() { void WindowHandlesCommand::ExecuteGet(Response* const response) { std::vector<int> window_ids; - if (!session_->GetWindowIds(&window_ids)) { - SET_WEBDRIVER_ERROR( - response, "Could not get window handles", kInternalServerError); + Error* error = session_->GetWindowIds(&window_ids); + if (error) { + response->SetError(error); return; } ListValue* id_list = new ListValue(); for (size_t i = 0; i < window_ids.size(); ++i) id_list->Append(new StringValue(base::IntToString(window_ids[i]))); - response->SetStatus(kSuccess); response->SetValue(id_list); } @@ -73,26 +71,20 @@ bool WindowCommand::DoesDelete() { void WindowCommand::ExecutePost(Response* const response) { std::string name; if (!GetStringParameter("name", &name)) { - SET_WEBDRIVER_ERROR( - response, "Missing or invalid 'name' parameter", kBadRequest); + response->SetError(new Error( + kBadRequest, "Missing or invalid 'name' parameter")); return; } - ErrorCode code = session_->SwitchToWindow(name); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Could not switch window", code); - return; - } - response->SetStatus(kSuccess); + Error* error = session_->SwitchToWindow(name); + if (error) + response->SetError(error); } void WindowCommand::ExecuteDelete(Response* const response) { - if (!session_->CloseWindow()) { - SET_WEBDRIVER_ERROR( - response, "Could not close window", kInternalServerError); - return; - } - response->SetStatus(kSuccess); + Error* error = session_->CloseWindow(); + if (error) + response->SetError(error); } SwitchFrameCommand::SwitchFrameCommand( @@ -110,34 +102,22 @@ void SwitchFrameCommand::ExecutePost(Response* const response) { std::string id; int index = 0; WebElementId element; + Error* error = NULL; if (GetStringParameter("id", &id)) { - ErrorCode code = session_->SwitchToFrameWithNameOrId(id); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Could not switch to frame", code); - return; - } + error = session_->SwitchToFrameWithNameOrId(id); } else if (GetIntegerParameter("id", &index)) { - ErrorCode code = session_->SwitchToFrameWithIndex(index); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Could not switch to frame", code); - return; - } + error = session_->SwitchToFrameWithIndex(index); } else if (GetWebElementParameter("id", &element)) { - ErrorCode code = session_->SwitchToFrameWithElement(element); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Could not switch to frame", code); - return; - } + error = session_->SwitchToFrameWithElement(element); } else if (IsNullParameter("id") || !HasParameter("id")) { // Treat null 'id' and no 'id' as the same. // See http://code.google.com/p/selenium/issues/detail?id=1479. session_->SwitchToTopFrame(); } else { - SET_WEBDRIVER_ERROR( - response, "Invalid 'id' parameter", kBadRequest); - return; + error = new Error(kBadRequest, "Invalid 'id' parameter"); } - response->SetStatus(kSuccess); + if (error) + response->SetError(error); } bool SwitchFrameCommand::GetWebElementParameter(const std::string& key, @@ -168,9 +148,12 @@ bool ActiveElementCommand::DoesPost() { void ActiveElementCommand::ExecutePost(Response* const response) { ListValue args; Value* result = NULL; - ErrorCode status = session_->ExecuteScript( + Error* error = session_->ExecuteScript( "return document.activeElement || document.body", &args, &result); - response->SetStatus(status); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } diff --git a/chrome/test/webdriver/commands/title_command.cc b/chrome/test/webdriver/commands/title_command.cc index a6cc20a..4898d5f 100644 --- a/chrome/test/webdriver/commands/title_command.cc +++ b/chrome/test/webdriver/commands/title_command.cc @@ -7,6 +7,8 @@ #include <string> #include "chrome/test/webdriver/commands/response.h" +#include "chrome/test/webdriver/session.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { @@ -22,14 +24,12 @@ bool TitleCommand::DoesGet() { void TitleCommand::ExecuteGet(Response* const response) { std::string title; - ErrorCode code = session_->GetTitle(&title); - if (code == kSuccess) - response->SetValue(new StringValue(title)); - response->SetStatus(code); -} - -bool TitleCommand::RequiresValidTab() { - return true; + Error* error = session_->GetTitle(&title); + if (error) { + response->SetError(error); + return; + } + response->SetValue(new StringValue(title)); } } // namespace webdriver diff --git a/chrome/test/webdriver/commands/title_command.h b/chrome/test/webdriver/commands/title_command.h index 3ec5fe81..4a4723e 100644 --- a/chrome/test/webdriver/commands/title_command.h +++ b/chrome/test/webdriver/commands/title_command.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -26,12 +26,9 @@ class TitleCommand : public WebDriverCommand { virtual void ExecuteGet(Response* const response); private: - virtual bool RequiresValidTab(); - DISALLOW_COPY_AND_ASSIGN(TitleCommand); }; } // namespace webdriver #endif // CHROME_TEST_WEBDRIVER_COMMANDS_TITLE_COMMAND_H_ - diff --git a/chrome/test/webdriver/commands/url_command.cc b/chrome/test/webdriver/commands/url_command.cc index 22efa1e..7a495d9 100644 --- a/chrome/test/webdriver/commands/url_command.cc +++ b/chrome/test/webdriver/commands/url_command.cc @@ -7,6 +7,8 @@ #include <string> #include "chrome/test/webdriver/commands/response.h" +#include "chrome/test/webdriver/session.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { @@ -26,32 +28,29 @@ bool URLCommand::DoesPost() { void URLCommand::ExecuteGet(Response* const response) { std::string url; - ErrorCode code = session_->GetURL(&url); - if (code == kSuccess) - response->SetValue(new StringValue(url)); - response->SetStatus(code); + Error* error = session_->GetURL(&url); + if (error) { + response->SetError(error); + return; + } + response->SetValue(new StringValue(url)); } void URLCommand::ExecutePost(Response* const response) { std::string url; if (!GetStringASCIIParameter("url", &url)) { - SET_WEBDRIVER_ERROR(response, "URL field not found", kInternalServerError); + response->SetError(new Error(kBadRequest, "Missing 'url' parameter")); return; } - // TODO(jmikhail): sniff for meta-redirects. - if (!session_->NavigateToURL(url)) { - SET_WEBDRIVER_ERROR(response, "NavigateToURL failed", - kInternalServerError); + + Error* error = session_->NavigateToURL(url); + if (error) { + response->SetError(error); return; } - response->SetValue(new StringValue(url)); - response->SetStatus(kSuccess); } -bool URLCommand::RequiresValidTab() { - return true; -} } // namespace webdriver diff --git a/chrome/test/webdriver/commands/url_command.h b/chrome/test/webdriver/commands/url_command.h index 0f5c1e8..075a4a8 100644 --- a/chrome/test/webdriver/commands/url_command.h +++ b/chrome/test/webdriver/commands/url_command.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -29,12 +29,9 @@ class URLCommand : public WebDriverCommand { virtual void ExecutePost(Response* const response); private: - virtual bool RequiresValidTab(); - DISALLOW_COPY_AND_ASSIGN(URLCommand); }; } // namespace webdriver #endif // CHROME_TEST_WEBDRIVER_COMMANDS_URL_COMMAND_H_ - diff --git a/chrome/test/webdriver/commands/webdriver_command.cc b/chrome/test/webdriver/commands/webdriver_command.cc index 1a30191..133b6a0 100644 --- a/chrome/test/webdriver/commands/webdriver_command.cc +++ b/chrome/test/webdriver/commands/webdriver_command.cc @@ -7,33 +7,51 @@ #include <string> #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/singleton.h" #include "base/values.h" #include "chrome/test/webdriver/commands/response.h" +#include "chrome/test/webdriver/session.h" #include "chrome/test/webdriver/session_manager.h" -#include "chrome/test/webdriver/error_codes.h" +#include "chrome/test/webdriver/webdriver_error.h" namespace webdriver { +WebDriverCommand::WebDriverCommand( + const std::vector<std::string>& path_segments, + const DictionaryValue* const parameters) + : Command(path_segments, parameters), session_(NULL) { +} + +WebDriverCommand::~WebDriverCommand() {} + bool WebDriverCommand::Init(Response* const response) { // There should be at least 3 path segments to match "/session/$id". std::string session_id = GetPathVariable(2); if (session_id.length() == 0) { - SET_WEBDRIVER_ERROR(response, "No session ID specified", kBadRequest); + response->SetError( + new Error(kBadRequest, "No session ID specified")); return false; } VLOG(1) << "Fetching session: " << session_id; session_ = SessionManager::GetInstance()->GetSession(session_id); if (session_ == NULL) { - SET_WEBDRIVER_ERROR(response, "Session not found: " + session_id, - kSessionNotFound); + response->SetError( + new Error(kSessionNotFound, "Session not found: " + session_id)); return false; } - if (!session_->WaitForAllTabsToStopLoading()) { - LOG(WARNING) << "Failed to wait for all tabs to stop loading"; + + // TODO(kkania): Do not use the standard automation timeout for this, + // and throw an error if it does not succeed. + scoped_ptr<Error> error(session_->WaitForAllTabsToStopLoading()); + if (error.get()) { + LOG(WARNING) << error->ToString(); + } + error.reset(session_->SwitchToTopFrameIfCurrentFrameInvalid()); + if (error.get()) { + LOG(WARNING) << error->ToString(); } - session_->SwitchToTopFrameIfCurrentFrameInvalid(); response->SetField("sessionId", Value::CreateStringValue(session_id)); return true; diff --git a/chrome/test/webdriver/commands/webdriver_command.h b/chrome/test/webdriver/commands/webdriver_command.h index 633a02d..c4e759d 100644 --- a/chrome/test/webdriver/commands/webdriver_command.h +++ b/chrome/test/webdriver/commands/webdriver_command.h @@ -9,13 +9,13 @@ #include <vector> #include "chrome/test/webdriver/commands/command.h" -#include "chrome/test/webdriver/session.h" class DictionaryValue; namespace webdriver { class Response; +class Session; // All URLs that are found in the document: // http://code.google.com/p/selenium/wiki/JsonWireProtocol @@ -25,10 +25,9 @@ class Response; // directly. class WebDriverCommand : public Command { public: - WebDriverCommand(const std::vector<std::string> path_segments, - const DictionaryValue* const parameters) - : Command(path_segments, parameters), session_(NULL) {} - virtual ~WebDriverCommand() {} + WebDriverCommand(const std::vector<std::string>& path_segments, + const DictionaryValue* const parameters); + virtual ~WebDriverCommand(); // Initializes this webdriver command by fetching the command session. virtual bool Init(Response* const response); diff --git a/chrome/test/webdriver/commands/webelement_commands.cc b/chrome/test/webdriver/commands/webelement_commands.cc index de68aef..dae3e4eb 100644 --- a/chrome/test/webdriver/commands/webelement_commands.cc +++ b/chrome/test/webdriver/commands/webelement_commands.cc @@ -9,8 +9,8 @@ #include "base/third_party/icu/icu_utf.h" #include "base/values.h" #include "chrome/test/webdriver/commands/response.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session.h" +#include "chrome/test/webdriver/webdriver_error.h" #include "third_party/webdriver/atoms.h" #include "ui/gfx/point.h" #include "ui/gfx/size.h" @@ -34,8 +34,7 @@ bool WebElementCommand::Init(Response* const response) { // There should be at least 5 segments to match // "/session/$session/element/$id" if (path_segments_.size() < 5) { - SET_WEBDRIVER_ERROR(response, "Path segments is less than 5", - kBadRequest); + response->SetError(new Error(kBadRequest, "Path segments is less than 5")); return false; } @@ -62,21 +61,23 @@ void ElementAttributeCommand::ExecuteGet(Response* const response) { // There should be at least 7 segments to match // "/session/$session/element/$id/attribute/$name" if (path_segments_.size() < 7) { - SET_WEBDRIVER_ERROR(response, "Path segments is less than 7", - kBadRequest); + response->SetError(new Error(kBadRequest, "Path segments is less than 7")); return; } std::string script = base::StringPrintf( "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE); - scoped_ptr<ListValue> args(new ListValue); - args->Append(element.ToValue()); - args->Append(Value::CreateStringValue(path_segments_.at(6))); + ListValue args; + args.Append(element.ToValue()); + args.Append(Value::CreateStringValue(path_segments_.at(6))); Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, args.get(), &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, &args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } @@ -94,15 +95,18 @@ bool ElementClearCommand::DoesPost() { } void ElementClearCommand::ExecutePost(Response* const response) { - scoped_ptr<ListValue> args(new ListValue); - args->Append(element.ToValue()); + ListValue args; + args.Append(element.ToValue()); std::string script = base::StringPrintf( "(%s).apply(null, arguments);", atoms::CLEAR); Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, args.get(), &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, &args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } @@ -123,21 +127,23 @@ void ElementCssCommand::ExecuteGet(Response* const response) { // There should be at least 7 segments to match // "/session/$session/element/$id/css/$propertyName" if (path_segments_.size() < 7) { - SET_WEBDRIVER_ERROR(response, "Path segments is less than 7", - kBadRequest); + response->SetError(new Error(kBadRequest, "Path segments is less than 7")); return; } std::string script = base::StringPrintf( "return (%s).apply(null, arguments);", atoms::GET_EFFECTIVE_STYLE); - scoped_ptr<ListValue> args(new ListValue); - args->Append(element.ToValue()); - args->Append(Value::CreateStringValue(path_segments_.at(6))); + ListValue args; + args.Append(element.ToValue()); + args.Append(Value::CreateStringValue(path_segments_.at(6))); Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, args.get(), &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, &args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } @@ -156,11 +162,13 @@ bool ElementDisplayedCommand::DoesGet() { void ElementDisplayedCommand::ExecuteGet(Response* const response) { bool is_displayed; - ErrorCode status = session_->IsElementDisplayed( + Error* error = session_->IsElementDisplayed( session_->current_target(), element, &is_displayed); - if (status == kSuccess) - response->SetValue(Value::CreateBooleanValue(is_displayed)); - response->SetStatus(status); + if (error) { + response->SetError(error); + return; + } + response->SetValue(Value::CreateBooleanValue(is_displayed)); } ///////////////////// ElementEnabledCommand //////////////////// @@ -177,15 +185,18 @@ bool ElementEnabledCommand::DoesGet() { } void ElementEnabledCommand::ExecuteGet(Response* const response) { - scoped_ptr<ListValue> args(new ListValue); - args->Append(element.ToValue()); + ListValue args; + args.Append(element.ToValue()); std::string script = base::StringPrintf( "return (%s).apply(null, arguments);", atoms::IS_ENABLED); Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, args.get(), &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, &args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } @@ -206,22 +217,24 @@ void ElementEqualsCommand::ExecuteGet(Response* const response) { // There should be at least 7 segments to match // "/session/$session/element/$id/equals/$other" if (path_segments_.size() < 7) { - SET_WEBDRIVER_ERROR(response, "Path segments is less than 7", - kBadRequest); + response->SetError(new Error(kBadRequest, "Path segments is less than 7")); return; } std::string script = "return arguments[0] == arguments[1];"; - scoped_ptr<ListValue> args(new ListValue); - args->Append(element.ToValue()); + ListValue args; + args.Append(element.ToValue()); WebElementId other_element(path_segments_.at(6)); - args->Append(other_element.ToValue()); + args.Append(other_element.ToValue()); Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, args.get(), &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, &args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } @@ -246,8 +259,11 @@ void ElementLocationCommand::ExecuteGet(Response* const response) { args.Append(element.ToValue()); Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, &args, &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, &args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } @@ -266,14 +282,15 @@ bool ElementLocationInViewCommand::DoesGet() { void ElementLocationInViewCommand::ExecuteGet(Response* const response) { gfx::Point location; - ErrorCode code = session_->GetElementLocationInView(element, &location); - response->SetStatus(code); - if (code == kSuccess) { - DictionaryValue* coord_dict = new DictionaryValue(); - coord_dict->SetInteger("x", location.x()); - coord_dict->SetInteger("y", location.y()); - response->SetValue(coord_dict); + Error* error = session_->GetElementLocationInView(element, &location); + if (error) { + response->SetError(error); + return; } + DictionaryValue* coord_dict = new DictionaryValue(); + coord_dict->SetInteger("x", location.x()); + coord_dict->SetInteger("y", location.y()); + response->SetValue(coord_dict); } ///////////////////// ElementNameCommand //////////////////// @@ -290,14 +307,17 @@ bool ElementNameCommand::DoesGet() { } void ElementNameCommand::ExecuteGet(Response* const response) { - scoped_ptr<ListValue> args(new ListValue); - args->Append(element.ToValue()); + ListValue args; + args.Append(element.ToValue()); std::string script = "return arguments[0].tagName.toLocaleLowerCase();"; Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, args.get(), &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, &args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } @@ -319,29 +339,35 @@ bool ElementSelectedCommand::DoesPost() { } void ElementSelectedCommand::ExecuteGet(Response* const response) { - scoped_ptr<ListValue> args(new ListValue); - args->Append(element.ToValue()); + ListValue args; + args.Append(element.ToValue()); std::string script = base::StringPrintf( "return (%s).apply(null, arguments);", atoms::IS_SELECTED); Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, args.get(), &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, &args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } void ElementSelectedCommand::ExecutePost(Response* const response) { - scoped_ptr<ListValue> args(new ListValue); - args->Append(element.ToValue()); - args->Append(Value::CreateBooleanValue(true)); + ListValue args; + args.Append(element.ToValue()); + args.Append(Value::CreateBooleanValue(true)); std::string script = base::StringPrintf( "return (%s).apply(null, arguments);", atoms::SET_SELECTED); Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, args.get(), &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, &args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } @@ -360,15 +386,16 @@ bool ElementSizeCommand::DoesGet() { void ElementSizeCommand::ExecuteGet(Response* const response) { gfx::Size size; - ErrorCode status = session_->GetElementSize( + Error* error = session_->GetElementSize( session_->current_target(), element, &size); - if (status == kSuccess) { - DictionaryValue* dict = new DictionaryValue(); - dict->SetInteger("width", size.width()); - dict->SetInteger("height", size.height()); - response->SetValue(dict); + if (error) { + response->SetError(error); + return; } - response->SetStatus(status); + DictionaryValue* dict = new DictionaryValue(); + dict->SetInteger("width", size.width()); + dict->SetInteger("height", size.height()); + response->SetValue(dict); } ///////////////////// ElementSubmitCommand //////////////////// @@ -394,8 +421,11 @@ void ElementSubmitCommand::ExecutePost(Response* const response) { args.Append(element.ToValue()); Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, &args, &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, &args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } @@ -420,8 +450,11 @@ void ElementToggleCommand::ExecutePost(Response* const response) { args.Append(element.ToValue()); Value* result = NULL; - ErrorCode status = session_->ExecuteScript(script, &args, &result); - response->SetStatus(status); + Error* error = session_->ExecuteScript(script, &args, &result); + if (error) { + response->SetError(error); + return; + } response->SetValue(result); } @@ -447,30 +480,28 @@ void ElementValueCommand::ExecuteGet(Response* const response) { ListValue args; std::string script = "return arguments[0]['value']"; args.Append(element.ToValue()); - ErrorCode code = + + Error* error = session_->ExecuteScript(script, &args, &unscoped_result); scoped_ptr<Value> result(unscoped_result); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Failed to execute script", code); + if (error) { + response->SetError(error); return; } if (!result->IsType(Value::TYPE_STRING) && !result->IsType(Value::TYPE_NULL)) { - SET_WEBDRIVER_ERROR(response, - "Result is not string or null type", - kInternalServerError); + response->SetError(new Error( + kUnknownError, "Result is not string or null type")); return; } - response->SetStatus(kSuccess); response->SetValue(result.release()); } void ElementValueCommand::ExecutePost(Response* const response) { ListValue* key_list; if (!GetListParameter("value", &key_list)) { - SET_WEBDRIVER_ERROR(response, - "Missing or invalid 'value' parameter", - kBadRequest); + response->SetError(new Error( + kBadRequest, "Missing or invalid 'value' parameter")); return; } // Flatten the given array of strings into one. @@ -480,24 +511,17 @@ void ElementValueCommand::ExecutePost(Response* const response) { key_list->GetString(i, &keys_list_part); for (size_t j = 0; j < keys_list_part.size(); ++j) { if (CBU16_IS_SURROGATE(keys_list_part[j])) { - SET_WEBDRIVER_ERROR( - response, - "ChromeDriver only supports characters in the BMP", - kBadRequest); + response->SetError(new Error( + kBadRequest, "ChromeDriver only supports characters in the BMP")); return; } } keys.append(keys_list_part); } - ErrorCode code = session_->SendKeys(element, keys); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, - "Internal SendKeys error", - code); - return; - } - response->SetStatus(kSuccess); + Error* error = session_->SendKeys(element, keys); + if (error) + response->SetError(error); } ///////////////////// ElementTextCommand //////////////////// @@ -521,20 +545,17 @@ void ElementTextCommand::ExecuteGet(Response* const response) { std::string script = base::StringPrintf( "return (%s).apply(null, arguments);", atoms::GET_TEXT); - ErrorCode code = session_->ExecuteScript(script, &args, - &unscoped_result); + Error* error = session_->ExecuteScript(script, &args, + &unscoped_result); scoped_ptr<Value> result(unscoped_result); - if (code != kSuccess) { - SET_WEBDRIVER_ERROR(response, "Failed to execute script", code); + if (error) { + response->SetError(error); return; } if (!result->IsType(Value::TYPE_STRING)) { - SET_WEBDRIVER_ERROR(response, - "Result is not string type", - kInternalServerError); + response->SetError(new Error(kUnknownError, "Result is not string type")); return; } - response->SetStatus(kSuccess); response->SetValue(result.release()); } diff --git a/chrome/test/webdriver/dispatch.cc b/chrome/test/webdriver/dispatch.cc index 29176c8..f1bfb77 100644 --- a/chrome/test/webdriver/dispatch.cc +++ b/chrome/test/webdriver/dispatch.cc @@ -229,9 +229,9 @@ bool ParseRequestInfo(const struct mg_request_info* const request_info, std::string json(request_info->post_data, request_info->post_data_len); std::string error; if (!ParseJSONDictionary(json, parameters, &error)) { - SET_WEBDRIVER_ERROR(response, - "Failed to parse command data: " + error + "\n Data: " + json, - kBadRequest); + response->SetError(new Error( + kBadRequest, + "Failed to parse command data: " + error + "\n Data: " + json)); return false; } } diff --git a/chrome/test/webdriver/error_codes.h b/chrome/test/webdriver/error_codes.h deleted file mode 100644 index 78060f8..0000000 --- a/chrome/test/webdriver/error_codes.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_TEST_WEBDRIVER_ERROR_CODES_H_ -#define CHROME_TEST_WEBDRIVER_ERROR_CODES_H_ - -namespace webdriver { -// These are the error codes defined in the WebDriver wire protcol. For more -// information, see: -// http://code.google.com/p/selenium/wiki/JsonWireProtocol#Response_Status_Codes -enum ErrorCode { - kSuccess = 0, - kNoSuchElement = 7, - kNoSuchFrame = 8, - kUnknownCommand = 9, - kStaleElementReference = 10, - kElementNotVisible = 11, - kInvalidElementState = 12, - kUnknownError = 13, - kElementNotSelectable = 15, - kXPathLookupError = 19, - kNoSuchWindow = 23, - kInvalidCookieDomain = 24, - kUnableToSetCookie = 25, - - // Non-standard error codes. - kBrowserCouldNotBeFound = 50, - kBrowserFailedToStart, - kIncompatibleBrowserVersion, - - // HTTP status codes. - kSeeOther = 303, - kBadRequest = 400, - kSessionNotFound = 404, - kMethodNotAllowed = 405, - kInternalServerError = 500, -}; - -} // namespace webdriver - -#endif // CHROME_TEST_WEBDRIVER_ERROR_CODES_H_ diff --git a/chrome/test/webdriver/server.cc b/chrome/test/webdriver/server.cc index 8c76823..a87bbf6 100644 --- a/chrome/test/webdriver/server.cc +++ b/chrome/test/webdriver/server.cc @@ -28,7 +28,6 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/webdriver/dispatch.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/session_manager.h" #include "chrome/test/webdriver/utility_functions.h" #include "chrome/test/webdriver/commands/alert_commands.h" @@ -43,7 +42,6 @@ #include "chrome/test/webdriver/commands/session_with_id.h" #include "chrome/test/webdriver/commands/set_timeout_commands.h" #include "chrome/test/webdriver/commands/source_command.h" -#include "chrome/test/webdriver/commands/speed_command.h" #include "chrome/test/webdriver/commands/target_locator_commands.h" #include "chrome/test/webdriver/commands/title_command.h" #include "chrome/test/webdriver/commands/url_command.h" @@ -138,7 +136,6 @@ void InitCallbacks(struct mg_context* ctx, Dispatcher* dispatcher, dispatcher->Add<SwitchFrameCommand>( "/session/*/frame"); dispatcher->Add<RefreshCommand>( "/session/*/refresh"); dispatcher->Add<SourceCommand>( "/session/*/source"); - dispatcher->Add<SpeedCommand>( "/session/*/speed"); dispatcher->Add<TitleCommand>( "/session/*/title"); dispatcher->Add<URLCommand>( "/session/*/url"); dispatcher->Add<WindowCommand>( "/session/*/window"); diff --git a/chrome/test/webdriver/session.cc b/chrome/test/webdriver/session.cc index c543429..780f970 100644 --- a/chrome/test/webdriver/session.cc +++ b/chrome/test/webdriver/session.cc @@ -32,6 +32,7 @@ #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/automation/automation_json_requests.h" +#include "chrome/test/webdriver/webdriver_error.h" #include "chrome/test/webdriver/session_manager.h" #include "chrome/test/webdriver/utility_functions.h" #include "chrome/test/webdriver/webdriver_key_converter.h" @@ -70,24 +71,23 @@ Session::~Session() { SessionManager::GetInstance()->Remove(id_); } -ErrorCode Session::Init(const FilePath& browser_exe, - const CommandLine& options) { +Error* Session::Init(const FilePath& browser_exe, + const CommandLine& options) { if (!thread_.Start()) { - LOG(ERROR) << "Cannot start session thread"; delete this; - return kUnknownError; + return new Error(kUnknownError, "Cannot start session thread"); } - ErrorCode code = kUnknownError; + Error* error = NULL; RunSessionTask(NewRunnableMethod( this, &Session::InitOnSessionThread, browser_exe, options, - &code)); - if (code != kSuccess) + &error)); + if (error) Terminate(); - return code; + return error; } void Session::Terminate() { @@ -97,10 +97,10 @@ void Session::Terminate() { delete this; } -ErrorCode Session::ExecuteScript(const FrameId& frame_id, - const std::string& script, - const ListValue* const args, - Value** value) { +Error* Session::ExecuteScript(const FrameId& frame_id, + const std::string& script, + const ListValue* const args, + Value** value) { std::string args_as_json; base::JSONWriter::Write(static_cast<const Value* const>(args), /*pretty_print=*/false, @@ -117,16 +117,16 @@ ErrorCode Session::ExecuteScript(const FrameId& frame_id, return ExecuteScriptAndParseResponse(frame_id, jscript, value); } -ErrorCode Session::ExecuteScript(const std::string& script, - const ListValue* const args, - Value** value) { +Error* Session::ExecuteScript(const std::string& script, + const ListValue* const args, + Value** value) { return ExecuteScript(current_target_, script, args, value); } -ErrorCode Session::ExecuteAsyncScript(const FrameId& frame_id, - const std::string& script, - const ListValue* const args, - Value** value) { +Error* Session::ExecuteAsyncScript(const FrameId& frame_id, + const std::string& script, + const ListValue* const args, + Value** value) { std::string args_as_json; base::JSONWriter::Write(static_cast<const Value* const>(args), /*pretty_print=*/false, @@ -148,118 +148,111 @@ ErrorCode Session::ExecuteAsyncScript(const FrameId& frame_id, return ExecuteScriptAndParseResponse(frame_id, jscript, value); } -ErrorCode Session::SendKeys(const WebElementId& element, const string16& keys) { +Error* Session::SendKeys(const WebElementId& element, const string16& keys) { bool is_displayed = false; - ErrorCode code = IsElementDisplayed(current_target_, element, &is_displayed); - if (code != kSuccess) - return code; + Error* error = IsElementDisplayed(current_target_, element, &is_displayed); + if (error) + return error; if (!is_displayed) - return kElementNotVisible; + return new Error(kElementNotVisible); bool is_enabled = false; - code = IsElementEnabled(current_target_, element, &is_enabled); - if (code != kSuccess) { - LOG(ERROR) << "Failed to determine if element is enabled"; - return code; - } + error = IsElementEnabled(current_target_, element, &is_enabled); + if (error) + return error; if (!is_enabled) - return kInvalidElementState; + return new Error(kInvalidElementState); ListValue args; args.Append(element.ToValue()); // This method will first check if the element we want to send the keys to is // already focused, if not it will try to focus on it first. // TODO(jleyba): Update this to use the correct atom. - std::string script = "if(document.activeElement!=arguments[0]){" + std::string script = "if(document.activeElement != arguments[0]) {" " if(document.activeElement)" " document.activeElement.blur();" " arguments[0].focus();" "}"; Value* unscoped_result = NULL; - code = ExecuteScript(script, &args, &unscoped_result); - if (code != kSuccess) { - LOG(ERROR) << "Failed to get or set focus element before sending keys"; - return code; + error = ExecuteScript(script, &args, &unscoped_result); + if (error) { + error->AddDetails("Failed to focus element before sending keys"); + return error; } - bool success = false; + error = NULL; RunSessionTask(NewRunnableMethod( this, &Session::SendKeysOnSessionThread, keys, - &success)); - if (!success) - return kUnknownError; - return kSuccess; + &error)); + return error; } -bool Session::NavigateToURL(const std::string& url) { - bool success = false; +Error* Session::NavigateToURL(const std::string& url) { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::NavigateToURL, current_target_.window_id, url, - &success)); - return success; + &error)); + return error; } -bool Session::GoForward() { - bool success = false; +Error* Session::GoForward() { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::GoForward, current_target_.window_id, - &success)); - return success; + &error)); + return error; } -bool Session::GoBack() { - bool success = false; +Error* Session::GoBack() { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::GoBack, current_target_.window_id, - &success)); - return success; + &error)); + return error; } -bool Session::Reload() { - bool success = false; +Error* Session::Reload() { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::Reload, current_target_.window_id, - &success)); - return success; + &error)); + return error; } -ErrorCode Session::GetURL(std::string* url) { +Error* Session::GetURL(std::string* url) { ListValue no_args; Value* unscoped_value = NULL; - ErrorCode code = ExecuteScript(current_target_, - "return document.URL;", - &no_args, - &unscoped_value); + Error* error = ExecuteScript(current_target_, + "return document.URL;", + &no_args, + &unscoped_value); scoped_ptr<Value> value(unscoped_value); - if (code != kSuccess) - return code; - if (!value->GetAsString(url)) { - LOG(ERROR) << "Script returned non-string type"; - return kUnknownError; - } - return kSuccess; + if (error) + return error; + if (!value->GetAsString(url)) + return new Error(kUnknownError, "GetURL Script returned non-string"); + return NULL; } -ErrorCode Session::GetURL(GURL* url) { +Error* Session::GetURL(GURL* url) { std::string url_spec; - ErrorCode code = GetURL(&url_spec); - if (code == kSuccess) { + Error* error = GetURL(&url_spec); + if (!error) *url = GURL(url_spec); - } - return code; + return error; } -ErrorCode Session::GetTitle(std::string* tab_title) { +Error* Session::GetTitle(std::string* tab_title) { std::string script = "if (document.title)" " return document.title;" @@ -268,117 +261,115 @@ ErrorCode Session::GetTitle(std::string* tab_title) { ListValue no_args; Value* unscoped_value = NULL; - ErrorCode code = ExecuteScript(current_target_, - script, - &no_args, - &unscoped_value); + Error* error = ExecuteScript(current_target_, + script, + &no_args, + &unscoped_value); scoped_ptr<Value> value(unscoped_value); - if (code != kSuccess) - return code; - if (!value->GetAsString(tab_title)) { - LOG(ERROR) << "Script returned non-string type"; - return kUnknownError; - } - return kSuccess; + if (error) + return error; + if (!value->GetAsString(tab_title)) + return new Error(kUnknownError, "GetTitle script returned non-string"); + return NULL; } -bool Session::MouseMoveAndClick(const gfx::Point& location, - automation::MouseButton button) { - bool success = false; +Error* Session::MouseMoveAndClick(const gfx::Point& location, + automation::MouseButton button) { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::MouseClick, current_target_.window_id, location, button, - &success)); - if (success) + &error)); + if (!error) mouse_position_ = location; - return success; + return error; } -bool Session::MouseMove(const gfx::Point& location) { - bool success = false; +Error* Session::MouseMove(const gfx::Point& location) { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::MouseMove, current_target_.window_id, location, - &success)); - if (success) + &error)); + if (!error) mouse_position_ = location; - return success; + return error; } -bool Session::MouseDrag(const gfx::Point& start, - const gfx::Point& end) { - bool success = false; +Error* Session::MouseDrag(const gfx::Point& start, + const gfx::Point& end) { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::MouseDrag, current_target_.window_id, start, end, - &success)); - if (success) + &error)); + if (!error) mouse_position_ = end; - return success; + return error; } -bool Session::MouseClick(automation::MouseButton button) { - bool success = false; +Error* Session::MouseClick(automation::MouseButton button) { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::MouseClick, current_target_.window_id, mouse_position_, button, - &success)); - return success; + &error)); + return error; } -bool Session::MouseButtonDown() { - bool success = false; +Error* Session::MouseButtonDown() { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::MouseButtonDown, current_target_.window_id, mouse_position_, - &success)); - return success; + &error)); + return error; } -bool Session::MouseButtonUp() { - bool success = false; +Error* Session::MouseButtonUp() { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::MouseButtonUp, current_target_.window_id, mouse_position_, - &success)); - return success; + &error)); + return error; } -bool Session::MouseDoubleClick() { - bool success = false; +Error* Session::MouseDoubleClick() { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::MouseDoubleClick, current_target_.window_id, mouse_position_, - &success)); - return success; + &error)); + return error; } -bool Session::GetCookies(const std::string& url, ListValue** cookies) { - bool success = false; +Error* Session::GetCookies(const std::string& url, ListValue** cookies) { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::GetCookies, url, cookies, - &success)); - return success; + &error)); + return error; } bool Session::GetCookiesDeprecated(const GURL& url, std::string* cookies) { @@ -412,16 +403,16 @@ bool Session::GetCookieByNameDeprecated(const GURL& url, return true; } -bool Session::DeleteCookie(const std::string& url, +Error* Session::DeleteCookie(const std::string& url, const std::string& cookie_name) { - bool success = false; + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::DeleteCookie, url, cookie_name, - &success)); - return success; + &error)); + return error; } bool Session::DeleteCookieDeprecated(const GURL& url, @@ -437,15 +428,16 @@ bool Session::DeleteCookieDeprecated(const GURL& url, return success; } -bool Session::SetCookie(const std::string& url, DictionaryValue* cookie_dict) { - bool success = false; +Error* Session::SetCookie(const std::string& url, + DictionaryValue* cookie_dict) { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::SetCookie, url, cookie_dict, - &success)); - return success; + &error)); + return error; } bool Session::SetCookieDeprecated(const GURL& url, const std::string& cookie) { @@ -460,51 +452,52 @@ bool Session::SetCookieDeprecated(const GURL& url, const std::string& cookie) { return success; } -bool Session::GetWindowIds(std::vector<int>* window_ids) { - bool success = false; +Error* Session::GetWindowIds(std::vector<int>* window_ids) { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::GetTabIds, window_ids, - &success)); - return success; + &error)); + return error; } -ErrorCode Session::SwitchToWindow(const std::string& name) { +Error* Session::SwitchToWindow(const std::string& name) { int switch_to_id = 0; int name_no = 0; if (base::StringToInt(name, &name_no)) { - bool success = false; + Error* error = NULL; bool does_exist = false; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::DoesTabExist, name_no, &does_exist, - &success)); - if (!success) { - LOG(ERROR) << "Unable to determine if window exists"; - return kUnknownError; - } + &error)); + if (error) + return error; if (does_exist) switch_to_id = name_no; } if (!switch_to_id) { std::vector<int> window_ids; - GetWindowIds(&window_ids); + Error* error = GetWindowIds(&window_ids); + if (error) + return error; // See if any of the window names match |name|. for (size_t i = 0; i < window_ids.size(); ++i) { ListValue empty_list; Value* unscoped_name_value; std::string window_name; - ErrorCode code = ExecuteScript(FrameId(window_ids[i], FramePath()), - "return window.name;", - &empty_list, - &unscoped_name_value); + Error* error = ExecuteScript(FrameId(window_ids[i], FramePath()), + "return window.name;", + &empty_list, + &unscoped_name_value); scoped_ptr<Value> name_value(unscoped_name_value); - if (code == kSuccess && - name_value->GetAsString(&window_name) && + if (error) + return error; + if (name_value->GetAsString(&window_name) && name == window_name) { switch_to_id = window_ids[i]; break; @@ -513,12 +506,12 @@ ErrorCode Session::SwitchToWindow(const std::string& name) { } if (!switch_to_id) - return kNoSuchWindow; + return new Error(kNoSuchWindow); current_target_ = FrameId(switch_to_id, FramePath()); - return kSuccess; + return NULL; } -ErrorCode Session::SwitchToFrameWithNameOrId(const std::string& name_or_id) { +Error* Session::SwitchToFrameWithNameOrId(const std::string& name_or_id) { std::string script = "var arg = arguments[0];" "var xpath = '(/html/body//iframe|/html/frameset/frame)';" @@ -537,7 +530,7 @@ ErrorCode Session::SwitchToFrameWithNameOrId(const std::string& name_or_id) { return SwitchToFrameWithJavaScriptLocatedFrame(script, &args); } -ErrorCode Session::SwitchToFrameWithIndex(int index) { +Error* Session::SwitchToFrameWithIndex(int index) { // We cannot simply index into window.frames because we need to know the // tagName of the frameElement. If child frame N is from another domain, then // the following will run afoul of the same origin policy: @@ -562,7 +555,7 @@ ErrorCode Session::SwitchToFrameWithIndex(int index) { return SwitchToFrameWithJavaScriptLocatedFrame(script, &args); } -ErrorCode Session::SwitchToFrameWithElement(const WebElementId& element) { +Error* Session::SwitchToFrameWithElement(const WebElementId& element) { // TODO(jleyba): Extract this, and the other frame switch methods to an atom. std::string script = "var element = arguments[0];" @@ -590,12 +583,12 @@ void Session::SwitchToTopFrame() { current_target_.frame_path = FramePath(); } -void Session::SwitchToTopFrameIfCurrentFrameInvalid() { +Error* Session::SwitchToTopFrameIfCurrentFrameInvalid() { std::vector<std::string> components; current_target_.frame_path.GetComponents(&components); if (frame_elements_.size() != components.size()) { - LOG(ERROR) << "Frame element vector out of sync with frame path"; - return; + return new Error(kUnknownError, + "Frame element vector out of sync with frame path"); } FramePath frame_path; Value* unscoped_value; @@ -607,31 +600,32 @@ void Session::SwitchToTopFrameIfCurrentFrameInvalid() { FrameId frame_id(current_target_.window_id, frame_path); ListValue args; args.Append(frame_elements_[i].ToValue()); - ErrorCode code = ExecuteScript( - frame_id, "", &args, &unscoped_value); + scoped_ptr<Error> error(ExecuteScript( + frame_id, "", &args, &unscoped_value)); scoped_ptr<Value> value(unscoped_value); - if (code == kStaleElementReference) { + if (error.get() && error->code() == kStaleElementReference) { SwitchToTopFrame(); - } else if (code != kSuccess) { - LOG(WARNING) << "Unable to determine if target frame should be reset"; - return; + } else if (error.get()) { + return error.release(); } frame_path = frame_path.Append(components[i]); } + return NULL; } -bool Session::CloseWindow() { - bool success = false; +Error* Session::CloseWindow() { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::CloseTab, current_target_.window_id, - &success)); + &error)); - if (success) { + if (!error) { std::vector<int> window_ids; - if (!GetWindowIds(&window_ids) || window_ids.empty()) { + scoped_ptr<Error> error(GetWindowIds(&window_ids)); + if (error.get() || window_ids.empty()) { // The automation connection will soon be closed, if not already, // because we supposedly just closed the last window. Terminate the // session. @@ -641,47 +635,47 @@ bool Session::CloseWindow() { Terminate(); } } - return success; + return error; } -ErrorCode Session::GetAlertMessage(std::string* text) { - bool success = false; +Error* Session::GetAlertMessage(std::string* text) { + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::GetAppModalDialogMessage, text, - &success)); - return success ? kSuccess : kUnknownError; + &error)); + return error; } -ErrorCode Session::SetAlertPromptText(const std::string& alert_prompt_text) { +Error* Session::SetAlertPromptText(const std::string& alert_prompt_text) { std::string message_text; // Only set the alert prompt text if an alert is actually active. - ErrorCode code = GetAlertMessage(&message_text); - if (code == kSuccess) { + Error* error = GetAlertMessage(&message_text); + if (!error) { has_alert_prompt_text_ = true; alert_prompt_text_ = alert_prompt_text; } - return code; + return error; } -ErrorCode Session::AcceptOrDismissAlert(bool accept) { - bool success = false; +Error* Session::AcceptOrDismissAlert(bool accept) { + Error* error = NULL; if (accept && has_alert_prompt_text_) { RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::AcceptPromptAppModalDialog, alert_prompt_text_, - &success)); + &error)); } else { RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::AcceptOrDismissAppModalDialog, accept, - &success)); + &error)); } has_alert_prompt_text_ = false; - return success ? kSuccess : kUnknownError; + return error; } std::string Session::GetBrowserVersion() { @@ -693,18 +687,21 @@ std::string Session::GetBrowserVersion() { return version; } -bool Session::CompareBrowserVersion(int client_build_no, - int client_patch_no, - bool* is_newer_or_equal) { +Error* Session::CompareBrowserVersion(int client_build_no, + int client_patch_no, + bool* is_newer_or_equal) { std::string version = GetBrowserVersion(); std::vector<std::string> split_version; base::SplitString(version, '.', &split_version); - if (split_version.size() != 4) - return false; + if (split_version.size() != 4) { + return new Error( + kUnknownError, "Browser version has unrecognized format: " + version); + } int build_no, patch_no; if (!base::StringToInt(split_version[2], &build_no) || !base::StringToInt(split_version[3], &patch_no)) { - return false; + return new Error( + kUnknownError, "Browser version has unrecognized format: " + version); } if (build_no < client_build_no) *is_newer_or_equal = false; @@ -712,46 +709,57 @@ bool Session::CompareBrowserVersion(int client_build_no, *is_newer_or_equal = true; else *is_newer_or_equal = patch_no >= client_patch_no; - return true; + return NULL; } -ErrorCode Session::FindElement(const FrameId& frame_id, - const WebElementId& root_element, - const std::string& locator, - const std::string& query, - WebElementId* element) { +Error* Session::FindElement(const FrameId& frame_id, + const WebElementId& root_element, + const std::string& locator, + const std::string& query, + WebElementId* element) { std::vector<WebElementId> elements; - ErrorCode code = FindElementsHelper( + Error* error = FindElementsHelper( frame_id, root_element, locator, query, true, &elements); - if (code == kSuccess) + if (!error) *element = elements[0]; - return code; + return error; } -ErrorCode Session::FindElements(const FrameId& frame_id, - const WebElementId& root_element, - const std::string& locator, - const std::string& query, - std::vector<WebElementId>* elements) { +Error* Session::FindElements(const FrameId& frame_id, + const WebElementId& root_element, + const std::string& locator, + const std::string& query, + std::vector<WebElementId>* elements) { return FindElementsHelper( frame_id, root_element, locator, query, false, elements); } -ErrorCode Session::GetElementLocationInView( +Error* Session::CheckElementPreconditionsForClicking( + const WebElementId& element) { + bool is_displayed = false; + Error* error = IsElementDisplayed(current_target_, element, &is_displayed); + if (error) + return error; + if (!is_displayed) + return new Error(kElementNotVisible, "Element must be displayed"); + return NULL; +} + +Error* Session::GetElementLocationInView( const WebElementId& element, gfx::Point* location) { CHECK(element.is_valid()); gfx::Size elem_size; - ErrorCode code = GetElementSize(current_target_, element, &elem_size); - if (code != kSuccess) - return code; + Error* error = GetElementSize(current_target_, element, &elem_size); + if (error) + return error; gfx::Point elem_offset(0, 0); - code = GetLocationInViewHelper( + error = GetLocationInViewHelper( current_target_, element, gfx::Rect(elem_offset, elem_size), &elem_offset); - if (code != kSuccess) - return code; + if (error) + return error; for (FramePath frame_path = current_target_.frame_path; frame_path.IsSubframe(); @@ -759,64 +767,62 @@ ErrorCode Session::GetElementLocationInView( // Find the frame element for the current frame path. FrameId frame_id(current_target_.window_id, frame_path.Parent()); WebElementId frame_element; - code = FindElement( + error = FindElement( frame_id, WebElementId(""), LocatorType::kXpath, frame_path.BaseName().value(), &frame_element); - if (code != kSuccess) { - LOG(ERROR) << "Could not find frame element: " - << frame_path.BaseName().value() - << " in frame: " << frame_path.Parent().value(); - return code; + if (error) { + std::string context = base::StringPrintf( + "Could not find frame element (%s) in frame (%s)", + frame_path.BaseName().value().c_str(), + frame_path.Parent().value().c_str()); + error->AddDetails(context); + return error; } // Modify |elem_offset| by the frame's border. int border_left, border_top; - code = GetElementBorder( + error = GetElementBorder( frame_id, frame_element, &border_left, &border_top); - if (code != kSuccess) { - LOG(ERROR) << "Could not get frame border width"; - return code; - } + if (error) + return error; elem_offset.Offset(border_left, border_top); - code = GetLocationInViewHelper( + error = GetLocationInViewHelper( frame_id, frame_element, gfx::Rect(elem_offset, elem_size), &elem_offset); - if (code != kSuccess) - return code; + if (error) + return error; } *location = elem_offset; - return kSuccess; + return NULL; } -ErrorCode Session::GetElementSize(const FrameId& frame_id, - const WebElementId& element, - gfx::Size* size) { +Error* Session::GetElementSize(const FrameId& frame_id, + const WebElementId& element, + gfx::Size* size) { std::string script = base::StringPrintf( "return (%s).apply(null, arguments);", atoms::GET_SIZE); ListValue args; args.Append(element.ToValue()); Value* unscoped_result = NULL; - ErrorCode code = ExecuteScript(frame_id, script, &args, &unscoped_result); + Error* error = ExecuteScript(frame_id, script, &args, &unscoped_result); scoped_ptr<Value> result(unscoped_result); - if (code != kSuccess) - return code; + if (error) + return error; if (!result->IsType(Value::TYPE_DICTIONARY)) { - LOG(ERROR) << "GetSize atom returned non-dict type"; - return kUnknownError; + return new Error(kUnknownError, "GetSize atom returned non-dict type"); } DictionaryValue* dict = static_cast<DictionaryValue*>(result.get()); int width, height; if (!dict->GetInteger("width", &width) || !dict->GetInteger("height", &height)) { - LOG(ERROR) << "GetSize atom returned dict without width and height keys"; - return kUnknownError; + return new Error(kUnknownError, "GetSize atom returned invalid dict"); } *size = gfx::Size(width, height); - return kSuccess; + return NULL; } -ErrorCode Session::GetElementEffectiveStyle( +Error* Session::GetElementEffectiveStyle( const FrameId& frame_id, const WebElementId& element, const std::string& prop, @@ -827,88 +833,88 @@ ErrorCode Session::GetElementEffectiveStyle( args.Append(element.ToValue()); args.Append(Value::CreateStringValue(prop)); Value* unscoped_result = NULL; - ErrorCode code = ExecuteScript( + Error* error = ExecuteScript( frame_id, script, &args, &unscoped_result); scoped_ptr<Value> result(unscoped_result); - if (code != kSuccess) { - LOG(ERROR) << "GetEffectiveStyle atom failed for property: " << prop; - return code; + if (error) { + error->AddDetails(base::StringPrintf( + "GetEffectiveStyle atom failed for property (%s)", prop.c_str())); + return error; } if (!result->GetAsString(value)) { - LOG(ERROR) << "GetEffectiveStyle atom returned non-string type for " - << "property: " << prop; - return kUnknownError; + std::string context = base::StringPrintf( + "GetEffectiveStyle atom returned non-string type for property (%s)", + prop.c_str()); + return new Error(kUnknownError, context); } - return kSuccess; + return NULL; } -ErrorCode Session::GetElementBorder(const FrameId& frame_id, - const WebElementId& element, - int* border_left, - int* border_top) { +Error* Session::GetElementBorder(const FrameId& frame_id, + const WebElementId& element, + int* border_left, + int* border_top) { std::string border_left_str, border_top_str; - ErrorCode code_left = GetElementEffectiveStyle( + Error* error = GetElementEffectiveStyle( frame_id, element, "border-left-width", &border_left_str); - ErrorCode code_top = GetElementEffectiveStyle( + if (error) + return error; + error = GetElementEffectiveStyle( frame_id, element, "border-top-width", &border_top_str); - if (code_left != kSuccess || code_top != kSuccess) - return code_left; + if (error) + return error; base::StringToInt(border_left_str, border_left); base::StringToInt(border_top_str, border_top); - return kSuccess; + return NULL; } -ErrorCode Session::IsElementDisplayed(const FrameId& frame_id, - const WebElementId& element, - bool* is_displayed) { +Error* Session::IsElementDisplayed(const FrameId& frame_id, + const WebElementId& element, + bool* is_displayed) { std::string script = base::StringPrintf( "return (%s).apply(null, arguments);", atoms::IS_DISPLAYED); ListValue args; args.Append(element.ToValue()); Value* unscoped_result = NULL; - ErrorCode code = ExecuteScript(frame_id, script, &args, &unscoped_result); + Error* error = ExecuteScript(frame_id, script, &args, &unscoped_result); scoped_ptr<Value> result(unscoped_result); - if (code != kSuccess) - return code; - if (!result->GetAsBoolean(is_displayed)) { - LOG(ERROR) << "IsDisplayed atom returned non boolean"; - return kUnknownError; - } - return kSuccess; + if (error) + return error; + if (!result->GetAsBoolean(is_displayed)) + return new Error(kUnknownError, "IsDisplayed atom returned non boolean"); + return NULL; } -ErrorCode Session::IsElementEnabled(const FrameId& frame_id, - const WebElementId& element, - bool* is_enabled) { +Error* Session::IsElementEnabled(const FrameId& frame_id, + const WebElementId& element, + bool* is_enabled) { std::string script = base::StringPrintf( "return (%s).apply(null, arguments);", atoms::IS_ENABLED); ListValue args; args.Append(element.ToValue()); Value* unscoped_result = NULL; - ErrorCode code = ExecuteScript(frame_id, script, &args, &unscoped_result); + Error* error = ExecuteScript(frame_id, script, &args, &unscoped_result); scoped_ptr<Value> result(unscoped_result); - if (code != kSuccess) - return code; - if (!result->GetAsBoolean(is_enabled)) { - LOG(ERROR) << "IsEnabled atom returned non boolean"; - return kUnknownError; - } - return kSuccess; + if (error) + return error; + if (!result->GetAsBoolean(is_enabled)) + return new Error(kUnknownError, "IsEnabled atom returned non boolean"); + return NULL; } -bool Session::WaitForAllTabsToStopLoading() { +Error* Session::WaitForAllTabsToStopLoading() { if (!automation_.get()) - return true; - bool success = false; + return NULL; + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::WaitForAllTabsToStopLoading, - &success)); - return success; + &error)); + return error; } const std::string& Session::id() const { @@ -935,14 +941,6 @@ int Session::implicit_wait() const { return implicit_wait_; } -void Session::set_speed(Speed speed) { - speed_ = speed; -} - -Session::Speed Session::speed() const { - return speed_; -} - void Session::set_screenshot_on_error(bool error) { screenshot_on_error_ = error; } @@ -959,6 +957,10 @@ bool Session::use_native_events() const { return use_native_events_; } +const gfx::Point& Session::get_mouse_position() const { + return mouse_position_; +} + void Session::RunSessionTask(Task* task) { base::WaitableEvent done_event(false, false); thread_.message_loop_proxy()->PostTask(FROM_HERE, NewRunnableMethod( @@ -978,26 +980,21 @@ void Session::RunSessionTaskOnSessionThread(Task* task, void Session::InitOnSessionThread(const FilePath& browser_exe, const CommandLine& options, - ErrorCode* code) { + Error** error) { automation_.reset(new Automation()); if (browser_exe.empty()) - automation_->Init(options, code); + automation_->Init(options, error); else - automation_->InitWithBrowserPath(browser_exe, options, code); - if (*code != kSuccess) + automation_->InitWithBrowserPath(browser_exe, options, error); + if (*error) return; - bool success = false; std::vector<int> tab_ids; - automation_->GetTabIds(&tab_ids, &success); - if (!success) { - LOG(ERROR) << "Could not get tab ids"; - *code = kUnknownError; + automation_->GetTabIds(&tab_ids, error); + if (*error) return; - } if (tab_ids.empty()) { - LOG(ERROR) << "No tab ids after initialization"; - *code = kUnknownError; + *error = new Error(kUnknownError, "No tab ids after initialization"); return; } current_target_ = FrameId(tab_ids[0], FramePath()); @@ -1009,16 +1006,15 @@ void Session::TerminateOnSessionThread() { automation_.reset(); } -ErrorCode Session::ExecuteScriptAndParseResponse(const FrameId& frame_id, - const std::string& script, - Value** value) { - +Error* Session::ExecuteScriptAndParseResponse(const FrameId& frame_id, + const std::string& script, + Value** value) { // Should we also log the script that's being executed? It could be several KB // in size and will add lots of noise to the logs. VLOG(1) << "Executing script in frame: " << frame_id.frame_path.value(); std::string result; - bool success = false; + Error* error = NULL; RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::ExecuteScript, @@ -1026,33 +1022,18 @@ ErrorCode Session::ExecuteScriptAndParseResponse(const FrameId& frame_id, frame_id.frame_path, script, &result, - &success)); - if (!success) { - LOG(ERROR) << "Automation failed to execute script"; - *value = Value::CreateStringValue( - "Unknown internal script execution failure"); - return kUnknownError; - } + &error)); + if (error) + return error; VLOG(1) << "...script result: " << result; scoped_ptr<Value> r(base::JSONReader::ReadAndReturnError( result, true, NULL, NULL)); - if (!r.get()) { - LOG(ERROR) << "Failed to parse script result"; - *value = Value::CreateStringValue( - "Internal script execution error: failed to parse script result"); - return kUnknownError; - } + if (!r.get()) + return new Error(kUnknownError, "Failed to parse script result"); - if (r->GetType() != Value::TYPE_DICTIONARY) { - LOG(ERROR) << "Execute script returned non-dictionary type"; - std::ostringstream stream; - stream << "Internal script execution error: script result must be a " - << print_valuetype(Value::TYPE_DICTIONARY) << ", but was " - << print_valuetype(r->GetType()) << ": " << result; - *value = Value::CreateStringValue(stream.str()); - return kUnknownError; - } + if (r->GetType() != Value::TYPE_DICTIONARY) + return new Error(kUnknownError, "Execute script did not return dictionary"); DictionaryValue* result_dict = static_cast<DictionaryValue*>(r.get()); @@ -1066,24 +1047,22 @@ ErrorCode Session::ExecuteScriptAndParseResponse(const FrameId& frame_id, } int status; - if (!result_dict->GetInteger("status", &status)) { - NOTREACHED() << "...script did not return a status flag."; - } - return static_cast<ErrorCode>(status); + if (!result_dict->GetInteger("status", &status)) + return new Error(kUnknownError, "Execute script did not return status"); + ErrorCode code = static_cast<ErrorCode>(status); + if (code != kSuccess) + return new Error(code); + return NULL; } -void Session::SendKeysOnSessionThread(const string16& keys, bool* success) { - *success = true; +void Session::SendKeysOnSessionThread(const string16& keys, Error** error) { std::vector<WebKeyEvent> key_events; std::string error_msg; if (!ConvertKeysToWebKeyEvents(keys, &key_events, &error_msg)) { - // TODO(kkania): Return this message to the user. - LOG(ERROR) << error_msg; - *success = false; + *error = new Error(kUnknownError, error_msg); return; } for (size_t i = 0; i < key_events.size(); ++i) { - bool key_success = false; if (use_native_events_) { // The automation provider will generate up/down events for us, we // only need to call it once as compared to the WebKeyEvent method. @@ -1094,59 +1073,62 @@ void Session::SendKeysOnSessionThread(const string16& keys, bool* success) { current_target_.window_id, key_events[i].key_code, key_events[i].modifiers, - &key_success); + error); } else { automation_->SendWebKeyEvent( - current_target_.window_id, key_events[i], &key_success); + current_target_.window_id, key_events[i], error); } - if (!key_success) { - LOG(ERROR) << "Failed to send key event. Event details:\n" - << "Type: " << key_events[i].type << "\n" - << "KeyCode: " << key_events[i].key_code << "\n" - << "UnmodifiedText: " << key_events[i].unmodified_text << "\n" - << "ModifiedText: " << key_events[i].modified_text << "\n" - << "Modifiers: " << key_events[i].modifiers << "\n"; - *success = false; + if (*error) { + std::string details = base::StringPrintf( + "Failed to send key event. Event details:\n" + "Type: %d, KeyCode: %d, UnmodifiedText: %s, ModifiedText: %s, " + "Modifiers: %d", + key_events[i].type, + key_events[i].key_code, + key_events[i].unmodified_text.c_str(), + key_events[i].modified_text.c_str(), + key_events[i].modifiers); + (*error)->AddDetails(details); + return; } } } -ErrorCode Session::SwitchToFrameWithJavaScriptLocatedFrame( - const std::string& script, - ListValue* args) { +Error* Session::SwitchToFrameWithJavaScriptLocatedFrame( + const std::string& script, ListValue* args) { Value* unscoped_result = NULL; - ErrorCode code = ExecuteScript(script, args, &unscoped_result); + Error* error = ExecuteScript(script, args, &unscoped_result); scoped_ptr<Value> result(unscoped_result); - if (code != kSuccess) - return code; + if (error) + return error; ListValue* frame_and_xpath_list; if (!result->GetAsList(&frame_and_xpath_list)) - return kNoSuchFrame; + return new Error(kNoSuchFrame); DictionaryValue* element_dict; std::string xpath; if (!frame_and_xpath_list->GetDictionary(0, &element_dict) || !frame_and_xpath_list->GetString(1, &xpath)) { - LOG(ERROR) << "Frame finding script did not return correct type"; - return kUnknownError; + return new Error(kUnknownError, + "Frame finding script did not return correct type"); } WebElementId new_frame_element(element_dict); if (!new_frame_element.is_valid()) { - LOG(ERROR) << "Frame finding script did not return a frame element"; - return kUnknownError; + return new Error(kUnknownError, + "Frame finding script did not return a frame element"); } frame_elements_.push_back(new_frame_element); current_target_.frame_path = current_target_.frame_path.Append(xpath); - return kSuccess; + return NULL; } -ErrorCode Session::FindElementsHelper(const FrameId& frame_id, - const WebElementId& root_element, - const std::string& locator, - const std::string& query, - bool find_one, - std::vector<WebElementId>* elements) { +Error* Session::FindElementsHelper(const FrameId& frame_id, + const WebElementId& root_element, + const std::string& locator, + const std::string& query, + bool find_one, + std::vector<WebElementId>* elements) { CHECK(root_element.is_valid()); std::string jscript; @@ -1176,20 +1158,21 @@ ErrorCode Session::FindElementsHelper(const FrameId& frame_id, base::Time start_time = base::Time::Now(); scoped_ptr<Value> value; - ErrorCode code = kUnknownError; + scoped_ptr<Error> error; bool done = false; while (!done) { Value* unscoped_value; - code = ExecuteScript(frame_id, jscript, &jscript_args, &unscoped_value); + error.reset(ExecuteScript( + frame_id, jscript, &jscript_args, &unscoped_value)); value.reset(unscoped_value); - if (code == kSuccess) { + if (!error.get()) { // If searching for many elements, make sure we found at least one before // stopping. done = find_one || (value->GetType() == Value::TYPE_LIST && static_cast<ListValue*>(value.get())->GetSize() > 0); - } else if (code != kNoSuchElement) { - return code; + } else if (error->code() != kNoSuchElement) { + return error.release(); } int64 elapsed_time = (base::Time::Now() - start_time).InMilliseconds(); done = done || elapsed_time > implicit_wait_; @@ -1198,19 +1181,21 @@ ErrorCode Session::FindElementsHelper(const FrameId& frame_id, } // Parse the results. - if (code == kSuccess) { + const char* kInvalidElementDictionaryMessage = + "Find element script returned invalid element dictionary"; + if (!error.get()) { if (value->IsType(Value::TYPE_LIST)) { ListValue* element_list = static_cast<ListValue*>(value.get()); for (size_t i = 0; i < element_list->GetSize(); ++i) { DictionaryValue* element_dict = NULL; if (!element_list->GetDictionary(i, &element_dict)) { - LOG(ERROR) << "Not all elements were dictionaries"; - return kUnknownError; + return new Error(kUnknownError, + "Find element script returned non-dictionary"); } + WebElementId element(element_dict); if (!element.is_valid()) { - LOG(ERROR) << "Not all elements were valid"; - return kUnknownError; + return new Error(kUnknownError, kInvalidElementDictionaryMessage); } elements->push_back(element); } @@ -1219,22 +1204,21 @@ ErrorCode Session::FindElementsHelper(const FrameId& frame_id, static_cast<DictionaryValue*>(value.get()); WebElementId element(element_dict); if (!element.is_valid()) { - LOG(ERROR) << "Element was invalid"; - return kUnknownError; + return new Error(kUnknownError, kInvalidElementDictionaryMessage); } elements->push_back(element); } else { - LOG(ERROR) << "Invalid result type from find element atom"; - return kUnknownError; + return new Error(kUnknownError, + "Find element script returned unsupported type"); } } - return code; + return error.release(); } -ErrorCode Session::GetLocationInViewHelper(const FrameId& frame_id, - const WebElementId& element, - const gfx::Rect& region, - gfx::Point* location) { +Error* Session::GetLocationInViewHelper(const FrameId& frame_id, + const WebElementId& element, + const gfx::Rect& region, + gfx::Point* location) { std::string jscript = base::StringPrintf( "return (%s).apply(null, arguments);", atoms::GET_LOCATION_IN_VIEW); ListValue jscript_args; @@ -1246,52 +1230,46 @@ ErrorCode Session::GetLocationInViewHelper(const FrameId& frame_id, elem_offset_dict->SetInteger("height", region.height()); jscript_args.Append(elem_offset_dict); Value* unscoped_value = NULL; - ErrorCode code = ExecuteScript(frame_id, jscript, &jscript_args, - &unscoped_value); + Error* error = ExecuteScript(frame_id, jscript, &jscript_args, + &unscoped_value); scoped_ptr<Value> value(unscoped_value); - if (code != kSuccess) - return code; + if (error) + return error; if (!value->IsType(Value::TYPE_DICTIONARY)) { - LOG(ERROR) << "Location atom returned non-dictionary type"; - code = kUnknownError; + return new Error(kUnknownError, + "Location atom returned non-dictionary type"); } DictionaryValue* loc_dict = static_cast<DictionaryValue*>(value.get()); int x = 0, y = 0; if (!loc_dict->GetInteger("x", &x) || !loc_dict->GetInteger("y", &y)) { - LOG(ERROR) << "Location atom returned bad coordinate dictionary"; - code = kUnknownError; + return new Error(kUnknownError, + "Location atom returned bad coordinate dictionary"); } *location = gfx::Point(x, y); - return kSuccess; + return NULL; } -bool Session::GetScreenShot(std::string* png) { - bool success = false; +Error* Session::GetScreenShot(std::string* png) { + Error* error = NULL; ScopedTempDir screenshots_dir; - - // Create a temp directory for screenshots. if (!screenshots_dir.CreateUniqueTempDir()) { - return false; + return new Error(kUnknownError, + "Could not create temp directory for screenshot"); } FilePath path = screenshots_dir.path().AppendASCII("screen"); - RunSessionTask(NewRunnableMethod( automation_.get(), &Automation::CaptureEntirePageAsPNG, current_target_.window_id, path, - &success)); - - if (success) { - success = file_util::ReadFileToString(path, png); - } - return success; -} - -const gfx::Point& Session::get_mouse_position() const { - return mouse_position_; + &error)); + if (error) + return error; + if (!file_util::ReadFileToString(path, png)) + return new Error(kUnknownError, "Could not read screenshot file"); + return NULL; } } // namespace webdriver diff --git a/chrome/test/webdriver/session.h b/chrome/test/webdriver/session.h index 9090691..a8b8764 100644 --- a/chrome/test/webdriver/session.h +++ b/chrome/test/webdriver/session.h @@ -14,7 +14,6 @@ #include "base/threading/thread.h" #include "chrome/common/automation_constants.h" #include "chrome/test/webdriver/automation.h" -#include "chrome/test/webdriver/error_codes.h" #include "chrome/test/webdriver/frame_path.h" #include "chrome/test/webdriver/web_element_id.h" #include "ui/gfx/point.h" @@ -37,6 +36,8 @@ class Size; namespace webdriver { +class Error; + // A window ID and frame path combination that uniquely identifies a specific // frame within a session. struct FrameId { @@ -52,8 +53,6 @@ struct FrameId { // A session manages its own lifetime. class Session { public: - enum Speed { kSlow, kMedium, kFast, kUnknown }; - // Adds this |Session| to the |SessionManager|. The session manages its own // lifetime. Do not call delete. Session(); @@ -64,8 +63,8 @@ class Session { // |browser_exe|. If |browser_exe| is empty, it will search in all the default // locations. Returns true on success. On failure, the session will delete // itself and return an error code. - ErrorCode Init(const FilePath& browser_exe, - const CommandLine& options); + Error* Init(const FilePath& browser_exe, + const CommandLine& options); // Terminates this session and deletes itself. void Terminate(); @@ -75,99 +74,99 @@ class Session { // (e.g. "return arguments[0]"), where |args| is the list of arguments to // pass to the function. The caller is responsible for the script result // |value|. - ErrorCode ExecuteScript(const FrameId& frame_id, - const std::string& script, - const ListValue* const args, - Value** value); + Error* ExecuteScript(const FrameId& frame_id, + const std::string& script, + const ListValue* const args, + Value** value); // Same as above, but uses the currently targeted window and frame. - ErrorCode ExecuteScript(const std::string& script, - const ListValue* const args, - Value** value); + Error* ExecuteScript(const std::string& script, + const ListValue* const args, + Value** value); // Executes given |script| in the context of the given frame. // The |script| should be in the form of a function body // (e.g. "return arguments[0]"), where |args| is the list of arguments to // pass to the function. The caller is responsible for the script result // |value|. - ErrorCode ExecuteAsyncScript(const FrameId& frame_id, - const std::string& script, - const ListValue* const args, - Value** value); + Error* ExecuteAsyncScript(const FrameId& frame_id, + const std::string& script, + const ListValue* const args, + Value** value); // Send the given keys to the given element dictionary. This function takes // ownership of |element|. - ErrorCode SendKeys(const WebElementId& element, const string16& keys); + Error* SendKeys(const WebElementId& element, const string16& keys); // Clicks the mouse at the given location using the given button. - bool MouseMoveAndClick(const gfx::Point& location, - automation::MouseButton button); - bool MouseMove(const gfx::Point& location); - bool MouseDrag(const gfx::Point& start, const gfx::Point& end); - bool MouseClick(automation::MouseButton button); - bool MouseButtonDown(); - bool MouseButtonUp(); - bool MouseDoubleClick(); - - bool NavigateToURL(const std::string& url); - bool GoForward(); - bool GoBack(); - bool Reload(); - ErrorCode GetURL(std::string* url); - ErrorCode GetURL(GURL* url); - ErrorCode GetTitle(std::string* tab_title); - bool GetScreenShot(std::string* png); - - bool GetCookies(const std::string& url, ListValue** cookies); + Error* MouseMoveAndClick(const gfx::Point& location, + automation::MouseButton button); + Error* MouseMove(const gfx::Point& location); + Error* MouseDrag(const gfx::Point& start, const gfx::Point& end); + Error* MouseClick(automation::MouseButton button); + Error* MouseButtonDown(); + Error* MouseButtonUp(); + Error* MouseDoubleClick(); + + Error* NavigateToURL(const std::string& url); + Error* GoForward(); + Error* GoBack(); + Error* Reload(); + Error* GetURL(std::string* url); + Error* GetURL(GURL* url); + Error* GetTitle(std::string* tab_title); + Error* GetScreenShot(std::string* png); + + Error* GetCookies(const std::string& url, ListValue** cookies); bool GetCookiesDeprecated(const GURL& url, std::string* cookies); bool GetCookieByNameDeprecated(const GURL& url, const std::string& cookie_name, std::string* cookie); - bool DeleteCookie(const std::string& url, const std::string& cookie_name); + Error* DeleteCookie(const std::string& url, const std::string& cookie_name); bool DeleteCookieDeprecated(const GURL& url, const std::string& cookie_name); - bool SetCookie(const std::string& url, DictionaryValue* cookie_dict); + Error* SetCookie(const std::string& url, DictionaryValue* cookie_dict); bool SetCookieDeprecated(const GURL& url, const std::string& cookie); // Gets all the currently existing window IDs. Returns true on success. - bool GetWindowIds(std::vector<int>* window_ids); + Error* GetWindowIds(std::vector<int>* window_ids); // Switches the window used by default. |name| is either an ID returned by // |GetWindowIds| or the name attribute of a DOM window. - ErrorCode SwitchToWindow(const std::string& name); + Error* SwitchToWindow(const std::string& name); // Switches the frame used by default. |name_or_id| is either the name or id // of a frame element. - ErrorCode SwitchToFrameWithNameOrId(const std::string& name_or_id); + Error* SwitchToFrameWithNameOrId(const std::string& name_or_id); // Switches the frame used by default. |index| is the zero-based frame index. - ErrorCode SwitchToFrameWithIndex(int index); + Error* SwitchToFrameWithIndex(int index); // Switches to the frame identified by the given |element|. The element must // be either an IFRAME or FRAME element. - ErrorCode SwitchToFrameWithElement(const WebElementId& element); + Error* SwitchToFrameWithElement(const WebElementId& element); // Switches the target frame to the topmost frame. void SwitchToTopFrame(); // Switches the target frame to the topmost frame if the current frame is // invalid. - void SwitchToTopFrameIfCurrentFrameInvalid(); + Error* SwitchToTopFrameIfCurrentFrameInvalid(); // Closes the current window. Returns true on success. // Note: The session will be deleted if this closes the last window in the // session. - bool CloseWindow(); + Error* CloseWindow(); // Gets the message of the currently active JavaScript modal dialog. - ErrorCode GetAlertMessage(std::string* text); + Error* GetAlertMessage(std::string* text); // Sets the prompt text to use when accepting or dismissing a JavaScript // modal dialog. - ErrorCode SetAlertPromptText(const std::string& alert_prompt_text); + Error* SetAlertPromptText(const std::string& alert_prompt_text); // Accept or dismiss the currently active JavaScript modal dialog with the // previously set alert prompt text. Then clears the saved alert prompt text. - ErrorCode AcceptOrDismissAlert(bool accept); + Error* AcceptOrDismissAlert(bool accept); // Gets the version of the running browser. std::string GetBrowserVersion(); @@ -175,63 +174,67 @@ class Session { // Gets whether the running browser's version is newer or equal to the given // version. Returns true on successful comparison. For example, in the version // 11.0.632.4, 632 is the build number and 4 is the patch number. - bool CompareBrowserVersion(int build_no, - int patch_no, - bool* is_newer_or_equal); + Error* CompareBrowserVersion(int build_no, + int patch_no, + bool* is_newer_or_equal); // Finds a single element in the given frame, starting at the given // |root_element|, using the given locator strategy. |locator| should be a // constant from |LocatorType|. Returns an error code. If successful, // |element| will be set as the found element. - ErrorCode FindElement(const FrameId& frame_id, - const WebElementId& root_element, - const std::string& locator, - const std::string& query, - WebElementId* element); + Error* FindElement(const FrameId& frame_id, + const WebElementId& root_element, + const std::string& locator, + const std::string& query, + WebElementId* element); // Same as above, but finds multiple elements. - ErrorCode FindElements(const FrameId& frame_id, - const WebElementId& root_element, - const std::string& locator, - const std::string& query, - std::vector<WebElementId>* elements); + Error* FindElements(const FrameId& frame_id, + const WebElementId& root_element, + const std::string& locator, + const std::string& query, + std::vector<WebElementId>* elements); + + // Checks that the given element meets the WebDriver requirements for + // clicking. + Error* CheckElementPreconditionsForClicking(const WebElementId& element); // Scroll the element into view and get its location relative to the client's // viewport. - ErrorCode GetElementLocationInView( + Error* GetElementLocationInView( const WebElementId& element, gfx::Point* location); // Gets the size of the element from the given window and frame, even if // its display is none. - ErrorCode GetElementSize(const FrameId& frame_id, - const WebElementId& element, - gfx::Size* size); + Error* GetElementSize(const FrameId& frame_id, + const WebElementId& element, + gfx::Size* size); // Gets the element's effective style for the given property. - ErrorCode GetElementEffectiveStyle( + Error* GetElementEffectiveStyle( const FrameId& frame_id, const WebElementId& element, const std::string& prop, std::string* value); // Gets the top and left element border widths for the given frame. - ErrorCode GetElementBorder(const FrameId& frame_id, - const WebElementId& element, - int* border_left, - int* border_top); + Error* GetElementBorder(const FrameId& frame_id, + const WebElementId& element, + int* border_left, + int* border_top); // Gets whether the element is currently displayed. - ErrorCode IsElementDisplayed(const FrameId& frame_id, - const WebElementId& element, - bool* is_visible); + Error* IsElementDisplayed(const FrameId& frame_id, + const WebElementId& element, + bool* is_visible); // Gets whether the element is currently enabled. - ErrorCode IsElementEnabled(const FrameId& frame_id, - const WebElementId& element, - bool* is_enabled); + Error* IsElementEnabled(const FrameId& frame_id, + const WebElementId& element, + bool* is_enabled); // Waits for all tabs to stop loading. Returns true on success. - bool WaitForAllTabsToStopLoading(); + Error* WaitForAllTabsToStopLoading(); const std::string& id() const; @@ -243,9 +246,6 @@ class Session { void set_implicit_wait(int timeout_ms); int implicit_wait() const; - void set_speed(Speed speed); - Speed speed() const; - void set_screenshot_on_error(bool error); bool screenshot_on_error() const; @@ -261,30 +261,30 @@ class Session { base::WaitableEvent* done_event); void InitOnSessionThread(const FilePath& browser_exe, const CommandLine& options, - ErrorCode* code); + Error** error); void TerminateOnSessionThread(); // Executes the given |script| in the context of the given frame. // Waits for script to finish and parses the response. // The caller is responsible for the script result |value|. - ErrorCode ExecuteScriptAndParseResponse(const FrameId& frame_id, - const std::string& script, - Value** value); + Error* ExecuteScriptAndParseResponse(const FrameId& frame_id, + const std::string& script, + Value** value); - void SendKeysOnSessionThread(const string16& keys, bool* success); - ErrorCode SwitchToFrameWithJavaScriptLocatedFrame( + void SendKeysOnSessionThread(const string16& keys, Error** error); + Error* SwitchToFrameWithJavaScriptLocatedFrame( const std::string& script, ListValue* args); - ErrorCode FindElementsHelper(const FrameId& frame_id, - const WebElementId& root_element, - const std::string& locator, - const std::string& query, - bool find_one, - std::vector<WebElementId>* elements); - ErrorCode GetLocationInViewHelper(const FrameId& frame_id, - const WebElementId& element, - const gfx::Rect& region, - gfx::Point* location); + Error* FindElementsHelper(const FrameId& frame_id, + const WebElementId& root_element, + const std::string& locator, + const std::string& query, + bool find_one, + std::vector<WebElementId>* elements); + Error* GetLocationInViewHelper(const FrameId& frame_id, + const WebElementId& element, + const gfx::Rect& region, + gfx::Point* location); const std::string id_; FrameId current_target_; @@ -298,8 +298,6 @@ class Session { // Time (in ms) of how long to wait while searching for a single element. int implicit_wait_; - Speed speed_; - // Since screenshots can be very large when in base64 PNG format; the // client is allowed to dyamically enable/disable screenshots on error // during the lifetime of the session. diff --git a/chrome/test/webdriver/webdriver_error.cc b/chrome/test/webdriver/webdriver_error.cc new file mode 100644 index 0000000..33baa7e --- /dev/null +++ b/chrome/test/webdriver/webdriver_error.cc @@ -0,0 +1,98 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/test/webdriver/webdriver_error.h" + +#include <sstream> + +namespace webdriver { + +namespace { + +// Returns the string equivalent of the given |ErrorCode|. +const char* ErrorCodeToString(ErrorCode code) { + switch (code) { + case kSuccess: + return "SUCCESS"; + case kNoSuchElement: + return "NO_SUCH_ELEMENT"; + case kNoSuchFrame: + return "NO_SUCH_FRAME"; + case kUnknownCommand: + return "UNKNOWN_COMMAND"; + case kStaleElementReference: + return "STALE_ELEMENT_REFERENCE"; + case kElementNotVisible: + return "ELEMENT_NOT_VISIBLE"; + case kInvalidElementState: + return "INVALID_ELEMENT_STATE"; + case kUnknownError: + return "UNKNOWN_ERROR"; + case kElementNotSelectable: + return "ELEMENT_NOT_SELECTABLE"; + case kXPathLookupError: + return "XPATH_LOOKUP_ERROR"; + case kNoSuchWindow: + return "NO_SUCH_WINDOW"; + case kInvalidCookieDomain: + return "INVALID_COOKIE_DOMAIN"; + case kUnableToSetCookie: + return "UNABLE_TO_SET_COOKIE"; + default: + return "<unknown>"; + } +} + +} // namespace + +Error::Error(ErrorCode code): code_(code) { +} + +Error::Error(ErrorCode code, const std::string& details) + : code_(code), details_(details) { +} + +Error::~Error() { +} + +void Error::AddDetails(const std::string& details) { + if (details_.empty()) + details_ = details; + else + details_ = details + ";\n " + details_; +} + +std::string Error::ToString() const { + std::string error; + if (code_ != kUnknownError) { + error += ErrorCodeToString(code_); + error += ": "; + } + if (details_.length()) { + error += details_; + } + size_t count = 0; + trace_.Addresses(&count); + if (count > 0) { + std::ostringstream ostream; + trace_.OutputToStream(&ostream); + error += "\n"; + error += ostream.str(); + } + return error; +} + +ErrorCode Error::code() const { + return code_; +} + +const std::string& Error::details() const { + return details_; +} + +const base::debug::StackTrace& Error::trace() const { + return trace_; +} + +} // namespace webdriver diff --git a/chrome/test/webdriver/webdriver_error.h b/chrome/test/webdriver/webdriver_error.h new file mode 100644 index 0000000..0a232da --- /dev/null +++ b/chrome/test/webdriver/webdriver_error.h @@ -0,0 +1,69 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_TEST_WEBDRIVER_WEBDRIVER_ERROR_H_ +#define CHROME_TEST_WEBDRIVER_WEBDRIVER_ERROR_H_ +#pragma once + +#include <string> + +#include "base/basictypes.h" +#include "base/debug/stack_trace.h" + +namespace webdriver { + +// Error codes defined by the WebDriver wire protcol. +// If you add a code here, don't forget to add it to |ErrorCodeToString|. +enum ErrorCode { + kSuccess = 0, + kNoSuchElement = 7, + kNoSuchFrame = 8, + kUnknownCommand = 9, + kStaleElementReference = 10, + kElementNotVisible = 11, + kInvalidElementState = 12, + kUnknownError = 13, + kElementNotSelectable = 15, + kXPathLookupError = 19, + kNoSuchWindow = 23, + kInvalidCookieDomain = 24, + kUnableToSetCookie = 25, + + // HTTP status codes. + kSeeOther = 303, + kBadRequest = 400, + kSessionNotFound = 404, + kMethodNotAllowed = 405, + kInternalServerError = 500, +}; + +// Represents a WebDriver error and the context within which the error occurred. +class Error { + public: + explicit Error(ErrorCode code); + + Error(ErrorCode code, const std::string& details); + + virtual ~Error(); + + void AddDetails(const std::string& details); + + // Returns a formatted string describing the error. For logging purposes. + std::string ToString() const; + + ErrorCode code() const; + const std::string& details() const; + const base::debug::StackTrace& trace() const; + + private: + ErrorCode code_; + std::string details_; + base::debug::StackTrace trace_; + + DISALLOW_COPY_AND_ASSIGN(Error); +}; + +} // namespace webdriver + +#endif // CHROME_TEST_WEBDRIVER_WEBDRIVER_ERROR_H_ |