summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-28 02:12:42 +0000
committerkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-28 02:12:42 +0000
commit2f2186cf42eac670305acf001a41d5780440b932 (patch)
treecb1794b571c42290e84d16747d6dd9b97f780759
parentb3e21e72aade511ae617f668891b2294d2bff20e (diff)
downloadchromium_src-2f2186cf42eac670305acf001a41d5780440b932.zip
chromium_src-2f2186cf42eac670305acf001a41d5780440b932.tar.gz
chromium_src-2f2186cf42eac670305acf001a41d5780440b932.tar.bz2
Implement the webdriver window sizing commands.
BUG=107630 TEST=none Review URL: http://codereview.chromium.org/9288051 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@119555 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/automation/automation_provider_json.cc8
-rw-r--r--chrome/browser/automation/automation_provider_json.h7
-rw-r--r--chrome/browser/automation/testing_automation_provider.cc28
-rw-r--r--chrome/browser/automation/testing_automation_provider.h15
-rw-r--r--chrome/chrome_tests.gypi2
-rw-r--r--chrome/common/automation_constants.cc4
-rw-r--r--chrome/common/automation_constants.h2
-rw-r--r--chrome/test/automation/automation_json_requests.cc20
-rw-r--r--chrome/test/automation/automation_json_requests.h10
-rw-r--r--chrome/test/webdriver/commands/chrome_commands.cc4
-rw-r--r--chrome/test/webdriver/commands/window_commands.cc161
-rw-r--r--chrome/test/webdriver/commands/window_commands.h53
-rw-r--r--chrome/test/webdriver/test/chromedriver_tests.py62
-rw-r--r--chrome/test/webdriver/webdriver_automation.cc10
-rw-r--r--chrome/test/webdriver/webdriver_automation.h7
-rw-r--r--chrome/test/webdriver/webdriver_error.cc4
-rw-r--r--chrome/test/webdriver/webdriver_server.cc4
-rw-r--r--chrome/test/webdriver/webdriver_session.cc31
-rw-r--r--chrome/test/webdriver/webdriver_session.h6
-rw-r--r--chrome/test/webdriver/webdriver_util.cc39
-rw-r--r--chrome/test/webdriver/webdriver_util.h5
21 files changed, 453 insertions, 29 deletions
diff --git a/chrome/browser/automation/automation_provider_json.cc b/chrome/browser/automation/automation_provider_json.cc
index 1c1e3bd..c43ad04 100644
--- a/chrome/browser/automation/automation_provider_json.cc
+++ b/chrome/browser/automation/automation_provider_json.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -42,14 +42,14 @@ void AutomationJSONReply::SendSuccess(const Value* value) {
}
void AutomationJSONReply::SendError(const std::string& error_message) {
- SendErrorInternal(Error(error_message));
+ SendError(Error(error_message));
}
void AutomationJSONReply::SendErrorCode(ErrorCode code) {
- SendErrorInternal(Error(code));
+ SendError(Error(code));
}
-void AutomationJSONReply::SendErrorInternal(const Error& error) {
+void AutomationJSONReply::SendError(const Error& error) {
DCHECK(message_) << "Resending reply for JSON automation request";
base::DictionaryValue dict;
diff --git a/chrome/browser/automation/automation_provider_json.h b/chrome/browser/automation/automation_provider_json.h
index 9ca6e906..10e9077 100644
--- a/chrome/browser/automation/automation_provider_json.h
+++ b/chrome/browser/automation/automation_provider_json.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -55,9 +55,10 @@ class AutomationJSONReply {
// associated error message.
void SendErrorCode(automation::ErrorCode code);
- private:
- void SendErrorInternal(const automation::Error& error);
+ // Send an automation error.
+ void SendError(const automation::Error& error);
+ private:
AutomationProvider* provider_;
IPC::Message* message_;
};
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index ed0f89b..d883808 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -120,6 +120,7 @@
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/renderer_host/render_widget_host_view.h"
#include "content/browser/tab_contents/interstitial_page.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/child_process_data.h"
@@ -2354,6 +2355,8 @@ void TestingAutomationProvider::SendJSONRequest(int handle,
&TestingAutomationProvider::DoesAutomationObjectExist;
handler_map["CloseTab"] =
&TestingAutomationProvider::CloseTabJSON;
+ handler_map["SetViewBounds"] =
+ &TestingAutomationProvider::SetViewBounds;
handler_map["WebkitMouseMove"] =
&TestingAutomationProvider::WebkitMouseMove;
handler_map["WebkitMouseClick"] =
@@ -6308,7 +6311,8 @@ void TestingAutomationProvider::ExecuteJavascriptJSON(
std::string error;
RenderViewHost* render_view;
if (!GetRenderViewFromJSONArgs(args, profile(), &render_view, &error)) {
- AutomationJSONReply(this, reply_message).SendError(error);
+ AutomationJSONReply(this, reply_message).SendError(
+ Error(automation::kInvalidId, error));
return;
}
if (!args->GetString("frame_xpath", &frame_xpath)) {
@@ -6598,6 +6602,28 @@ void TestingAutomationProvider::CloseTabJSON(
reply.SendSuccess(NULL);
}
+void TestingAutomationProvider::SetViewBounds(
+ base::DictionaryValue* args,
+ IPC::Message* reply_message) {
+ AutomationJSONReply reply(this, reply_message);
+ int x, y, width, height;
+ if (!args->GetInteger("bounds.x", &x) ||
+ !args->GetInteger("bounds.y", &y) ||
+ !args->GetInteger("bounds.width", &width) ||
+ !args->GetInteger("bounds.height", &height)) {
+ reply.SendError("Missing or invalid 'bounds'");
+ return;
+ }
+ Browser* browser;
+ std::string error;
+ if (!GetBrowserFromJSONArgs(args, &browser, &error)) {
+ reply.SendError(Error(automation::kInvalidId, error));
+ return;
+ }
+ browser->window()->SetBounds(gfx::Rect(x, y, width, height));
+ reply.SendSuccess(NULL);
+}
+
void TestingAutomationProvider::ActivateTabJSON(
DictionaryValue* args,
IPC::Message* reply_message) {
diff --git a/chrome/browser/automation/testing_automation_provider.h b/chrome/browser/automation/testing_automation_provider.h
index e6f9092..1b712e8 100644
--- a/chrome/browser/automation/testing_automation_provider.h
+++ b/chrome/browser/automation/testing_automation_provider.h
@@ -1096,6 +1096,21 @@ class TestingAutomationProvider : public AutomationProvider,
// output: none
void CloseTabJSON(base::DictionaryValue* args, IPC::Message* reply_message);
+ // Sets the specified web view bounds.
+ // The single |auto_id| must be given to specify the view.
+ // This method currently is only supported for tabs.
+ // Example:
+ // input: { "auto_id": { "type": 0, "id": "awoein" },
+ // "bounds": {
+ // "x": 100,
+ // "y": 200,
+ // "width": 500,
+ // "height": 800
+ // }
+ // }
+ // output: none
+ void SetViewBounds(base::DictionaryValue* args, IPC::Message* reply_message);
+
// Sends the WebKit events for a mouse click at a given coordinate.
// The pair |windex| and |tab_index| or the single |auto_id| must be given
// to specify the render view.
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 8cb9734..756e9ea 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1024,6 +1024,8 @@
'test/webdriver/commands/webdriver_command.h',
'test/webdriver/commands/webelement_commands.cc',
'test/webdriver/commands/webelement_commands.h',
+ 'test/webdriver/commands/window_commands.cc',
+ 'test/webdriver/commands/window_commands.h',
'test/webdriver/frame_path.cc',
'test/webdriver/frame_path.h',
'test/webdriver/http_response.cc',
diff --git a/chrome/common/automation_constants.cc b/chrome/common/automation_constants.cc
index 0fbb0de..1b8d32d 100644
--- a/chrome/common/automation_constants.cc
+++ b/chrome/common/automation_constants.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -32,6 +32,8 @@ const char* DefaultMessageForErrorCode(ErrorCode code) {
return "No JavaScript modal dialog is open";
case kBlockedByModalDialog:
return "Command blocked by an open modal dialog";
+ case kInvalidId:
+ return "ID is invalid or does not refer to an existing object";
default:
return "<unknown>";
}
diff --git a/chrome/common/automation_constants.h b/chrome/common/automation_constants.h
index ffb5754..bd4ec01 100644
--- a/chrome/common/automation_constants.h
+++ b/chrome/common/automation_constants.h
@@ -85,6 +85,8 @@ enum ErrorCode {
// An open modal dialog blocked the operation. The operation may have
// partially completed.
kBlockedByModalDialog = 2,
+ // An ID was supplied that is invalid or does not refer to an existing object.
+ kInvalidId = 3,
};
// Represents an automation error. Each error has a code and an error message.
diff --git a/chrome/test/automation/automation_json_requests.cc b/chrome/test/automation/automation_json_requests.cc
index a9e349c..af122f6 100644
--- a/chrome/test/automation/automation_json_requests.cc
+++ b/chrome/test/automation/automation_json_requests.cc
@@ -674,6 +674,26 @@ bool SendDragAndDropFilePathsJSONRequest(
return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
}
+bool SendSetViewBoundsJSONRequest(
+ AutomationMessageSender* sender,
+ const WebViewId& id,
+ int x,
+ int y,
+ int width,
+ int height,
+ automation::Error* error) {
+ DictionaryValue dict;
+ dict.SetString("command", "SetViewBounds");
+ id.UpdateDictionary(&dict, "auto_id");
+ dict.SetInteger("bounds.x", x);
+ dict.SetInteger("bounds.y", y);
+ dict.SetInteger("bounds.width", width);
+ dict.SetInteger("bounds.height", height);
+
+ DictionaryValue reply_dict;
+ return SendAutomationJSONRequest(sender, dict, &reply_dict, error);
+}
+
bool SendGetAppModalDialogMessageJSONRequest(
AutomationMessageSender* sender,
std::string* message,
diff --git a/chrome/test/automation/automation_json_requests.h b/chrome/test/automation/automation_json_requests.h
index 5d35400..1f71ccb 100644
--- a/chrome/test/automation/automation_json_requests.h
+++ b/chrome/test/automation/automation_json_requests.h
@@ -404,6 +404,16 @@ bool SendDragAndDropFilePathsJSONRequest(
const std::vector<FilePath::StringType>& paths,
automation::Error* error) WARN_UNUSED_RESULT;
+// Requests to set the given view's bounds. Returns true on success.
+bool SendSetViewBoundsJSONRequest(
+ AutomationMessageSender* sender,
+ const WebViewId& id,
+ int x,
+ int y,
+ int width,
+ int height,
+ automation::Error* error) WARN_UNUSED_RESULT;
+
// Requests to get the active JavaScript modal dialog's message. Returns true
// on success.
bool SendGetAppModalDialogMessageJSONRequest(
diff --git a/chrome/test/webdriver/commands/chrome_commands.cc b/chrome/test/webdriver/commands/chrome_commands.cc
index dca46ae..d12e071 100644
--- a/chrome/test/webdriver/commands/chrome_commands.cc
+++ b/chrome/test/webdriver/commands/chrome_commands.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -246,7 +246,7 @@ void ViewsCommand::ExecuteGet(Response* const response) {
for (size_t i = 0; i < views.size(); ++i) {
DictionaryValue* dict = new DictionaryValue();
AutomationId id = views[i].view_id.GetId();
- dict->SetString("handle", JsonStringify(id.ToValue()));
+ dict->SetString("handle", WebViewIdToString(WebViewId::ForView(id)));
dict->SetInteger("type", id.type());
if (!views[i].extension_id.empty())
dict->SetString("extension_id", views[i].extension_id);
diff --git a/chrome/test/webdriver/commands/window_commands.cc b/chrome/test/webdriver/commands/window_commands.cc
new file mode 100644
index 0000000..e799dd3
--- /dev/null
+++ b/chrome/test/webdriver/commands/window_commands.cc
@@ -0,0 +1,161 @@
+// 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/window_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"
+#include "chrome/test/webdriver/webdriver_util.h"
+
+using base::Value;
+
+namespace webdriver {
+
+namespace {
+
+bool GetWindowId(const std::string& window_id_string,
+ const WebViewId& current_id,
+ WebViewId* window_id,
+ Response* const response) {
+ if (window_id_string == "current") {
+ *window_id = current_id;
+ } else if (!StringToWebViewId(window_id_string, window_id)) {
+ response->SetError(
+ new Error(kBadRequest, "Invalid window ID"));
+ return false;
+ }
+ return true;
+}
+
+}
+
+WindowSizeCommand::WindowSizeCommand(
+ const std::vector<std::string>& path_segments,
+ const base::DictionaryValue* parameters)
+ : WebDriverCommand(path_segments, parameters) {
+}
+
+WindowSizeCommand::~WindowSizeCommand() {
+}
+
+bool WindowSizeCommand::DoesGet() {
+ return true;
+}
+
+bool WindowSizeCommand::DoesPost() {
+ return true;
+}
+
+void WindowSizeCommand::ExecuteGet(Response* const response) {
+ // Path segment: "/session/$sessionId/window/$windowHandle/size"
+ WebViewId window_id;
+ WebViewId current_id = session_->current_target().view_id;
+ if (!GetWindowId(GetPathVariable(4), current_id, &window_id, response))
+ return;
+
+ Rect bounds;
+ Error* error = session_->GetWindowBounds(window_id, &bounds);
+ if (error) {
+ response->SetError(error);
+ return;
+ }
+ base::DictionaryValue* size = new base::DictionaryValue();
+ size->SetInteger("width", bounds.width());
+ size->SetInteger("height", bounds.height());
+ response->SetValue(size);
+}
+
+void WindowSizeCommand::ExecutePost(Response* const response) {
+ // Path segment: "/session/$sessionId/window/$windowHandle/size"
+ WebViewId window_id;
+ WebViewId current_id = session_->current_target().view_id;
+ if (!GetWindowId(GetPathVariable(4), current_id, &window_id, response))
+ return;
+
+ int width, height;
+ if (!GetIntegerParameter("width", &width) ||
+ !GetIntegerParameter("height", &height)) {
+ response->SetError(new Error(
+ kBadRequest,
+ "Missing or invalid 'width' or 'height' parameters"));
+ return;
+ }
+ Rect bounds;
+ Error* error = session_->GetWindowBounds(window_id, &bounds);
+ if (!error) {
+ bounds = Rect(bounds.origin(), Size(width, height));
+ error = session_->SetWindowBounds(window_id, bounds);
+ }
+ if (error) {
+ response->SetError(error);
+ return;
+ }
+}
+
+WindowPositionCommand::WindowPositionCommand(
+ const std::vector<std::string>& path_segments,
+ const base::DictionaryValue* parameters)
+ : WebDriverCommand(path_segments, parameters) {
+}
+
+WindowPositionCommand::~WindowPositionCommand() {
+}
+
+bool WindowPositionCommand::DoesGet() {
+ return true;
+}
+
+bool WindowPositionCommand::DoesPost() {
+ return true;
+}
+
+void WindowPositionCommand::ExecuteGet(Response* const response) {
+ // Path segment: "/session/$sessionId/window/$windowHandle/position"
+ WebViewId window_id;
+ WebViewId current_id = session_->current_target().view_id;
+ if (!GetWindowId(GetPathVariable(4), current_id, &window_id, response))
+ return;
+
+ Rect bounds;
+ Error* error = session_->GetWindowBounds(window_id, &bounds);
+ if (error) {
+ response->SetError(error);
+ return;
+ }
+ base::DictionaryValue* size = new base::DictionaryValue();
+ size->SetInteger("x", bounds.x());
+ size->SetInteger("y", bounds.y());
+ response->SetValue(size);
+}
+
+void WindowPositionCommand::ExecutePost(Response* const response) {
+ // Path segment: "/session/$sessionId/window/$windowHandle/size"
+ WebViewId window_id;
+ WebViewId current_id = session_->current_target().view_id;
+ if (!GetWindowId(GetPathVariable(4), current_id, &window_id, response))
+ return;
+
+ int x, y;
+ if (!GetIntegerParameter("x", &x) ||
+ !GetIntegerParameter("y", &y)) {
+ response->SetError(new Error(
+ kBadRequest,
+ "Missing or invalid 'x' or 'y' parameters"));
+ return;
+ }
+ Rect bounds;
+ Error* error = session_->GetWindowBounds(window_id, &bounds);
+ if (!error) {
+ bounds = Rect(Point(x, y), bounds.size());
+ error = session_->SetWindowBounds(window_id, bounds);
+ }
+ if (error) {
+ response->SetError(error);
+ return;
+ }
+}
+
+} // namespace webdriver
diff --git a/chrome/test/webdriver/commands/window_commands.h b/chrome/test/webdriver/commands/window_commands.h
new file mode 100644
index 0000000..d5df95d
--- /dev/null
+++ b/chrome/test/webdriver/commands/window_commands.h
@@ -0,0 +1,53 @@
+// 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_WINDOW_COMMANDS_H_
+#define CHROME_TEST_WEBDRIVER_COMMANDS_WINDOW_COMMANDS_H_
+
+#include <string>
+#include <vector>
+
+#include "chrome/test/webdriver/commands/webdriver_command.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace webdriver {
+
+class Response;
+
+class WindowSizeCommand : public WebDriverCommand {
+ public:
+ WindowSizeCommand(const std::vector<std::string>& path_segments,
+ const base::DictionaryValue* parameters);
+ virtual ~WindowSizeCommand();
+
+ virtual bool DoesGet() OVERRIDE;
+ virtual bool DoesPost() OVERRIDE;
+ virtual void ExecuteGet(Response* const response) OVERRIDE;
+ virtual void ExecutePost(Response* const response) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WindowSizeCommand);
+};
+
+class WindowPositionCommand : public WebDriverCommand {
+ public:
+ WindowPositionCommand(const std::vector<std::string>& path_segments,
+ const base::DictionaryValue* parameters);
+ virtual ~WindowPositionCommand();
+
+ virtual bool DoesGet() OVERRIDE;
+ virtual bool DoesPost() OVERRIDE;
+ virtual void ExecuteGet(Response* const response) OVERRIDE;
+ virtual void ExecutePost(Response* const response) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WindowPositionCommand);
+};
+
+} // namespace webdriver
+
+#endif // CHROME_TEST_WEBDRIVER_COMMANDS_WINDOW_COMMANDS_H_
diff --git a/chrome/test/webdriver/test/chromedriver_tests.py b/chrome/test/webdriver/test/chromedriver_tests.py
index 1e7d359..7802589 100644
--- a/chrome/test/webdriver/test/chromedriver_tests.py
+++ b/chrome/test/webdriver/test/chromedriver_tests.py
@@ -36,6 +36,7 @@ try:
except ImportError:
import json
+from selenium.common.exceptions import NoSuchWindowException
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
@@ -921,6 +922,7 @@ class FrameSwitchingTest(ChromeDriverTest):
self.assertEquals(str(i), driver.current_url.split('?')[-1])
driver.switch_to_default_content()
+
class AlertTest(ChromeDriverTest):
def testAlertOnLoadDoesNotHang(self):
@@ -982,6 +984,66 @@ class AlertTest(ChromeDriverTest):
driver.execute_async_script('arguments[0](); window.alert("ok")')
driver.switch_to_alert().accept()
+
+class WindowTest(ChromeDriverTest):
+ def testSizeAndPosition(self):
+ driver = self.GetNewDriver()
+
+ # TODO(kkania): Update the python bindings and get rid of these.
+ driver.command_executor._commands.update({
+ 'getSize': ('GET', '/session/$sessionId/window/$windowHandle/size'),
+ 'setSize': ('POST', '/session/$sessionId/window/$windowHandle/size'),
+ 'getPos': ('GET', '/session/$sessionId/window/$windowHandle/position'),
+ 'setPos': ('POST', '/session/$sessionId/window/$windowHandle/position')
+ })
+ def getSize(window='current'):
+ return driver.execute('getSize', {'windowHandle': window})['value']
+ def setSize(width, height, window='current'):
+ params = { 'windowHandle': window,
+ 'width': width,
+ 'height': height
+ }
+ return driver.execute('setSize', params)
+ def getPosition(window='current'):
+ return driver.execute('getPos', {'windowHandle': window})['value']
+ def setPosition(x, y, window='current'):
+ params = { 'windowHandle': window,
+ 'x': x,
+ 'y': y
+ }
+ return driver.execute('setPos', params)
+
+ # Test size.
+ size = getSize()
+ setSize(size['width'], size['height'])
+ self.assertEquals(size, getSize())
+ setSize(800, 600)
+ self.assertEquals(800, getSize()['width'])
+ self.assertEquals(600, getSize()['height'])
+ # Test position.
+ pos = getPosition()
+ setPosition(pos['x'], pos['y'])
+ self.assertEquals(pos, getPosition())
+ setPosition(100, 200)
+ self.assertEquals(100, getPosition()['x'])
+ self.assertEquals(200, getPosition()['y'])
+ # Test specifying window handle.
+ driver.execute_script(
+ 'window.open("about:blank", "name", "height=200, width=200")')
+ windows = driver.window_handles
+ self.assertEquals(2, len(windows))
+ setSize(400, 300, windows[1])
+ self.assertEquals(400, getSize(windows[1])['width'])
+ self.assertEquals(300, getSize(windows[1])['height'])
+ self.assertNotEquals(getSize(windows[1]), getSize(windows[0]))
+ # Test specifying invalid handle.
+ invalid_handle = 'f1-120'
+ self.assertRaises(WebDriverException, setSize, 400, 300, invalid_handle)
+ self.assertRaises(NoSuchWindowException, getSize, invalid_handle)
+ self.assertRaises(NoSuchWindowException, setPosition, 1, 1, invalid_handle)
+ self.assertRaises(NoSuchWindowException, getPosition, invalid_handle)
+
+
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 efc5f00..f8ea88a 100644
--- a/chrome/test/webdriver/webdriver_automation.cc
+++ b/chrome/test/webdriver/webdriver_automation.cc
@@ -713,6 +713,16 @@ void Automation::CloseView(const WebViewId& view_id, Error** error) {
*error = Error::FromAutomationError(auto_error);
}
+void Automation::SetViewBounds(const WebViewId& view_id,
+ const Rect& bounds,
+ Error** error) {
+ automation::Error auto_error;
+ if (!SendSetViewBoundsJSONRequest(
+ automation(), view_id, bounds.x(), bounds.y(),
+ bounds.width(), bounds.height(), &auto_error))
+ *error = Error::FromAutomationError(auto_error);
+}
+
void Automation::GetAppModalDialogMessage(std::string* message, Error** error) {
*error = CheckAlertsSupported();
if (*error)
diff --git a/chrome/test/webdriver/webdriver_automation.h b/chrome/test/webdriver/webdriver_automation.h
index 76e46f5..f205527 100644
--- a/chrome/test/webdriver/webdriver_automation.h
+++ b/chrome/test/webdriver/webdriver_automation.h
@@ -37,6 +37,7 @@ namespace webdriver {
class Error;
class FramePath;
class Point;
+class Rect;
// Creates and controls the Chrome instance.
// This class should be created and accessed on a single thread.
@@ -169,6 +170,12 @@ class Automation {
// Closes the given view.
void CloseView(const WebViewId& view_id, Error** error);
+ // Sets the bounds for the given view. The position should be in screen
+ // coordinates, while the size should be the desired size of the view.
+ void SetViewBounds(const WebViewId& view_id,
+ const Rect& bounds,
+ Error** error);
+
// Gets the active JavaScript modal dialog's message.
void GetAppModalDialogMessage(std::string* message, Error** error);
diff --git a/chrome/test/webdriver/webdriver_error.cc b/chrome/test/webdriver/webdriver_error.cc
index 0884e10..102f14d 100644
--- a/chrome/test/webdriver/webdriver_error.cc
+++ b/chrome/test/webdriver/webdriver_error.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -62,6 +62,8 @@ Error* Error::FromAutomationError(const automation::Error& error) {
case automation::kBlockedByModalDialog:
code = kUnexpectedAlertOpen;
break;
+ case automation::kInvalidId:
+ code = kNoSuchWindow;
default:
break;
}
diff --git a/chrome/test/webdriver/webdriver_server.cc b/chrome/test/webdriver/webdriver_server.cc
index a2f2b45..4b6e005 100644
--- a/chrome/test/webdriver/webdriver_server.cc
+++ b/chrome/test/webdriver/webdriver_server.cc
@@ -53,6 +53,7 @@
#include "chrome/test/webdriver/commands/title_command.h"
#include "chrome/test/webdriver/commands/url_command.h"
#include "chrome/test/webdriver/commands/webelement_commands.h"
+#include "chrome/test/webdriver/commands/window_commands.h"
#include "chrome/test/webdriver/webdriver_dispatch.h"
#include "chrome/test/webdriver/webdriver_logging.h"
#include "chrome/test/webdriver/webdriver_session_manager.h"
@@ -140,6 +141,9 @@ void InitCallbacks(Dispatcher* dispatcher,
dispatcher->Add<WindowCommand>( "/session/*/window");
dispatcher->Add<WindowHandleCommand>( "/session/*/window_handle");
dispatcher->Add<WindowHandlesCommand>("/session/*/window_handles");
+ dispatcher->Add<WindowSizeCommand>( "/session/*/window/*/size");
+ dispatcher->Add<WindowPositionCommand>(
+ "/session/*/window/*/position");
dispatcher->Add<SetAsyncScriptTimeoutCommand>(
"/session/*/timeouts/async_script");
dispatcher->Add<ImplicitWaitCommand>( "/session/*/timeouts/implicit_wait");
diff --git a/chrome/test/webdriver/webdriver_session.cc b/chrome/test/webdriver/webdriver_session.cc
index 03a090b8..d924009 100644
--- a/chrome/test/webdriver/webdriver_session.cc
+++ b/chrome/test/webdriver/webdriver_session.cc
@@ -773,6 +773,37 @@ Error* Session::CloseWindow() {
return error;
}
+Error* Session::GetWindowBounds(const WebViewId& window, Rect* bounds) {
+ const char* kGetWindowBoundsScript =
+ "function() {"
+ " return {"
+ " 'left': window.screenX,"
+ " 'top': window.screenY,"
+ " 'width': window.outerWidth,"
+ " 'height': window.outerHeight"
+ " }"
+ "}";
+ return ExecuteScriptAndParse(
+ FrameId(window, FramePath()),
+ kGetWindowBoundsScript,
+ "getWindowBoundsScript",
+ new ListValue(),
+ CreateDirectValueParser(bounds));
+}
+
+Error* Session::SetWindowBounds(
+ const WebViewId& window,
+ const Rect& bounds) {
+ Error* error = NULL;
+ RunSessionTask(base::Bind(
+ &Automation::SetViewBounds,
+ base::Unretained(automation_.get()),
+ window,
+ bounds,
+ &error));
+ return error;
+}
+
Error* Session::GetAlertMessage(std::string* text) {
Error* error = NULL;
RunSessionTask(base::Bind(
diff --git a/chrome/test/webdriver/webdriver_session.h b/chrome/test/webdriver/webdriver_session.h
index f039edc..a6c2c83 100644
--- a/chrome/test/webdriver/webdriver_session.h
+++ b/chrome/test/webdriver/webdriver_session.h
@@ -174,6 +174,12 @@ class Session {
// session.
Error* CloseWindow();
+ // Gets the bounds for the specified window.
+ Error* GetWindowBounds(const WebViewId& window, Rect* bounds);
+
+ // Sets the bounds for the specified window.
+ Error* SetWindowBounds(const WebViewId& window, const Rect& bounds);
+
// Gets the message of the currently active JavaScript modal dialog.
Error* GetAlertMessage(std::string* text);
diff --git a/chrome/test/webdriver/webdriver_util.cc b/chrome/test/webdriver/webdriver_util.cc
index 1347284..bab42b8 100644
--- a/chrome/test/webdriver/webdriver_util.cc
+++ b/chrome/test/webdriver/webdriver_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -12,6 +12,7 @@
#include "base/rand_util.h"
#include "base/stringprintf.h"
#include "base/string_number_conversions.h"
+#include "base/string_split.h"
#include "base/third_party/icu/icu_utf.h"
#include "chrome/common/automation_id.h"
#include "chrome/test/automation/automation_json_requests.h"
@@ -121,31 +122,37 @@ const char* GetJsonTypeName(Value::Type type) {
return "unknown";
}
+std::string AutomationIdToString(const AutomationId& id) {
+ return base::StringPrintf("%d-%s", id.type(), id.id().c_str());
+}
+
bool StringToAutomationId(const std::string& string_id, AutomationId* id) {
- scoped_ptr<Value> value(base::JSONReader::Read(string_id, false));
- std::string error_msg;
- return value.get() && AutomationId::FromValue(value.get(), id, &error_msg);
+ std::vector<std::string> split_id;
+ base::SplitString(string_id, '-', &split_id);
+ if (split_id.size() != 2)
+ return false;
+ int type;
+ if (!base::StringToInt(split_id[0], &type))
+ return false;
+ *id = AutomationId(static_cast<AutomationId::Type>(type), split_id[1]);
+ return true;
}
std::string WebViewIdToString(const WebViewId& view_id) {
- DictionaryValue* dict = view_id.GetId().ToValue();
- if (view_id.old_style())
- dict->SetBoolean("old_style", true);
- return JsonStringify(dict);
+ return base::StringPrintf(
+ "%s%s",
+ view_id.old_style() ? "t" : "f",
+ AutomationIdToString(view_id.GetId()).c_str());
}
bool StringToWebViewId(const std::string& string_id, WebViewId* view_id) {
- scoped_ptr<Value> value(base::JSONReader::Read(string_id, false));
+ if (string_id.empty() || (string_id[0] != 'f' && string_id[0] != 't'))
+ return false;
+ bool old_style = string_id[0] == 't';
AutomationId id;
- std::string error_msg;
- DictionaryValue* dict;
- if (!value.get() || !AutomationId::FromValue(value.get(), &id, &error_msg) ||
- !value->GetAsDictionary(&dict))
+ if (!StringToAutomationId(string_id.substr(1), &id))
return false;
- bool old_style = false;
- dict->GetBoolean("old_style", &old_style);
-
if (old_style) {
int tab_id;
if (!base::StringToInt(id.id(), &tab_id))
diff --git a/chrome/test/webdriver/webdriver_util.h b/chrome/test/webdriver/webdriver_util.h
index 628623b..2628e0e 100644
--- a/chrome/test/webdriver/webdriver_util.h
+++ b/chrome/test/webdriver/webdriver_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -34,6 +34,9 @@ std::string JsonStringifyForDisplay(const base::Value* value);
// Returns the string representation of the given type, for display purposes.
const char* GetJsonTypeName(base::Value::Type type);
+// Converts the automation ID to a string.
+std::string AutomationIdToString(const AutomationId& id);
+
// Converts the string to an automation ID and returns true on success.
bool StringToAutomationId(const std::string& string_id, AutomationId* id);