Index: chrome/test/webdriver/automation.cc |
diff --git a/chrome/test/webdriver/automation.cc b/chrome/test/webdriver/automation.cc |
index de44bebfca7bc951705f5b985a55134f54d94671..2c7e2258b99a4b471bfb20bdae2576a92691cae2 100644 |
--- a/chrome/test/webdriver/automation.cc |
+++ b/chrome/test/webdriver/automation.cc |
@@ -1,665 +1,665 @@ |
-// 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/automation.h" |
- |
-#if defined(OS_WIN) |
-#include <windows.h> |
-#endif |
- |
-#include "base/base_paths.h" |
-#include "base/command_line.h" |
-#include "base/environment.h" |
-#include "base/file_path.h" |
-#include "base/file_util.h" |
-#include "base/json/json_writer.h" |
-#include "base/logging.h" |
-#include "base/path_service.h" |
-#include "base/string_number_conversions.h" |
-#include "base/string_split.h" |
-#include "base/stringprintf.h" |
-#include "base/synchronization/waitable_event.h" |
-#include "base/utf_string_conversions.h" |
-#include "base/values.h" |
-#include "chrome/common/automation_constants.h" |
-#include "chrome/common/chrome_constants.h" |
-#include "chrome/common/chrome_switches.h" |
-#include "chrome/common/url_constants.h" |
-#include "chrome/test/automation/automation_json_requests.h" |
-#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" |
- |
-#if defined(OS_WIN) |
-#include "base/win/registry.h" |
-#include "base/win/windows_version.h" |
-#endif |
- |
-namespace { |
- |
-// Gets the path to the default Chrome executable. Returns true on success. |
-bool GetDefaultChromeExe(FilePath* browser_exe) { |
- std::vector<FilePath> locations; |
- // Add the directory which this module resides in. |
- FilePath module_dir; |
- if (PathService::Get(base::DIR_MODULE, &module_dir)) |
- locations.push_back(module_dir); |
- |
-#if defined(OS_WIN) |
- // Add the App Paths registry key location. |
- const wchar_t kSubKey[] = |
- L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe"; |
- base::win::RegKey key(HKEY_CURRENT_USER, kSubKey, KEY_READ); |
- std::wstring path; |
- if (key.ReadValue(L"path", &path) == ERROR_SUCCESS) |
- locations.push_back(FilePath(path)); |
- base::win::RegKey sys_key(HKEY_LOCAL_MACHINE, kSubKey, KEY_READ); |
- if (sys_key.ReadValue(L"path", &path) == ERROR_SUCCESS) |
- locations.push_back(FilePath(path)); |
- |
- // Add the user-level location for Chrome. |
- FilePath app_from_google(L"Google\\Chrome\\Application"); |
- scoped_ptr<base::Environment> env(base::Environment::Create()); |
- std::string home_dir; |
- if (env->GetVar("userprofile", &home_dir)) { |
- FilePath default_location(UTF8ToWide(home_dir)); |
- if (base::win::GetVersion() < base::win::VERSION_VISTA) { |
- default_location = default_location.Append( |
- L"Local Settings\\Application Data"); |
- } else { |
- default_location = default_location.Append(L"AppData\\Local"); |
- } |
- locations.push_back(default_location.Append(app_from_google)); |
- } |
- |
- // Add the system-level location for Chrome. |
- std::string program_dir; |
- if (env->GetVar("ProgramFiles", &program_dir)) { |
- locations.push_back(FilePath(UTF8ToWide(program_dir)) |
- .Append(app_from_google)); |
- } |
- if (env->GetVar("ProgramFiles(x86)", &program_dir)) { |
- locations.push_back(FilePath(UTF8ToWide(program_dir)) |
- .Append(app_from_google)); |
- } |
-#elif defined(OS_MACOSX) |
- locations.push_back(FilePath("/Applications")); |
-#elif defined(OS_LINUX) |
- // Proxy launcher doesn't check for google-chrome, only chrome. |
- FilePath chrome_sym_link("/usr/bin/google-chrome"); |
- if (file_util::PathExists(chrome_sym_link)) { |
- FilePath chrome; |
- if (file_util::ReadSymbolicLink(chrome_sym_link, &chrome)) { |
- locations.push_back(chrome.DirName()); |
- } |
- } |
-#endif |
- |
- // Add the current directory. |
- FilePath current_dir; |
- if (file_util::GetCurrentDirectory(¤t_dir)) |
- locations.push_back(current_dir); |
- |
- // Determine the default directory. |
- for (size_t i = 0; i < locations.size(); ++i) { |
- FilePath path = locations[i].Append(chrome::kBrowserProcessExecutablePath); |
- if (file_util::PathExists(path)) { |
- *browser_exe = path; |
- return true; |
- } |
- } |
- return false; |
-} |
- |
-} // namespace |
- |
-namespace webdriver { |
- |
-Automation::Automation() {} |
- |
-Automation::~Automation() {} |
- |
-void Automation::Init(const CommandLine& options, |
- Error** error) { |
- FilePath browser_exe; |
- if (!GetDefaultChromeExe(&browser_exe)) { |
- *error = new Error(kUnknownError, "Could not find default Chrome binary"); |
- return; |
- } |
- |
- InitWithBrowserPath(browser_exe, options, error); |
-} |
- |
-void Automation::InitWithBrowserPath(const FilePath& browser_exe, |
- const CommandLine& options, |
- Error** error) { |
- if (!file_util::PathExists(browser_exe)) { |
- std::string message = base::StringPrintf( |
- "Could not find Chrome binary at: %" PRFilePath, |
- browser_exe.value().c_str()); |
- *error = new Error(kUnknownError, message); |
- return; |
- } |
- |
- CommandLine command(browser_exe); |
- command.AppendSwitch(switches::kDisableHangMonitor); |
- command.AppendSwitch(switches::kDisablePromptOnRepost); |
- command.AppendSwitch(switches::kDomAutomationController); |
- command.AppendSwitch(switches::kFullMemoryCrashReport); |
- command.AppendSwitchASCII(switches::kHomePage, chrome::kAboutBlankURL); |
- command.AppendSwitch(switches::kNoDefaultBrowserCheck); |
- command.AppendSwitch(switches::kNoFirstRun); |
- command.AppendSwitchASCII(switches::kTestType, "webdriver"); |
- |
- command.AppendArguments(options, false); |
- |
- launcher_.reset(new AnonymousProxyLauncher(false)); |
- ProxyLauncher::LaunchState launch_props = { |
- false, // clear_profile |
- FilePath(), // template_user_data |
- ProxyLauncher::DEFAULT_THEME, |
- command, |
- true, // include_testing_id |
- true // show_window |
- }; |
- |
- std::string chrome_details = base::StringPrintf( |
- "Using Chrome binary at: %" PRFilePath, |
- browser_exe.value().c_str()); |
- VLOG(1) << chrome_details; |
- |
- if (!launcher_->LaunchBrowserAndServer(launch_props, true)) { |
- *error = new Error( |
- kUnknownError, |
- "Unable to either launch or connect to Chrome. Please check that " |
- "ChromeDriver is up-to-date. " + chrome_details); |
- return; |
- } |
- |
- launcher_->automation()->set_action_timeout_ms(base::kNoTimeout); |
- VLOG(1) << "Chrome launched successfully. Version: " |
- << automation()->server_version(); |
- |
- bool has_automation_version = false; |
- *error = CompareVersion(730, 0, &has_automation_version); |
- if (*error) |
- return; |
- |
- chrome_details += ", version (" + automation()->server_version() + ")"; |
- if (has_automation_version) { |
- int version = 0; |
- std::string error_msg; |
- if (!SendGetChromeDriverAutomationVersion( |
- automation(), &version, &error_msg)) { |
- *error = new Error(kUnknownError, error_msg + " " + chrome_details); |
- return; |
- } |
- if (version > automation::kChromeDriverAutomationVersion) { |
- *error = new Error( |
- kUnknownError, |
- "ChromeDriver is not compatible with this version of Chrome. " + |
- chrome_details); |
- return; |
- } |
- } |
-} |
- |
-void Automation::Terminate() { |
- if (launcher_.get() && launcher_->process() != base::kNullProcessHandle) { |
- launcher_->QuitBrowser(); |
- } |
-} |
- |
-void Automation::ExecuteScript(int tab_id, |
- const FramePath& frame_path, |
- const std::string& script, |
- std::string* result, |
- Error** error) { |
- int windex = 0, tab_index = 0; |
- *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, &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- return; |
- } |
- scoped_ptr<Value> value(unscoped_value); |
- if (!value->GetAsString(result)) |
- *error = new Error(kUnknownError, "Execute script did not return string"); |
-} |
- |
-void Automation::MouseMove(int tab_id, |
- const gfx::Point& p, |
- Error** error) { |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendMouseMoveJSONRequest( |
- automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::MouseClick(int tab_id, |
- const gfx::Point& p, |
- automation::MouseButton button, |
- Error** error) { |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendMouseClickJSONRequest( |
- automation(), windex, tab_index, button, p.x(), p.y(), &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::MouseDrag(int tab_id, |
- const gfx::Point& start, |
- const gfx::Point& end, |
- Error** error) { |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendMouseDragJSONRequest(automation(), windex, tab_index, start.x(), |
- start.y(), end.x(), end.y(), &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::MouseButtonUp(int tab_id, |
- const gfx::Point& p, |
- Error** error) { |
- *error = CheckAdvancedInteractionsSupported(); |
- if (*error) |
- return; |
- |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendMouseButtonUpJSONRequest( |
- automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::MouseButtonDown(int tab_id, |
- const gfx::Point& p, |
- Error** error) { |
- *error = CheckAdvancedInteractionsSupported(); |
- if (*error) |
- return; |
- |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendMouseButtonDownJSONRequest( |
- automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::MouseDoubleClick(int tab_id, |
- const gfx::Point& p, |
- Error** error) { |
- *error = CheckAdvancedInteractionsSupported(); |
- if (*error) |
- return; |
- |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendMouseDoubleClickJSONRequest( |
- automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::SendWebKeyEvent(int tab_id, |
- const WebKeyEvent& key_event, |
- Error** error) { |
- int windex = 0, tab_index = 0; |
- *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 = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::SendNativeKeyEvent(int tab_id, |
- ui::KeyboardCode key_code, |
- int modifiers, |
- Error** error) { |
- int windex = 0, tab_index = 0; |
- *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 = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::CaptureEntirePageAsPNG(int tab_id, |
- const FilePath& path, |
- Error** error) { |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendCaptureEntirePageJSONRequest( |
- automation(), windex, tab_index, path, &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::NavigateToURL(int tab_id, |
- const std::string& url, |
- Error** error) { |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- AutomationMsg_NavigationResponseValues navigate_response; |
- std::string error_msg; |
- if (!SendNavigateToURLJSONRequest(automation(), windex, tab_index, |
- GURL(url), 1, &navigate_response, |
- &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- return; |
- } |
- // 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, Error** error) { |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendGoForwardJSONRequest( |
- automation(), windex, tab_index, &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::GoBack(int tab_id, Error** error) { |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendGoBackJSONRequest(automation(), windex, tab_index, &error_msg)) |
- *error = new Error(kUnknownError, error_msg); |
-} |
- |
-void Automation::Reload(int tab_id, Error** error) { |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendReloadJSONRequest(automation(), windex, tab_index, &error_msg)) |
- *error = new Error(kUnknownError, error_msg); |
-} |
- |
-void Automation::GetCookies(const std::string& url, |
- ListValue** cookies, |
- Error** error) { |
- std::string error_msg; |
- if (!SendGetCookiesJSONRequest(automation(), url, cookies, &error_msg)) |
- *error = new Error(kUnknownError, error_msg); |
-} |
- |
-void Automation::GetCookiesDeprecated(int tab_id, |
- const GURL& gurl, |
- std::string* cookies, |
- bool* success) { |
- int windex = 0, tab_index = 0; |
- scoped_ptr<Error> error(GetIndicesForTab(tab_id, &windex, &tab_index)); |
- if (error.get()) { |
- *success = false; |
- return; |
- } |
- |
- *success = SendGetCookiesJSONRequestDeprecated( |
- automation(), windex, gurl.possibly_invalid_spec(), cookies); |
-} |
- |
-void Automation::DeleteCookie(const std::string& url, |
- const std::string& cookie_name, |
- Error** error) { |
- std::string error_msg; |
- if (!SendDeleteCookieJSONRequest( |
- automation(), url, cookie_name, &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::DeleteCookieDeprecated(int tab_id, |
- const GURL& gurl, |
- const std::string& cookie_name, |
- bool* success) { |
- int windex = 0, tab_index = 0; |
- scoped_ptr<Error> error(GetIndicesForTab(tab_id, &windex, &tab_index)); |
- if (error.get()) { |
- *success = false; |
- return; |
- } |
- |
- *success = SendDeleteCookieJSONRequestDeprecated( |
- automation(), |
- windex, |
- gurl.possibly_invalid_spec(), |
- cookie_name); |
-} |
- |
-void Automation::SetCookie(const std::string& url, |
- DictionaryValue* cookie_dict, |
- Error** error) { |
- std::string error_msg; |
- if (!SendSetCookieJSONRequest(automation(), url, cookie_dict, &error_msg)) |
- *error = new Error(kUnknownError, error_msg); |
-} |
- |
-void Automation::SetCookieDeprecated(int tab_id, |
- const GURL& gurl, |
- const std::string& cookie, |
- bool* success) { |
- int windex = 0, tab_index = 0; |
- scoped_ptr<Error> error(GetIndicesForTab(tab_id, &windex, &tab_index)); |
- if (error.get()) { |
- *success = false; |
- return; |
- } |
- |
- *success = SendSetCookieJSONRequestDeprecated( |
- automation(), |
- windex, |
- gurl.possibly_invalid_spec(), |
- cookie); |
-} |
- |
-void Automation::GetTabIds(std::vector<int>* tab_ids, |
- Error** error) { |
- std::string error_msg; |
- if (!SendGetTabIdsJSONRequest(automation(), tab_ids, &error_msg)) |
- *error = new Error(kUnknownError, error_msg); |
-} |
- |
-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 = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::CloseTab(int tab_id, Error** error) { |
- int windex = 0, tab_index = 0; |
- *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendCloseTabJSONRequest(automation(), windex, tab_index, &error_msg)) |
- *error = new Error(kUnknownError, error_msg); |
-} |
- |
-void Automation::GetAppModalDialogMessage(std::string* message, Error** error) { |
- *error = CheckAlertsSupported(); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendGetAppModalDialogMessageJSONRequest( |
- automation(), message, &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::AcceptOrDismissAppModalDialog(bool accept, Error** error) { |
- *error = CheckAlertsSupported(); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendAcceptOrDismissAppModalDialogJSONRequest( |
- automation(), accept, &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::AcceptPromptAppModalDialog(const std::string& prompt_text, |
- Error** error) { |
- *error = CheckAlertsSupported(); |
- if (*error) |
- return; |
- |
- std::string error_msg; |
- if (!SendAcceptPromptAppModalDialogJSONRequest( |
- automation(), prompt_text, &error_msg)) { |
- *error = new Error(kUnknownError, error_msg); |
- } |
-} |
- |
-void Automation::GetBrowserVersion(std::string* version) { |
- *version = automation()->server_version(); |
-} |
- |
-void Automation::GetChromeDriverAutomationVersion(int* version, Error** error) { |
- std::string error_msg; |
- if (!SendGetChromeDriverAutomationVersion(automation(), version, &error_msg)) |
- *error = new Error(kUnknownError, error_msg); |
-} |
- |
-void Automation::WaitForAllTabsToStopLoading(Error** error) { |
- std::string error_msg; |
- if (!SendWaitForAllTabsToStopLoadingJSONRequest(automation(), &error_msg)) |
- *error = new Error(kUnknownError, error_msg); |
-} |
- |
-AutomationProxy* Automation::automation() const { |
- return launcher_->automation(); |
-} |
- |
-Error* Automation::GetIndicesForTab( |
- int tab_id, int* browser_index, int* tab_index) { |
- std::string error_msg; |
- if (!SendGetIndicesFromTabIdJSONRequest( |
- automation(), tab_id, browser_index, tab_index, &error_msg)) { |
- return new Error(kUnknownError, error_msg); |
- } |
- return NULL; |
-} |
- |
-Error* Automation::CompareVersion(int client_build_no, |
- int client_patch_no, |
- bool* is_newer_or_equal) { |
- std::string version = automation()->server_version(); |
- std::vector<std::string> split_version; |
- base::SplitString(version, '.', &split_version); |
- 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 new Error( |
- kUnknownError, "Browser version has unrecognized format: " + version); |
- } |
- if (build_no < client_build_no) |
- *is_newer_or_equal = false; |
- else if (build_no > client_build_no) |
- *is_newer_or_equal = true; |
- else |
- *is_newer_or_equal = patch_no >= client_patch_no; |
- return NULL; |
-} |
- |
-Error* Automation::CheckVersion(int client_build_no, |
- int client_patch_no, |
- const std::string& error_msg) { |
- bool version_is_ok = false; |
- Error* error = CompareVersion( |
- client_build_no, client_patch_no, &version_is_ok); |
- if (error) |
- return error; |
- if (!version_is_ok) |
- return new Error(kUnknownError, error_msg); |
- return NULL; |
-} |
- |
-Error* Automation::CheckAlertsSupported() { |
- return CheckVersion( |
- 768, 0, "Alerts are not supported for this version of Chrome"); |
-} |
- |
-Error* Automation::CheckAdvancedInteractionsSupported() { |
- const char* message = |
- "Advanced user interactions are not supported for this version of Chrome"; |
- return CheckVersion(750, 0, message); |
-} |
- |
-} // namespace webdriver |
+// 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/automation.h" |
+ |
+#if defined(OS_WIN) |
+#include <windows.h> |
+#endif |
+ |
+#include "base/base_paths.h" |
+#include "base/command_line.h" |
+#include "base/environment.h" |
+#include "base/file_path.h" |
+#include "base/file_util.h" |
+#include "base/json/json_writer.h" |
+#include "base/logging.h" |
+#include "base/path_service.h" |
+#include "base/string_number_conversions.h" |
+#include "base/string_split.h" |
+#include "base/stringprintf.h" |
+#include "base/synchronization/waitable_event.h" |
+#include "base/utf_string_conversions.h" |
+#include "base/values.h" |
+#include "chrome/common/automation_constants.h" |
+#include "chrome/common/chrome_constants.h" |
+#include "chrome/common/chrome_switches.h" |
+#include "chrome/common/url_constants.h" |
+#include "chrome/test/automation/automation_json_requests.h" |
+#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" |
+ |
+#if defined(OS_WIN) |
+#include "base/win/registry.h" |
+#include "base/win/windows_version.h" |
+#endif |
+ |
+namespace { |
+ |
+// Gets the path to the default Chrome executable. Returns true on success. |
+bool GetDefaultChromeExe(FilePath* browser_exe) { |
+ std::vector<FilePath> locations; |
+ // Add the directory which this module resides in. |
+ FilePath module_dir; |
+ if (PathService::Get(base::DIR_MODULE, &module_dir)) |
+ locations.push_back(module_dir); |
+ |
+#if defined(OS_WIN) |
+ // Add the App Paths registry key location. |
+ const wchar_t kSubKey[] = |
+ L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe"; |
+ base::win::RegKey key(HKEY_CURRENT_USER, kSubKey, KEY_READ); |
+ std::wstring path; |
+ if (key.ReadValue(L"path", &path) == ERROR_SUCCESS) |
+ locations.push_back(FilePath(path)); |
+ base::win::RegKey sys_key(HKEY_LOCAL_MACHINE, kSubKey, KEY_READ); |
+ if (sys_key.ReadValue(L"path", &path) == ERROR_SUCCESS) |
+ locations.push_back(FilePath(path)); |
+ |
+ // Add the user-level location for Chrome. |
+ FilePath app_from_google(L"Google\\Chrome\\Application"); |
+ scoped_ptr<base::Environment> env(base::Environment::Create()); |
+ std::string home_dir; |
+ if (env->GetVar("userprofile", &home_dir)) { |
+ FilePath default_location(UTF8ToWide(home_dir)); |
+ if (base::win::GetVersion() < base::win::VERSION_VISTA) { |
+ default_location = default_location.Append( |
+ L"Local Settings\\Application Data"); |
+ } else { |
+ default_location = default_location.Append(L"AppData\\Local"); |
+ } |
+ locations.push_back(default_location.Append(app_from_google)); |
+ } |
+ |
+ // Add the system-level location for Chrome. |
+ std::string program_dir; |
+ if (env->GetVar("ProgramFiles", &program_dir)) { |
+ locations.push_back(FilePath(UTF8ToWide(program_dir)) |
+ .Append(app_from_google)); |
+ } |
+ if (env->GetVar("ProgramFiles(x86)", &program_dir)) { |
+ locations.push_back(FilePath(UTF8ToWide(program_dir)) |
+ .Append(app_from_google)); |
+ } |
+#elif defined(OS_MACOSX) |
+ locations.push_back(FilePath("/Applications")); |
+#elif defined(OS_LINUX) |
+ // Proxy launcher doesn't check for google-chrome, only chrome. |
+ FilePath chrome_sym_link("/usr/bin/google-chrome"); |
+ if (file_util::PathExists(chrome_sym_link)) { |
+ FilePath chrome; |
+ if (file_util::ReadSymbolicLink(chrome_sym_link, &chrome)) { |
+ locations.push_back(chrome.DirName()); |
+ } |
+ } |
+#endif |
+ |
+ // Add the current directory. |
+ FilePath current_dir; |
+ if (file_util::GetCurrentDirectory(¤t_dir)) |
+ locations.push_back(current_dir); |
+ |
+ // Determine the default directory. |
+ for (size_t i = 0; i < locations.size(); ++i) { |
+ FilePath path = locations[i].Append(chrome::kBrowserProcessExecutablePath); |
+ if (file_util::PathExists(path)) { |
+ *browser_exe = path; |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+} // namespace |
+ |
+namespace webdriver { |
+ |
+Automation::Automation() {} |
+ |
+Automation::~Automation() {} |
+ |
+void Automation::Init(const CommandLine& options, |
+ Error** error) { |
+ FilePath browser_exe; |
+ if (!GetDefaultChromeExe(&browser_exe)) { |
+ *error = new Error(kUnknownError, "Could not find default Chrome binary"); |
+ return; |
+ } |
+ |
+ InitWithBrowserPath(browser_exe, options, error); |
+} |
+ |
+void Automation::InitWithBrowserPath(const FilePath& browser_exe, |
+ const CommandLine& options, |
+ Error** error) { |
+ if (!file_util::PathExists(browser_exe)) { |
+ std::string message = base::StringPrintf( |
+ "Could not find Chrome binary at: %" PRFilePath, |
+ browser_exe.value().c_str()); |
+ *error = new Error(kUnknownError, message); |
+ return; |
+ } |
+ |
+ CommandLine command(browser_exe); |
+ command.AppendSwitch(switches::kDisableHangMonitor); |
+ command.AppendSwitch(switches::kDisablePromptOnRepost); |
+ command.AppendSwitch(switches::kDomAutomationController); |
+ command.AppendSwitch(switches::kFullMemoryCrashReport); |
+ command.AppendSwitchASCII(switches::kHomePage, chrome::kAboutBlankURL); |
+ command.AppendSwitch(switches::kNoDefaultBrowserCheck); |
+ command.AppendSwitch(switches::kNoFirstRun); |
+ command.AppendSwitchASCII(switches::kTestType, "webdriver"); |
+ |
+ command.AppendArguments(options, false); |
+ |
+ launcher_.reset(new AnonymousProxyLauncher(false)); |
+ ProxyLauncher::LaunchState launch_props = { |
+ false, // clear_profile |
+ FilePath(), // template_user_data |
+ ProxyLauncher::DEFAULT_THEME, |
+ command, |
+ true, // include_testing_id |
+ true // show_window |
+ }; |
+ |
+ std::string chrome_details = base::StringPrintf( |
+ "Using Chrome binary at: %" PRFilePath, |
+ browser_exe.value().c_str()); |
+ LOG(INFO) << chrome_details; |
+ |
+ if (!launcher_->LaunchBrowserAndServer(launch_props, true)) { |
+ *error = new Error( |
+ kUnknownError, |
+ "Unable to either launch or connect to Chrome. Please check that " |
+ "ChromeDriver is up-to-date. " + chrome_details); |
+ return; |
+ } |
+ |
+ launcher_->automation()->set_action_timeout_ms(base::kNoTimeout); |
+ LOG(INFO) << "Chrome launched successfully. Version: " |
+ << automation()->server_version(); |
+ |
+ bool has_automation_version = false; |
+ *error = CompareVersion(730, 0, &has_automation_version); |
+ if (*error) |
+ return; |
+ |
+ chrome_details += ", version (" + automation()->server_version() + ")"; |
+ if (has_automation_version) { |
+ int version = 0; |
+ std::string error_msg; |
+ if (!SendGetChromeDriverAutomationVersion( |
+ automation(), &version, &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg + " " + chrome_details); |
+ return; |
+ } |
+ if (version > automation::kChromeDriverAutomationVersion) { |
+ *error = new Error( |
+ kUnknownError, |
+ "ChromeDriver is not compatible with this version of Chrome. " + |
+ chrome_details); |
+ return; |
+ } |
+ } |
+} |
+ |
+void Automation::Terminate() { |
+ if (launcher_.get() && launcher_->process() != base::kNullProcessHandle) { |
+ launcher_->QuitBrowser(); |
+ } |
+} |
+ |
+void Automation::ExecuteScript(int tab_id, |
+ const FramePath& frame_path, |
+ const std::string& script, |
+ std::string* result, |
+ Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *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, &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ return; |
+ } |
+ scoped_ptr<Value> value(unscoped_value); |
+ if (!value->GetAsString(result)) |
+ *error = new Error(kUnknownError, "Execute script did not return string"); |
+} |
+ |
+void Automation::MouseMove(int tab_id, |
+ const gfx::Point& p, |
+ Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendMouseMoveJSONRequest( |
+ automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::MouseClick(int tab_id, |
+ const gfx::Point& p, |
+ automation::MouseButton button, |
+ Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendMouseClickJSONRequest( |
+ automation(), windex, tab_index, button, p.x(), p.y(), &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::MouseDrag(int tab_id, |
+ const gfx::Point& start, |
+ const gfx::Point& end, |
+ Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendMouseDragJSONRequest(automation(), windex, tab_index, start.x(), |
+ start.y(), end.x(), end.y(), &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::MouseButtonUp(int tab_id, |
+ const gfx::Point& p, |
+ Error** error) { |
+ *error = CheckAdvancedInteractionsSupported(); |
+ if (*error) |
+ return; |
+ |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendMouseButtonUpJSONRequest( |
+ automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::MouseButtonDown(int tab_id, |
+ const gfx::Point& p, |
+ Error** error) { |
+ *error = CheckAdvancedInteractionsSupported(); |
+ if (*error) |
+ return; |
+ |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendMouseButtonDownJSONRequest( |
+ automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::MouseDoubleClick(int tab_id, |
+ const gfx::Point& p, |
+ Error** error) { |
+ *error = CheckAdvancedInteractionsSupported(); |
+ if (*error) |
+ return; |
+ |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendMouseDoubleClickJSONRequest( |
+ automation(), windex, tab_index, p.x(), p.y(), &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::SendWebKeyEvent(int tab_id, |
+ const WebKeyEvent& key_event, |
+ Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *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 = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::SendNativeKeyEvent(int tab_id, |
+ ui::KeyboardCode key_code, |
+ int modifiers, |
+ Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *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 = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::CaptureEntirePageAsPNG(int tab_id, |
+ const FilePath& path, |
+ Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendCaptureEntirePageJSONRequest( |
+ automation(), windex, tab_index, path, &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::NavigateToURL(int tab_id, |
+ const std::string& url, |
+ Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ AutomationMsg_NavigationResponseValues navigate_response; |
+ std::string error_msg; |
+ if (!SendNavigateToURLJSONRequest(automation(), windex, tab_index, |
+ GURL(url), 1, &navigate_response, |
+ &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ return; |
+ } |
+ // 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, Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendGoForwardJSONRequest( |
+ automation(), windex, tab_index, &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::GoBack(int tab_id, Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendGoBackJSONRequest(automation(), windex, tab_index, &error_msg)) |
+ *error = new Error(kUnknownError, error_msg); |
+} |
+ |
+void Automation::Reload(int tab_id, Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendReloadJSONRequest(automation(), windex, tab_index, &error_msg)) |
+ *error = new Error(kUnknownError, error_msg); |
+} |
+ |
+void Automation::GetCookies(const std::string& url, |
+ ListValue** cookies, |
+ Error** error) { |
+ std::string error_msg; |
+ if (!SendGetCookiesJSONRequest(automation(), url, cookies, &error_msg)) |
+ *error = new Error(kUnknownError, error_msg); |
+} |
+ |
+void Automation::GetCookiesDeprecated(int tab_id, |
+ const GURL& gurl, |
+ std::string* cookies, |
+ bool* success) { |
+ int windex = 0, tab_index = 0; |
+ scoped_ptr<Error> error(GetIndicesForTab(tab_id, &windex, &tab_index)); |
+ if (error.get()) { |
+ *success = false; |
+ return; |
+ } |
+ |
+ *success = SendGetCookiesJSONRequestDeprecated( |
+ automation(), windex, gurl.possibly_invalid_spec(), cookies); |
+} |
+ |
+void Automation::DeleteCookie(const std::string& url, |
+ const std::string& cookie_name, |
+ Error** error) { |
+ std::string error_msg; |
+ if (!SendDeleteCookieJSONRequest( |
+ automation(), url, cookie_name, &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::DeleteCookieDeprecated(int tab_id, |
+ const GURL& gurl, |
+ const std::string& cookie_name, |
+ bool* success) { |
+ int windex = 0, tab_index = 0; |
+ scoped_ptr<Error> error(GetIndicesForTab(tab_id, &windex, &tab_index)); |
+ if (error.get()) { |
+ *success = false; |
+ return; |
+ } |
+ |
+ *success = SendDeleteCookieJSONRequestDeprecated( |
+ automation(), |
+ windex, |
+ gurl.possibly_invalid_spec(), |
+ cookie_name); |
+} |
+ |
+void Automation::SetCookie(const std::string& url, |
+ DictionaryValue* cookie_dict, |
+ Error** error) { |
+ std::string error_msg; |
+ if (!SendSetCookieJSONRequest(automation(), url, cookie_dict, &error_msg)) |
+ *error = new Error(kUnknownError, error_msg); |
+} |
+ |
+void Automation::SetCookieDeprecated(int tab_id, |
+ const GURL& gurl, |
+ const std::string& cookie, |
+ bool* success) { |
+ int windex = 0, tab_index = 0; |
+ scoped_ptr<Error> error(GetIndicesForTab(tab_id, &windex, &tab_index)); |
+ if (error.get()) { |
+ *success = false; |
+ return; |
+ } |
+ |
+ *success = SendSetCookieJSONRequestDeprecated( |
+ automation(), |
+ windex, |
+ gurl.possibly_invalid_spec(), |
+ cookie); |
+} |
+ |
+void Automation::GetTabIds(std::vector<int>* tab_ids, |
+ Error** error) { |
+ std::string error_msg; |
+ if (!SendGetTabIdsJSONRequest(automation(), tab_ids, &error_msg)) |
+ *error = new Error(kUnknownError, error_msg); |
+} |
+ |
+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 = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::CloseTab(int tab_id, Error** error) { |
+ int windex = 0, tab_index = 0; |
+ *error = GetIndicesForTab(tab_id, &windex, &tab_index); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendCloseTabJSONRequest(automation(), windex, tab_index, &error_msg)) |
+ *error = new Error(kUnknownError, error_msg); |
+} |
+ |
+void Automation::GetAppModalDialogMessage(std::string* message, Error** error) { |
+ *error = CheckAlertsSupported(); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendGetAppModalDialogMessageJSONRequest( |
+ automation(), message, &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::AcceptOrDismissAppModalDialog(bool accept, Error** error) { |
+ *error = CheckAlertsSupported(); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendAcceptOrDismissAppModalDialogJSONRequest( |
+ automation(), accept, &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::AcceptPromptAppModalDialog(const std::string& prompt_text, |
+ Error** error) { |
+ *error = CheckAlertsSupported(); |
+ if (*error) |
+ return; |
+ |
+ std::string error_msg; |
+ if (!SendAcceptPromptAppModalDialogJSONRequest( |
+ automation(), prompt_text, &error_msg)) { |
+ *error = new Error(kUnknownError, error_msg); |
+ } |
+} |
+ |
+void Automation::GetBrowserVersion(std::string* version) { |
+ *version = automation()->server_version(); |
+} |
+ |
+void Automation::GetChromeDriverAutomationVersion(int* version, Error** error) { |
+ std::string error_msg; |
+ if (!SendGetChromeDriverAutomationVersion(automation(), version, &error_msg)) |
+ *error = new Error(kUnknownError, error_msg); |
+} |
+ |
+void Automation::WaitForAllTabsToStopLoading(Error** error) { |
+ std::string error_msg; |
+ if (!SendWaitForAllTabsToStopLoadingJSONRequest(automation(), &error_msg)) |
+ *error = new Error(kUnknownError, error_msg); |
+} |
+ |
+AutomationProxy* Automation::automation() const { |
+ return launcher_->automation(); |
+} |
+ |
+Error* Automation::GetIndicesForTab( |
+ int tab_id, int* browser_index, int* tab_index) { |
+ std::string error_msg; |
+ if (!SendGetIndicesFromTabIdJSONRequest( |
+ automation(), tab_id, browser_index, tab_index, &error_msg)) { |
+ return new Error(kUnknownError, error_msg); |
+ } |
+ return NULL; |
+} |
+ |
+Error* Automation::CompareVersion(int client_build_no, |
+ int client_patch_no, |
+ bool* is_newer_or_equal) { |
+ std::string version = automation()->server_version(); |
+ std::vector<std::string> split_version; |
+ base::SplitString(version, '.', &split_version); |
+ 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 new Error( |
+ kUnknownError, "Browser version has unrecognized format: " + version); |
+ } |
+ if (build_no < client_build_no) |
+ *is_newer_or_equal = false; |
+ else if (build_no > client_build_no) |
+ *is_newer_or_equal = true; |
+ else |
+ *is_newer_or_equal = patch_no >= client_patch_no; |
+ return NULL; |
+} |
+ |
+Error* Automation::CheckVersion(int client_build_no, |
+ int client_patch_no, |
+ const std::string& error_msg) { |
+ bool version_is_ok = false; |
+ Error* error = CompareVersion( |
+ client_build_no, client_patch_no, &version_is_ok); |
+ if (error) |
+ return error; |
+ if (!version_is_ok) |
+ return new Error(kUnknownError, error_msg); |
+ return NULL; |
+} |
+ |
+Error* Automation::CheckAlertsSupported() { |
+ return CheckVersion( |
+ 768, 0, "Alerts are not supported for this version of Chrome"); |
+} |
+ |
+Error* Automation::CheckAdvancedInteractionsSupported() { |
+ const char* message = |
+ "Advanced user interactions are not supported for this version of Chrome"; |
+ return CheckVersion(750, 0, message); |
+} |
+ |
+} // namespace webdriver |