Index: chrome/test/automation/automation_json_requests.cc |
diff --git a/chrome/test/automation/automation_json_requests.cc b/chrome/test/automation/automation_json_requests.cc |
index c05770b023341dc81068215efe1f080aa0522064..00a654f2786b35a9aa3ffe978e6ebce320e450b8 100644 |
--- a/chrome/test/automation/automation_json_requests.cc |
+++ b/chrome/test/automation/automation_json_requests.cc |
@@ -1,637 +1,632 @@ |
-// 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/automation/automation_json_requests.h" |
- |
-#include "base/basictypes.h" |
-#include "base/file_path.h" |
-#include "base/format_macros.h" |
-#include "base/json/json_reader.h" |
-#include "base/json/json_writer.h" |
-#include "base/memory/scoped_ptr.h" |
-#include "base/stringprintf.h" |
-#include "base/test/test_timeouts.h" |
-#include "base/time.h" |
-#include "base/values.h" |
-#include "chrome/common/automation_messages.h" |
-#include "chrome/test/automation/automation_proxy.h" |
-#include "content/common/json_value_serializer.h" |
- |
-namespace { |
- |
-bool SendAutomationJSONRequest(AutomationMessageSender* sender, |
- const DictionaryValue& request_dict, |
- DictionaryValue* reply_dict, |
- std::string* error_msg) { |
- std::string request, reply; |
- base::JSONWriter::Write(&request_dict, false, &request); |
- bool success = false; |
- int timeout_ms = TestTimeouts::action_max_timeout_ms(); |
- base::Time before_sending = base::Time::Now(); |
- if (!SendAutomationJSONRequest( |
- sender, request, timeout_ms, &reply, &success)) { |
- int64 elapsed_ms = (base::Time::Now() - before_sending).InMilliseconds(); |
- std::string command; |
- request_dict.GetString("command", &command); |
- if (elapsed_ms >= timeout_ms) { |
- *error_msg = base::StringPrintf( |
- "Chrome did not respond to '%s'. Request may have timed out. " |
- "Elapsed time was %" PRId64 " ms. Request timeout was %d ms. " |
- "Request details: (%s).", |
- command.c_str(), |
- elapsed_ms, |
- timeout_ms, |
- request.c_str()); |
- } else { |
- *error_msg = base::StringPrintf( |
- "Chrome did not respond to '%s'. Elapsed time was %" PRId64 " ms. " |
- "Request details: (%s).", |
- command.c_str(), |
- elapsed_ms, |
- request.c_str()); |
- } |
- return false; |
- } |
- scoped_ptr<Value> value(base::JSONReader::Read(reply, true)); |
- if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) { |
- std::string command; |
- request_dict.GetString("command", &command); |
- LOG(ERROR) << "JSON request did not return dict: " << command << "\n"; |
- return false; |
- } |
- DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); |
- if (!success) { |
- std::string command, error; |
- request_dict.GetString("command", &command); |
- dict->GetString("error", &error); |
- *error_msg = base::StringPrintf( |
- "Internal Chrome error during '%s': (%s). Request details: (%s).", |
- command.c_str(), |
- error.c_str(), |
- request.c_str()); |
- LOG(ERROR) << "JSON request failed: " << command << "\n" |
- << " with error: " << error; |
- return false; |
- } |
- reply_dict->MergeDictionary(dict); |
- return true; |
-} |
- |
-} // namespace |
- |
-WebKeyEvent::WebKeyEvent(automation::KeyEventTypes type, |
- ui::KeyboardCode key_code, |
- const std::string& unmodified_text, |
- const std::string& modified_text, |
- int modifiers) |
- : type(type), |
- key_code(key_code), |
- unmodified_text(unmodified_text), |
- modified_text(modified_text), |
- modifiers(modifiers) {} |
- |
-bool SendAutomationJSONRequest(AutomationMessageSender* sender, |
- const std::string& request, |
- int timeout_ms, |
- std::string* reply, |
- bool* success) { |
- return sender->Send(new AutomationMsg_SendJSONRequest( |
- -1, request, reply, success), timeout_ms); |
-} |
- |
-bool SendGetIndicesFromTabIdJSONRequest( |
- AutomationMessageSender* sender, |
- int tab_id, |
- int* browser_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, error_msg)) |
- return false; |
- if (!reply_dict.GetInteger("windex", browser_index)) |
- return false; |
- if (!reply_dict.GetInteger("tab_index", tab_index)) |
- return false; |
- return true; |
-} |
- |
-bool SendGetIndicesFromTabHandleJSONRequest( |
- AutomationMessageSender* sender, |
- int tab_handle, |
- int* browser_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, error_msg)) |
- return false; |
- if (!reply_dict.GetInteger("windex", browser_index)) |
- return false; |
- if (!reply_dict.GetInteger("tab_index", tab_index)) |
- return false; |
- return true; |
-} |
- |
-bool SendNavigateToURLJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- const GURL& url, |
- int navigation_count, |
- AutomationMsg_NavigationResponseValues* nav_response, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "NavigateToURL"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetInteger("tab_index", tab_index); |
- dict.SetString("url", url.possibly_invalid_spec()); |
- dict.SetInteger("navigation_count", navigation_count); |
- DictionaryValue reply_dict; |
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) |
- return false; |
- int response = 0; |
- if (!reply_dict.GetInteger("result", &response)) |
- return false; |
- *nav_response = static_cast<AutomationMsg_NavigationResponseValues>(response); |
- return true; |
-} |
- |
-bool SendExecuteJavascriptJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- const std::string& frame_xpath, |
- const std::string& javascript, |
- Value** result, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "ExecuteJavascript"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetInteger("tab_index", tab_index); |
- dict.SetString("frame_xpath", frame_xpath); |
- dict.SetString("javascript", javascript); |
- DictionaryValue reply_dict; |
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) |
- return false; |
- |
- std::string json; |
- if (!reply_dict.GetString("result", &json)) { |
- LOG(ERROR) << "Executed javascript but received no 'result'"; |
- return false; |
- } |
- // Wrap |json| in an array before deserializing because valid JSON has an |
- // array or an object as the root. |
- json.insert(0, "["); |
- json.append("]"); |
- |
- JSONStringValueSerializer deserializer(json); |
- Value* value = deserializer.Deserialize(NULL, NULL); |
- if (!value || !value->IsType(Value::TYPE_LIST)) { |
- LOG(ERROR) << "Unable to deserialize returned JSON"; |
- return false; |
- } |
- scoped_ptr<ListValue> list(static_cast<ListValue*>(value)); |
- return list->Remove(0, result); |
-} |
- |
-bool SendGoForwardJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_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, error_msg); |
-} |
- |
-bool SendGoBackJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_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, error_msg); |
-} |
- |
-bool SendReloadJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_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, error_msg); |
-} |
- |
-bool SendCaptureEntirePageJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- const FilePath& path, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "CaptureEntirePage"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetInteger("tab_index", tab_index); |
- dict.SetString("path", path.value()); |
- DictionaryValue 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* 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, error_msg)) |
- return false; |
- return reply_dict.GetString("url", url); |
-} |
- |
-bool SendGetTabTitleJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- 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, error_msg)) |
- return false; |
- return reply_dict.GetString("title", tab_title); |
-} |
- |
-bool SendGetCookiesJSONRequest( |
- AutomationMessageSender* sender, |
- const std::string& url, |
- 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, error_msg)) |
- return false; |
- Value* cookies_unscoped_value; |
- if (!reply_dict.Remove("cookies", &cookies_unscoped_value)) |
- return false; |
- scoped_ptr<Value> cookies_value(cookies_unscoped_value); |
- if (!cookies_value->IsType(Value::TYPE_LIST)) |
- return false; |
- *cookies = static_cast<ListValue*>(cookies_value.release()); |
- return true; |
-} |
- |
-bool SendGetCookiesJSONRequestDeprecated( |
- AutomationMessageSender* sender, |
- int browser_index, |
- const std::string& url, |
- std::string* cookies) { |
- DictionaryValue dict; |
- dict.SetString("command", "GetCookies"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetString("url", url); |
- DictionaryValue reply_dict; |
- std::string error_msg; |
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, &error_msg)) |
- return false; |
- return reply_dict.GetString("cookies", cookies); |
-} |
- |
-bool SendDeleteCookieJSONRequest( |
- AutomationMessageSender* sender, |
- const std::string& url, |
- 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, error_msg); |
-} |
- |
-bool SendDeleteCookieJSONRequestDeprecated( |
- AutomationMessageSender* sender, |
- int browser_index, |
- const std::string& url, |
- const std::string& cookie_name) { |
- DictionaryValue dict; |
- dict.SetString("command", "DeleteCookie"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetString("url", url); |
- dict.SetString("name", cookie_name); |
- DictionaryValue 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, |
- 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, error_msg); |
-} |
- |
-bool SendSetCookieJSONRequestDeprecated( |
- AutomationMessageSender* sender, |
- int browser_index, |
- const std::string& url, |
- const std::string& cookie) { |
- DictionaryValue dict; |
- dict.SetString("command", "SetCookie"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetString("url", url); |
- dict.SetString("cookie", cookie); |
- DictionaryValue reply_dict; |
- std::string error_msg; |
- return SendAutomationJSONRequest(sender, dict, &reply_dict, &error_msg); |
-} |
- |
-bool SendGetTabIdsJSONRequest( |
- 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, error_msg)) |
- return false; |
- ListValue* id_list; |
- if (!reply_dict.GetList("ids", &id_list)) { |
- LOG(ERROR) << "Returned 'ids' key is missing or invalid"; |
- return false; |
- } |
- std::vector<int> temp_ids; |
- for (size_t i = 0; i < id_list->GetSize(); ++i) { |
- int id; |
- if (!id_list->GetInteger(i, &id)) { |
- LOG(ERROR) << "Returned 'ids' key contains non-integer values"; |
- return false; |
- } |
- temp_ids.push_back(id); |
- } |
- *tab_ids = temp_ids; |
- return true; |
-} |
- |
-bool SendIsTabIdValidJSONRequest( |
- 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, error_msg)) |
- return false; |
- return reply_dict.GetBoolean("is_valid", is_valid); |
-} |
- |
-bool SendCloseTabJSONRequest( |
- 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, error_msg); |
-} |
- |
-bool SendMouseMoveJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- int x, |
- int y, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "WebkitMouseMove"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetInteger("tab_index", tab_index); |
- dict.SetInteger("x", x); |
- dict.SetInteger("y", y); |
- DictionaryValue reply_dict; |
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
-} |
- |
-bool SendMouseClickJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- automation::MouseButton button, |
- int x, |
- int y, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "WebkitMouseClick"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetInteger("tab_index", tab_index); |
- dict.SetInteger("button", button); |
- dict.SetInteger("x", x); |
- dict.SetInteger("y", y); |
- DictionaryValue reply_dict; |
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
-} |
- |
-bool SendMouseDragJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- int start_x, |
- int start_y, |
- int end_x, |
- int end_y, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "WebkitMouseDrag"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetInteger("tab_index", tab_index); |
- dict.SetInteger("start_x", start_x); |
- dict.SetInteger("start_y", start_y); |
- dict.SetInteger("end_x", end_x); |
- dict.SetInteger("end_y", end_y); |
- DictionaryValue reply_dict; |
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
-} |
- |
-bool SendMouseButtonDownJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- int x, |
- int y, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "WebkitMouseButtonDown"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetInteger("tab_index", tab_index); |
- dict.SetInteger("x", x); |
- dict.SetInteger("y", y); |
- DictionaryValue reply_dict; |
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
-} |
- |
-bool SendMouseButtonUpJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- int x, |
- int y, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "WebkitMouseButtonUp"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetInteger("tab_index", tab_index); |
- dict.SetInteger("x", x); |
- dict.SetInteger("y", y); |
- DictionaryValue reply_dict; |
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
-} |
- |
-bool SendMouseDoubleClickJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- int x, |
- int y, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "WebkitMouseDoubleClick"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetInteger("tab_index", tab_index); |
- dict.SetInteger("x", x); |
- dict.SetInteger("y", y); |
- DictionaryValue reply_dict; |
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
-} |
- |
-bool SendWebKeyEventJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- const WebKeyEvent& key_event, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "SendWebkitKeyEvent"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetInteger("tab_index", tab_index); |
- dict.SetInteger("type", key_event.type); |
- dict.SetInteger("nativeKeyCode", key_event.key_code); |
- dict.SetInteger("windowsKeyCode", key_event.key_code); |
- dict.SetString("unmodifiedText", key_event.unmodified_text); |
- dict.SetString("text", key_event.modified_text); |
- dict.SetInteger("modifiers", key_event.modifiers); |
- dict.SetBoolean("isSystemKey", false); |
- DictionaryValue reply_dict; |
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
-} |
- |
-bool SendNativeKeyEventJSONRequest( |
- AutomationMessageSender* sender, |
- int browser_index, |
- int tab_index, |
- ui::KeyboardCode key_code, |
- int modifiers, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "SendOSLevelKeyEventToTab"); |
- dict.SetInteger("windex", browser_index); |
- dict.SetInteger("tab_index", tab_index); |
- dict.SetInteger("keyCode", key_code); |
- dict.SetInteger("modifiers", modifiers); |
- DictionaryValue reply_dict; |
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
-} |
- |
-bool SendGetAppModalDialogMessageJSONRequest( |
- AutomationMessageSender* sender, |
- std::string* message, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "GetAppModalDialogMessage"); |
- DictionaryValue reply_dict; |
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) |
- return false; |
- return reply_dict.GetString("message", message); |
-} |
- |
-bool SendAcceptOrDismissAppModalDialogJSONRequest( |
- AutomationMessageSender* sender, |
- 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, error_msg); |
-} |
- |
-bool SendAcceptPromptAppModalDialogJSONRequest( |
- AutomationMessageSender* sender, |
- 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, error_msg); |
-} |
- |
-bool SendWaitForAllTabsToStopLoadingJSONRequest( |
- AutomationMessageSender* sender, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "WaitForAllTabsToStopLoading"); |
- DictionaryValue reply_dict; |
- return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
-} |
- |
-bool SendGetChromeDriverAutomationVersion( |
- AutomationMessageSender* sender, |
- int* version, |
- std::string* error_msg) { |
- DictionaryValue dict; |
- dict.SetString("command", "GetChromeDriverAutomationVersion"); |
- DictionaryValue reply_dict; |
- if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) |
- return false; |
- return reply_dict.GetInteger("version", version); |
-} |
+// 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/automation/automation_json_requests.h" |
+ |
+#include "base/basictypes.h" |
+#include "base/file_path.h" |
+#include "base/format_macros.h" |
+#include "base/json/json_reader.h" |
+#include "base/json/json_writer.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/stringprintf.h" |
+#include "base/test/test_timeouts.h" |
+#include "base/time.h" |
+#include "base/values.h" |
+#include "chrome/common/automation_messages.h" |
+#include "chrome/test/automation/automation_proxy.h" |
+#include "content/common/json_value_serializer.h" |
+ |
+namespace { |
+ |
+bool SendAutomationJSONRequest(AutomationMessageSender* sender, |
+ const DictionaryValue& request_dict, |
+ DictionaryValue* reply_dict, |
+ std::string* error_msg) { |
+ std::string request, reply; |
+ base::JSONWriter::Write(&request_dict, false, &request); |
+ std::string command; |
+ request_dict.GetString("command", &command); |
+ LOG(INFO) << "Sending '" << command << "' command."; |
+ |
+ base::Time before_sending = base::Time::Now(); |
+ bool success = false; |
+ if (!SendAutomationJSONRequestWithDefaultTimeout( |
+ sender, request, &reply, &success)) { |
+ *error_msg = base::StringPrintf( |
+ "Chrome did not respond to '%s'. Elapsed time was %" PRId64 " ms. " |
+ "Request details: (%s).", |
+ command.c_str(), |
+ (base::Time::Now() - before_sending).InMilliseconds(), |
+ request.c_str()); |
+ return false; |
+ } |
+ scoped_ptr<Value> value(base::JSONReader::Read(reply, true)); |
+ if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) { |
+ LOG(ERROR) << "JSON request did not return dict: " << command << "\n"; |
+ return false; |
+ } |
+ DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); |
+ if (!success) { |
+ std::string error; |
+ dict->GetString("error", &error); |
+ *error_msg = base::StringPrintf( |
+ "Internal Chrome error during '%s': (%s). Request details: (%s).", |
+ command.c_str(), |
+ error.c_str(), |
+ request.c_str()); |
+ LOG(ERROR) << "JSON request failed: " << command << "\n" |
+ << " with error: " << error; |
+ return false; |
+ } |
+ reply_dict->MergeDictionary(dict); |
+ return true; |
+} |
+ |
+} // namespace |
+ |
+WebKeyEvent::WebKeyEvent(automation::KeyEventTypes type, |
+ ui::KeyboardCode key_code, |
+ const std::string& unmodified_text, |
+ const std::string& modified_text, |
+ int modifiers) |
+ : type(type), |
+ key_code(key_code), |
+ unmodified_text(unmodified_text), |
+ modified_text(modified_text), |
+ modifiers(modifiers) {} |
+ |
+bool SendAutomationJSONRequest(AutomationMessageSender* sender, |
+ const std::string& request, |
+ int timeout_ms, |
+ std::string* reply, |
+ bool* success) { |
+ return sender->Send(new AutomationMsg_SendJSONRequest( |
+ -1, request, reply, success), timeout_ms); |
+} |
+ |
+bool SendAutomationJSONRequestWithDefaultTimeout( |
+ AutomationMessageSender* sender, |
+ const std::string& request, |
+ std::string* reply, |
+ bool* success) { |
+ return sender->Send(new AutomationMsg_SendJSONRequest( |
+ -1, request, reply, success)); |
+} |
+ |
+bool SendGetIndicesFromTabIdJSONRequest( |
+ AutomationMessageSender* sender, |
+ int tab_id, |
+ int* browser_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, error_msg)) |
+ return false; |
+ if (!reply_dict.GetInteger("windex", browser_index)) |
+ return false; |
+ if (!reply_dict.GetInteger("tab_index", tab_index)) |
+ return false; |
+ return true; |
+} |
+ |
+bool SendGetIndicesFromTabHandleJSONRequest( |
+ AutomationMessageSender* sender, |
+ int tab_handle, |
+ int* browser_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, error_msg)) |
+ return false; |
+ if (!reply_dict.GetInteger("windex", browser_index)) |
+ return false; |
+ if (!reply_dict.GetInteger("tab_index", tab_index)) |
+ return false; |
+ return true; |
+} |
+ |
+bool SendNavigateToURLJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ const GURL& url, |
+ int navigation_count, |
+ AutomationMsg_NavigationResponseValues* nav_response, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "NavigateToURL"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetInteger("tab_index", tab_index); |
+ dict.SetString("url", url.possibly_invalid_spec()); |
+ dict.SetInteger("navigation_count", navigation_count); |
+ DictionaryValue reply_dict; |
+ if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) |
+ return false; |
+ int response = 0; |
+ if (!reply_dict.GetInteger("result", &response)) |
+ return false; |
+ *nav_response = static_cast<AutomationMsg_NavigationResponseValues>(response); |
+ return true; |
+} |
+ |
+bool SendExecuteJavascriptJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ const std::string& frame_xpath, |
+ const std::string& javascript, |
+ Value** result, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "ExecuteJavascript"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetInteger("tab_index", tab_index); |
+ dict.SetString("frame_xpath", frame_xpath); |
+ dict.SetString("javascript", javascript); |
+ DictionaryValue reply_dict; |
+ if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) |
+ return false; |
+ |
+ std::string json; |
+ if (!reply_dict.GetString("result", &json)) { |
+ LOG(ERROR) << "Executed javascript but received no 'result'"; |
+ return false; |
+ } |
+ // Wrap |json| in an array before deserializing because valid JSON has an |
+ // array or an object as the root. |
+ json.insert(0, "["); |
+ json.append("]"); |
+ |
+ JSONStringValueSerializer deserializer(json); |
+ Value* value = deserializer.Deserialize(NULL, NULL); |
+ if (!value || !value->IsType(Value::TYPE_LIST)) { |
+ LOG(ERROR) << "Unable to deserialize returned JSON"; |
+ return false; |
+ } |
+ scoped_ptr<ListValue> list(static_cast<ListValue*>(value)); |
+ return list->Remove(0, result); |
+} |
+ |
+bool SendGoForwardJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_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, error_msg); |
+} |
+ |
+bool SendGoBackJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_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, error_msg); |
+} |
+ |
+bool SendReloadJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_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, error_msg); |
+} |
+ |
+bool SendCaptureEntirePageJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ const FilePath& path, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "CaptureEntirePage"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetInteger("tab_index", tab_index); |
+ dict.SetString("path", path.value()); |
+ DictionaryValue 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* 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, error_msg)) |
+ return false; |
+ return reply_dict.GetString("url", url); |
+} |
+ |
+bool SendGetTabTitleJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ 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, error_msg)) |
+ return false; |
+ return reply_dict.GetString("title", tab_title); |
+} |
+ |
+bool SendGetCookiesJSONRequest( |
+ AutomationMessageSender* sender, |
+ const std::string& url, |
+ 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, error_msg)) |
+ return false; |
+ Value* cookies_unscoped_value; |
+ if (!reply_dict.Remove("cookies", &cookies_unscoped_value)) |
+ return false; |
+ scoped_ptr<Value> cookies_value(cookies_unscoped_value); |
+ if (!cookies_value->IsType(Value::TYPE_LIST)) |
+ return false; |
+ *cookies = static_cast<ListValue*>(cookies_value.release()); |
+ return true; |
+} |
+ |
+bool SendGetCookiesJSONRequestDeprecated( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ const std::string& url, |
+ std::string* cookies) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "GetCookies"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetString("url", url); |
+ DictionaryValue reply_dict; |
+ std::string error_msg; |
+ if (!SendAutomationJSONRequest(sender, dict, &reply_dict, &error_msg)) |
+ return false; |
+ return reply_dict.GetString("cookies", cookies); |
+} |
+ |
+bool SendDeleteCookieJSONRequest( |
+ AutomationMessageSender* sender, |
+ const std::string& url, |
+ 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, error_msg); |
+} |
+ |
+bool SendDeleteCookieJSONRequestDeprecated( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ const std::string& url, |
+ const std::string& cookie_name) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "DeleteCookie"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetString("url", url); |
+ dict.SetString("name", cookie_name); |
+ DictionaryValue 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, |
+ 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, error_msg); |
+} |
+ |
+bool SendSetCookieJSONRequestDeprecated( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ const std::string& url, |
+ const std::string& cookie) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "SetCookie"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetString("url", url); |
+ dict.SetString("cookie", cookie); |
+ DictionaryValue reply_dict; |
+ std::string error_msg; |
+ return SendAutomationJSONRequest(sender, dict, &reply_dict, &error_msg); |
+} |
+ |
+bool SendGetTabIdsJSONRequest( |
+ 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, error_msg)) |
+ return false; |
+ ListValue* id_list; |
+ if (!reply_dict.GetList("ids", &id_list)) { |
+ LOG(ERROR) << "Returned 'ids' key is missing or invalid"; |
+ return false; |
+ } |
+ std::vector<int> temp_ids; |
+ for (size_t i = 0; i < id_list->GetSize(); ++i) { |
+ int id; |
+ if (!id_list->GetInteger(i, &id)) { |
+ LOG(ERROR) << "Returned 'ids' key contains non-integer values"; |
+ return false; |
+ } |
+ temp_ids.push_back(id); |
+ } |
+ *tab_ids = temp_ids; |
+ return true; |
+} |
+ |
+bool SendIsTabIdValidJSONRequest( |
+ 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, error_msg)) |
+ return false; |
+ return reply_dict.GetBoolean("is_valid", is_valid); |
+} |
+ |
+bool SendCloseTabJSONRequest( |
+ 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, error_msg); |
+} |
+ |
+bool SendMouseMoveJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ int x, |
+ int y, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "WebkitMouseMove"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetInteger("tab_index", tab_index); |
+ dict.SetInteger("x", x); |
+ dict.SetInteger("y", y); |
+ DictionaryValue reply_dict; |
+ return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
+} |
+ |
+bool SendMouseClickJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ automation::MouseButton button, |
+ int x, |
+ int y, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "WebkitMouseClick"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetInteger("tab_index", tab_index); |
+ dict.SetInteger("button", button); |
+ dict.SetInteger("x", x); |
+ dict.SetInteger("y", y); |
+ DictionaryValue reply_dict; |
+ return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
+} |
+ |
+bool SendMouseDragJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ int start_x, |
+ int start_y, |
+ int end_x, |
+ int end_y, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "WebkitMouseDrag"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetInteger("tab_index", tab_index); |
+ dict.SetInteger("start_x", start_x); |
+ dict.SetInteger("start_y", start_y); |
+ dict.SetInteger("end_x", end_x); |
+ dict.SetInteger("end_y", end_y); |
+ DictionaryValue reply_dict; |
+ return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
+} |
+ |
+bool SendMouseButtonDownJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ int x, |
+ int y, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "WebkitMouseButtonDown"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetInteger("tab_index", tab_index); |
+ dict.SetInteger("x", x); |
+ dict.SetInteger("y", y); |
+ DictionaryValue reply_dict; |
+ return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
+} |
+ |
+bool SendMouseButtonUpJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ int x, |
+ int y, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "WebkitMouseButtonUp"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetInteger("tab_index", tab_index); |
+ dict.SetInteger("x", x); |
+ dict.SetInteger("y", y); |
+ DictionaryValue reply_dict; |
+ return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
+} |
+ |
+bool SendMouseDoubleClickJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ int x, |
+ int y, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "WebkitMouseDoubleClick"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetInteger("tab_index", tab_index); |
+ dict.SetInteger("x", x); |
+ dict.SetInteger("y", y); |
+ DictionaryValue reply_dict; |
+ return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
+} |
+ |
+bool SendWebKeyEventJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ const WebKeyEvent& key_event, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "SendWebkitKeyEvent"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetInteger("tab_index", tab_index); |
+ dict.SetInteger("type", key_event.type); |
+ dict.SetInteger("nativeKeyCode", key_event.key_code); |
+ dict.SetInteger("windowsKeyCode", key_event.key_code); |
+ dict.SetString("unmodifiedText", key_event.unmodified_text); |
+ dict.SetString("text", key_event.modified_text); |
+ dict.SetInteger("modifiers", key_event.modifiers); |
+ dict.SetBoolean("isSystemKey", false); |
+ DictionaryValue reply_dict; |
+ return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
+} |
+ |
+bool SendNativeKeyEventJSONRequest( |
+ AutomationMessageSender* sender, |
+ int browser_index, |
+ int tab_index, |
+ ui::KeyboardCode key_code, |
+ int modifiers, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "SendOSLevelKeyEventToTab"); |
+ dict.SetInteger("windex", browser_index); |
+ dict.SetInteger("tab_index", tab_index); |
+ dict.SetInteger("keyCode", key_code); |
+ dict.SetInteger("modifiers", modifiers); |
+ DictionaryValue reply_dict; |
+ return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
+} |
+ |
+bool SendGetAppModalDialogMessageJSONRequest( |
+ AutomationMessageSender* sender, |
+ std::string* message, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "GetAppModalDialogMessage"); |
+ DictionaryValue reply_dict; |
+ if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) |
+ return false; |
+ return reply_dict.GetString("message", message); |
+} |
+ |
+bool SendAcceptOrDismissAppModalDialogJSONRequest( |
+ AutomationMessageSender* sender, |
+ 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, error_msg); |
+} |
+ |
+bool SendAcceptPromptAppModalDialogJSONRequest( |
+ AutomationMessageSender* sender, |
+ 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, error_msg); |
+} |
+ |
+bool SendWaitForAllTabsToStopLoadingJSONRequest( |
+ AutomationMessageSender* sender, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "WaitForAllTabsToStopLoading"); |
+ DictionaryValue reply_dict; |
+ return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg); |
+} |
+ |
+bool SendGetChromeDriverAutomationVersion( |
+ AutomationMessageSender* sender, |
+ int* version, |
+ std::string* error_msg) { |
+ DictionaryValue dict; |
+ dict.SetString("command", "GetChromeDriverAutomationVersion"); |
+ DictionaryValue reply_dict; |
+ if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg)) |
+ return false; |
+ return reply_dict.GetInteger("version", version); |
+} |