From 69f21bface7145ec9db86cc3e1a109134dc37202 Mon Sep 17 00:00:00 2001 From: "kkania@chromium.org" Date: Fri, 27 Apr 2012 01:20:24 +0000 Subject: Geolocation support for chromedriver, client side. BUG=chromedriver:14 TEST=none Review URL: http://codereview.chromium.org/10167014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134200 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/chrome_tests.gypi | 2 + chrome/test/automation/automation_json_requests.cc | 10 +++++ chrome/test/automation/automation_json_requests.h | 6 +++ .../webdriver/commands/html5_location_commands.cc | 47 ++++++++++++++++++++++ .../webdriver/commands/html5_location_commands.h | 42 +++++++++++++++++++ chrome/test/webdriver/test/chromedriver_tests.py | 32 +++++++++++++++ chrome/test/webdriver/webdriver_automation.cc | 36 +++++++++++++++++ chrome/test/webdriver/webdriver_automation.h | 10 +++++ chrome/test/webdriver/webdriver_server.cc | 2 + chrome/test/webdriver/webdriver_session.cc | 20 +++++++++ chrome/test/webdriver/webdriver_session.h | 6 +++ 11 files changed, 213 insertions(+) create mode 100644 chrome/test/webdriver/commands/html5_location_commands.cc create mode 100644 chrome/test/webdriver/commands/html5_location_commands.h diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 08b4cea..f155fc6 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -859,6 +859,8 @@ 'test/webdriver/commands/file_upload_command.h', 'test/webdriver/commands/find_element_commands.cc', 'test/webdriver/commands/find_element_commands.h', + 'test/webdriver/commands/html5_location_commands.cc', + 'test/webdriver/commands/html5_location_commands.h', 'test/webdriver/commands/html5_storage_commands.cc', 'test/webdriver/commands/html5_storage_commands.h', 'test/webdriver/commands/keys_command.cc', diff --git a/chrome/test/automation/automation_json_requests.cc b/chrome/test/automation/automation_json_requests.cc index 11fc25a..059c11e 100644 --- a/chrome/test/automation/automation_json_requests.cc +++ b/chrome/test/automation/automation_json_requests.cc @@ -901,3 +901,13 @@ bool SendSetPreferenceJSONRequest( DictionaryValue reply_dict; return SendAutomationJSONRequest(sender, dict, &reply_dict, error); } + +bool SendOverrideGeolocationJSONRequest( + AutomationMessageSender* sender, + base::DictionaryValue* geolocation, + Error* error) { + scoped_ptr dict(geolocation->DeepCopy()); + dict->SetString("command", "OverrideGeoposition"); + DictionaryValue reply_dict; + return SendAutomationJSONRequest(sender, *dict.get(), &reply_dict, error); +} diff --git a/chrome/test/automation/automation_json_requests.h b/chrome/test/automation/automation_json_requests.h index 1f71ccb..5fc2c14 100644 --- a/chrome/test/automation/automation_json_requests.h +++ b/chrome/test/automation/automation_json_requests.h @@ -510,4 +510,10 @@ bool SendSetPreferenceJSONRequest( base::Value* value, automation::Error* error) WARN_UNUSED_RESULT; +// Requests to override the user's geolocation. Returns true on success. +bool SendOverrideGeolocationJSONRequest( + AutomationMessageSender* sender, + base::DictionaryValue* geolocation, + automation::Error* error) WARN_UNUSED_RESULT; + #endif // CHROME_TEST_AUTOMATION_AUTOMATION_JSON_REQUESTS_H_ diff --git a/chrome/test/webdriver/commands/html5_location_commands.cc b/chrome/test/webdriver/commands/html5_location_commands.cc new file mode 100644 index 0000000..d2466d7 --- /dev/null +++ b/chrome/test/webdriver/commands/html5_location_commands.cc @@ -0,0 +1,47 @@ +// Copyright (c) 2012 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/html5_location_commands.h" + +#include "base/values.h" +#include "chrome/test/webdriver/commands/response.h" +#include "chrome/test/webdriver/webdriver_error.h" +#include "chrome/test/webdriver/webdriver_session.h" + +namespace webdriver { + +HTML5LocationCommand::HTML5LocationCommand( + const std::vector& path_segments, + const base::DictionaryValue* const parameters) + : WebDriverCommand(path_segments, parameters) {} + +HTML5LocationCommand::~HTML5LocationCommand() {} + +bool HTML5LocationCommand::DoesGet() { + return true; +} + +bool HTML5LocationCommand::DoesPost() { + return true; +} + +void HTML5LocationCommand::ExecuteGet(Response* const response) { + scoped_ptr geolocation; + Error* error = session_->GetGeolocation(&geolocation); + if (error) { + response->SetError(error); + return; + } + response->SetValue(geolocation.release()); +} + +void HTML5LocationCommand::ExecutePost(Response* const response) { + base::DictionaryValue geolocation; + geolocation.MergeDictionary(parameters_.get()); + Error* error = session_->OverrideGeolocation(&geolocation); + if (error) + response->SetError(error); +} + +} // namespace webdriver diff --git a/chrome/test/webdriver/commands/html5_location_commands.h b/chrome/test/webdriver/commands/html5_location_commands.h new file mode 100644 index 0000000..b927876 --- /dev/null +++ b/chrome/test/webdriver/commands/html5_location_commands.h @@ -0,0 +1,42 @@ +// Copyright (c) 2012 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_HTML5_LOCATION_COMMANDS_H_ +#define CHROME_TEST_WEBDRIVER_COMMANDS_HTML5_LOCATION_COMMANDS_H_ + +#include +#include + +#include "chrome/test/webdriver/commands/webdriver_command.h" + +namespace base { +class DictionaryValue; +} + +namespace webdriver { + +class Response; + +class HTML5LocationCommand : public WebDriverCommand { + public: + HTML5LocationCommand(const std::vector& path_segments, + const base::DictionaryValue* const parameters); + virtual ~HTML5LocationCommand(); + + virtual bool DoesGet() OVERRIDE; + virtual bool DoesPost() OVERRIDE; + + // Returns the current geolocation. + virtual void ExecuteGet(Response* const response) OVERRIDE; + + // Sets the current geolocation. + virtual void ExecutePost(Response* const response) OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(HTML5LocationCommand); +}; + +} // namespace webdriver + +#endif // CHROME_TEST_WEBDRIVER_COMMANDS_HTML5_LOCATION_COMMANDS_H_ diff --git a/chrome/test/webdriver/test/chromedriver_tests.py b/chrome/test/webdriver/test/chromedriver_tests.py index 7a39062..fb030ab 100644 --- a/chrome/test/webdriver/test/chromedriver_tests.py +++ b/chrome/test/webdriver/test/chromedriver_tests.py @@ -1037,6 +1037,38 @@ class WindowTest(ChromeDriverTest): self.assertRaises(NoSuchWindowException, getPosition, invalid_handle) +class GeolocationTest(ChromeDriverTest): + """Tests for WebDriver geolocation commands.""" + + def testGeolocation(self): + """Tests the get and set geolocation commands.""" + driver = self.GetNewDriver() + + # TODO(kkania): Update the python bindings and get rid of these. + driver.command_executor._commands.update({ + 'getLoc': ('GET', '/session/$sessionId/location'), + 'setLoc': ('POST', '/session/$sessionId/location') + }) + def getLocation(): + return driver.execute('getLoc')['value'] + def setLocation(location): + driver.execute('setLoc', location) + expected_location = {'latitude': 50, 'longitude': 50, 'altitude': 300} + setLocation(expected_location) + location = getLocation() + self.assertEquals(expected_location, location) + + driver.set_script_timeout(10) + result = driver.execute_async_script(""" + var callback = arguments[0]; + window.navigator.geolocation.getCurrentPosition( + function success(result) { callback(result.coords); }, + function fail(error) { callback(error.message); });""") + self.assertEquals(expected_location['latitude'], result['latitude']) + self.assertEquals(expected_location['longitude'], result['longitude']) + self.assertEquals(expected_location['altitude'], result['altitude']) + + class ExtensionTest(ChromeDriverTest): INFOBAR_BROWSER_ACTION_EXTENSION = test_paths.TEST_DATA_PATH + \ diff --git a/chrome/test/webdriver/webdriver_automation.cc b/chrome/test/webdriver/webdriver_automation.cc index 95e9cad..05addd1 100644 --- a/chrome/test/webdriver/webdriver_automation.cc +++ b/chrome/test/webdriver/webdriver_automation.cc @@ -908,6 +908,35 @@ void Automation::SetPreference(const std::string& pref, } } +void Automation::GetGeolocation(scoped_ptr* geolocation, + Error** error) { + *error = CheckGeolocationSupported(); + if (*error) + return; + + if (geolocation_.get()) { + geolocation->reset(geolocation_->DeepCopy()); + } else { + *error = new Error(kUnknownError, + "Location must be set before it can be retrieved"); + } +} + +void Automation::OverrideGeolocation(DictionaryValue* geolocation, + Error** error) { + *error = CheckGeolocationSupported(); + if (*error) + return; + + automation::Error auto_error; + if (SendOverrideGeolocationJSONRequest( + automation(), geolocation, &auto_error)) { + geolocation_.reset(geolocation->DeepCopy()); + } else { + *error = Error::FromAutomationError(auto_error); + } +} + AutomationProxy* Automation::automation() const { return launcher_->automation(); } @@ -967,4 +996,11 @@ Error* Automation::CheckNewExtensionInterfaceSupported() { return CheckVersion(947, message); } +Error* Automation::CheckGeolocationSupported() { + const char* message = + "Geolocation automation interface is not supported for this version of " + "Chrome."; + return CheckVersion(1119, message); +} + } // namespace webdriver diff --git a/chrome/test/webdriver/webdriver_automation.h b/chrome/test/webdriver/webdriver_automation.h index 44332f2..312ef14 100644 --- a/chrome/test/webdriver/webdriver_automation.h +++ b/chrome/test/webdriver/webdriver_automation.h @@ -237,6 +237,14 @@ class Automation { base::Value* value, Error** error); + // Gets the current geolocation. + void GetGeolocation(scoped_ptr* geolocation, + Error** error); + + // Overrides the current geolocation. + void OverrideGeolocation(base::DictionaryValue* geolocation, + Error** error); + private: AutomationProxy* automation() const; Error* ConvertViewIdToLocator(const WebViewId& view_id, @@ -247,11 +255,13 @@ class Automation { Error* CheckAlertsSupported(); Error* CheckAdvancedInteractionsSupported(); Error* CheckNewExtensionInterfaceSupported(); + Error* CheckGeolocationSupported(); Error* IsNewMouseApiSupported(bool* supports_new_api); const Logger& logger_; scoped_ptr launcher_; int build_no_; + scoped_ptr geolocation_; DISALLOW_COPY_AND_ASSIGN(Automation); }; diff --git a/chrome/test/webdriver/webdriver_server.cc b/chrome/test/webdriver/webdriver_server.cc index 888038c..b8438aa 100644 --- a/chrome/test/webdriver/webdriver_server.cc +++ b/chrome/test/webdriver/webdriver_server.cc @@ -41,6 +41,7 @@ #include "chrome/test/webdriver/commands/execute_command.h" #include "chrome/test/webdriver/commands/file_upload_command.h" #include "chrome/test/webdriver/commands/find_element_commands.h" +#include "chrome/test/webdriver/commands/html5_location_commands.h" #include "chrome/test/webdriver/commands/html5_storage_commands.h" #include "chrome/test/webdriver/commands/keys_command.h" #include "chrome/test/webdriver/commands/log_command.h" @@ -164,6 +165,7 @@ void InitCallbacks(Dispatcher* dispatcher, dispatcher->Add("/session/*/chrome/views"); // HTML5 functions. + dispatcher->Add("/session/*/location"); dispatcher->Add("/session/*/local_storage"); dispatcher->Add("/session/*/local_storage/size"); dispatcher->Add("/session/*/local_storage/key*"); diff --git a/chrome/test/webdriver/webdriver_session.cc b/chrome/test/webdriver/webdriver_session.cc index 171e47f..cfa3281 100644 --- a/chrome/test/webdriver/webdriver_session.cc +++ b/chrome/test/webdriver/webdriver_session.cc @@ -1363,6 +1363,26 @@ Error* Session::RemoveStorageItem(StorageType type, CreateDirectValueParser(value)); } +Error* Session::GetGeolocation(scoped_ptr* geolocation) { + Error* error = NULL; + RunSessionTask(base::Bind( + &Automation::GetGeolocation, + base::Unretained(automation_.get()), + geolocation, + &error)); + return error; +} + +Error* Session::OverrideGeolocation(base::DictionaryValue* geolocation) { + Error* error = NULL; + RunSessionTask(base::Bind( + &Automation::OverrideGeolocation, + base::Unretained(automation_.get()), + geolocation, + &error)); + return error; +} + const std::string& Session::id() const { return id_; } diff --git a/chrome/test/webdriver/webdriver_session.h b/chrome/test/webdriver/webdriver_session.h index 30c5cd3..ff53cca 100644 --- a/chrome/test/webdriver/webdriver_session.h +++ b/chrome/test/webdriver/webdriver_session.h @@ -367,6 +367,12 @@ class Session { // no errors, the function sets |value| and the caller takes ownership. Error* GetStorageKeys(StorageType type, base::ListValue** keys); + // Gets the current geolocation. + Error* GetGeolocation(scoped_ptr* geolocation); + + // Overrides the current geolocation. + Error* OverrideGeolocation(base::DictionaryValue* geolocation); + const std::string& id() const; const FrameId& current_target() const; -- cgit v1.1