summaryrefslogtreecommitdiffstats
path: root/chrome/test/webdriver
diff options
context:
space:
mode:
authorkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-17 17:02:53 +0000
committerkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-17 17:02:53 +0000
commit496e57908e1d53b286a9fb38339a558863b7068c (patch)
treee25648bbc8c2a4ce1899a0799cff3d8c8c94511a /chrome/test/webdriver
parent3c51bcfe87bda9ea798986c42b2e38503f4b0de8 (diff)
downloadchromium_src-496e57908e1d53b286a9fb38339a558863b7068c.zip
chromium_src-496e57908e1d53b286a9fb38339a558863b7068c.tar.gz
chromium_src-496e57908e1d53b286a9fb38339a558863b7068c.tar.bz2
Implement the target locator commands for ChromeDriver.
BUG=none TEST=none Review URL: http://codereview.chromium.org/6507015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75279 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/test/webdriver')
-rw-r--r--chrome/test/webdriver/WEBDRIVER_TESTS5
-rw-r--r--chrome/test/webdriver/automation.cc209
-rw-r--r--chrome/test/webdriver/automation.h57
-rw-r--r--chrome/test/webdriver/commands/command.cc8
-rw-r--r--chrome/test/webdriver/commands/command.h7
-rw-r--r--chrome/test/webdriver/commands/create_session.cc18
-rw-r--r--chrome/test/webdriver/commands/session_with_id.cc2
-rw-r--r--chrome/test/webdriver/commands/target_locator_commands.cc133
-rw-r--r--chrome/test/webdriver/commands/target_locator_commands.h84
-rw-r--r--chrome/test/webdriver/server.cc25
-rw-r--r--chrome/test/webdriver/session.cc227
-rw-r--r--chrome/test/webdriver/session.h61
-rw-r--r--chrome/test/webdriver/session_manager.cc37
-rw-r--r--chrome/test/webdriver/session_manager.h4
14 files changed, 734 insertions, 143 deletions
diff --git a/chrome/test/webdriver/WEBDRIVER_TESTS b/chrome/test/webdriver/WEBDRIVER_TESTS
index abbd9fc..f5ec2ac 100644
--- a/chrome/test/webdriver/WEBDRIVER_TESTS
+++ b/chrome/test/webdriver/WEBDRIVER_TESTS
@@ -51,7 +51,10 @@
'-executing_javascript_test.ExecutingJavaScriptTests.testShouldBeAbleToPassAStringAnAsArgument',
'-executing_javascript_test.ExecutingJavaScriptTests.testShouldBeAbleToPassInMoreThanOneArgument',
# 'form_handling_tests',
-# 'frame_switching_tests',
+ 'frame_switching_tests',
+ # Next two frame switching tests are disabled because they depend on toggle.
+ '-frame_switching_tests.FrameSwitchingTest.testThatWeCanSwitchFrameByName',
+ '-frame_switching_tests.FrameSwitchingTest.testThatWeCanSwitchToFrameByIndex',
# 'implicit_waits_tests',
'page_loading_tests',
# testShouldReturnWhenGettingAUrlThatDoesNotResolve causes the test after
diff --git a/chrome/test/webdriver/automation.cc b/chrome/test/webdriver/automation.cc
index 19236b0..dfaae5a 100644
--- a/chrome/test/webdriver/automation.cc
+++ b/chrome/test/webdriver/automation.cc
@@ -10,6 +10,7 @@
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/test/automation/automation_proxy.h"
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/test_launcher_utils.h"
@@ -37,16 +38,6 @@ void Automation::Init(bool* success) {
launch_arguments_.AppendSwitchPath(switches::kUserDataDir,
profile_dir_.path());
UITestBase::SetUp();
- browser_ = automation()->GetBrowserWindow(0);
- if (!browser_.get()) {
- Terminate();
- return;
- }
- tab_ = browser_->GetActiveTab();
- if (!tab_.get()) {
- Terminate();
- return;
- }
*success = true;
}
@@ -54,21 +45,51 @@ void Automation::Terminate() {
QuitBrowser();
}
-void Automation::ExecuteScript(const std::string& frame_xpath,
+void Automation::ExecuteScript(int tab_id,
+ const std::string& frame_xpath,
const std::string& script,
std::string* result,
bool* success) {
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
std::wstring wide_xpath = UTF8ToWide(frame_xpath);
std::wstring wide_script = UTF8ToWide(script);
std::wstring wide_result;
- *success = tab_->ExecuteAndExtractString(
+ *success = tab->ExecuteAndExtractString(
wide_xpath, wide_script, &wide_result);
if (*success)
*result = WideToUTF8(wide_result);
}
-void Automation::SendWebKeyEvent(const WebKeyEvent& key_event,
+void Automation::SendWebKeyEvent(int tab_id,
+ const WebKeyEvent& key_event,
bool* success) {
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ LOG(ERROR) << "No such tab";
+ *success = false;
+ return;
+ }
+ int tab_index = 0;
+ if (!tab->GetTabIndex(&tab_index)) {
+ LOG(ERROR) << "Could not get tab index";
+ *success = false;
+ return;
+ }
+ scoped_refptr<BrowserProxy> browser = tab->GetParentBrowser();
+ if (!browser.get()) {
+ LOG(ERROR) << "Could not get parent browser of tab";
+ *success = false;
+ return;
+ }
+ if (!browser->ActivateTab(tab_index)) {
+ LOG(ERROR) << "Could not activate tab to send keys";
+ *success = false;
+ return;
+ }
scoped_ptr<DictionaryValue> dict(new DictionaryValue);
dict->SetString("command", "SendKeyEventToActiveTab");
dict->SetInteger("type", key_event.type);
@@ -81,73 +102,189 @@ void Automation::SendWebKeyEvent(const WebKeyEvent& key_event,
std::string request;
base::JSONWriter::Write(dict.get(), false, &request);
std::string reply;
- *success = browser_->SendJSONRequest(request, &reply);
+ *success = browser->SendJSONRequest(request, &reply);
if (!*success) {
LOG(ERROR) << "Could not send web key event. Reply: " << reply;
}
}
-void Automation::NavigateToURL(const std::string& url,
+void Automation::NavigateToURL(int tab_id,
+ const std::string& url,
bool* success) {
- *success = tab_->NavigateToURL(GURL(url));
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
+ *success = tab->NavigateToURL(GURL(url));
}
-void Automation::GoForward(bool* success) {
- *success = tab_->GoForward();
+void Automation::GoForward(int tab_id, bool* success) {
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
+ *success = tab->GoForward();
}
-void Automation::GoBack(bool* success) {
- *success = tab_->GoBack();
+void Automation::GoBack(int tab_id, bool* success) {
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
+ *success = tab->GoBack();
}
-void Automation::Reload(bool* success) {
- *success = tab_->Reload();
+void Automation::Reload(int tab_id, bool* success) {
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
+ *success = tab->Reload();
}
-void Automation::GetURL(std::string* url,
+void Automation::GetURL(int tab_id,
+ std::string* url,
bool* success) {
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
GURL gurl;
- *success = tab_->GetCurrentURL(&gurl);
+ *success = tab->GetCurrentURL(&gurl);
if (*success)
*url = gurl.possibly_invalid_spec();
}
-void Automation::GetGURL(GURL* gurl,
+void Automation::GetGURL(int tab_id,
+ GURL* gurl,
bool* success) {
- *success = tab_->GetCurrentURL(gurl);
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
+ *success = tab->GetCurrentURL(gurl);
}
-void Automation::GetTabTitle(std::string* tab_title,
+void Automation::GetTabTitle(int tab_id,
+ std::string* tab_title,
bool* success) {
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
std::wstring wide_title;
- *success = tab_->GetTabTitle(&wide_title);
+ *success = tab->GetTabTitle(&wide_title);
if (*success)
*tab_title = WideToUTF8(wide_title);
}
-void Automation::GetCookies(const GURL& gurl,
+void Automation::GetCookies(int tab_id,
+ const GURL& gurl,
std::string* cookies,
bool* success) {
- *success = tab_->GetCookies(gurl, cookies);
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
+ *success = tab->GetCookies(gurl, cookies);
}
-void Automation::GetCookieByName(const GURL& gurl,
+void Automation::GetCookieByName(int tab_id,
+ const GURL& gurl,
const std::string& cookie_name,
std::string* cookie,
bool* success) {
- *success = tab_->GetCookieByName(gurl, cookie_name, cookie);
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
+ *success = tab->GetCookieByName(gurl, cookie_name, cookie);
}
-void Automation::DeleteCookie(const GURL& gurl,
+void Automation::DeleteCookie(int tab_id,
+ const GURL& gurl,
const std::string& cookie_name,
bool* success) {
- *success = tab_->DeleteCookie(gurl, cookie_name);
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
+ *success = tab->DeleteCookie(gurl, cookie_name);
}
-void Automation::SetCookie(const GURL& gurl,
+void Automation::SetCookie(int tab_id,
+ const GURL& gurl,
const std::string& cookie,
bool* success) {
- *success = tab_->SetCookie(gurl, cookie);
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
+ *success = tab->SetCookie(gurl, cookie);
+}
+
+void Automation::GetTabIds(std::vector<int>* tab_ids,
+ bool* success) {
+ *success = false;
+ int browser_count = 0;
+ if (!automation()->GetBrowserWindowCount(&browser_count)) {
+ LOG(ERROR) << "Failed to get browser window count";
+ return;
+ }
+ TabIdMap tab_id_map;
+ for (int browser_index = 0; browser_index < browser_count; ++browser_index) {
+ scoped_refptr<BrowserProxy> browser =
+ automation()->GetBrowserWindow(browser_index);
+ if (!browser.get())
+ continue;
+ int tab_count = 0;
+ if (!browser->GetTabCount(&tab_count))
+ continue;
+
+ for (int tab_index = 0; tab_index < tab_count; ++tab_index) {
+ scoped_refptr<TabProxy> tab = browser->GetTab(tab_index);
+ if (!tab.get())
+ continue;
+ tab_ids->push_back(tab->handle());
+ tab_id_map.insert(std::make_pair(tab->handle(), tab));
+ }
+ }
+
+ tab_id_map_ = tab_id_map;
+ *success = true;
+}
+
+void Automation::DoesTabExist(int tab_id, bool* does_exist) {
+ TabProxy* tab = GetTabById(tab_id);
+ *does_exist = tab && tab->is_valid();
+}
+
+void Automation::CloseTab(int tab_id, bool* success) {
+ TabProxy* tab = GetTabById(tab_id);
+ if (!tab) {
+ *success = false;
+ return;
+ }
+ *success = tab->Close(true);
+}
+
+TabProxy* Automation::GetTabById(int tab_id) {
+ TabIdMap::const_iterator iter = tab_id_map_.find(tab_id);
+ if (iter != tab_id_map_.end()) {
+ return iter->second.get();
+ }
+ return NULL;
}
} // namespace webdriver
diff --git a/chrome/test/webdriver/automation.h b/chrome/test/webdriver/automation.h
index 1d97bc2..34a1cca 100644
--- a/chrome/test/webdriver/automation.h
+++ b/chrome/test/webdriver/automation.h
@@ -5,7 +5,9 @@
#ifndef CHROME_TEST_WEBDRIVER_AUTOMATION_H_
#define CHROME_TEST_WEBDRIVER_AUTOMATION_H_
+#include <map>
#include <string>
+#include <vector>
#include "base/task.h"
#include "base/ref_counted.h"
@@ -15,6 +17,7 @@
#include "ui/base/keycodes/keyboard_codes.h"
class GURL;
+class TabProxy;
namespace webdriver {
@@ -57,33 +60,53 @@ class Automation : private UITestBase {
// Executes the given |script| in the specified frame of the current
// tab. |result| will be set to the JSON result. Returns true on success.
- void ExecuteScript(const std::string& frame_xpath,
+ void ExecuteScript(int tab_id,
+ const std::string& frame_xpath,
const std::string& script,
std::string* result,
bool* success);
// Sends a key event to the current browser. Waits until the key has
// been processed by the web page.
- void SendWebKeyEvent(const WebKeyEvent& key_event, bool* success);
-
- void NavigateToURL(const std::string& url, bool* success);
- void GoForward(bool* success);
- void GoBack(bool* success);
- void Reload(bool* success);
- void GetURL(std::string* url, bool* success);
- void GetGURL(GURL* gurl, bool* success);
- void GetTabTitle(std::string* tab_title, bool* success);
- void GetCookies(const GURL& gurl, std::string* cookies, bool* success);
- void GetCookieByName(const GURL& gurl, const std::string& cookie_name,
- std::string* cookie, bool* success);
- void DeleteCookie(const GURL& gurl, const std::string& cookie_name,
+ void SendWebKeyEvent(int tab_id, const WebKeyEvent& key_event, bool* success);
+
+ void NavigateToURL(int tab_id, const std::string& url, bool* success);
+ void GoForward(int tab_id, bool* success);
+ void GoBack(int tab_id, bool* success);
+ void Reload(int tab_id, bool* success);
+ void GetURL(int tab_id, std::string* url, bool* success);
+ void GetGURL(int tab_id, GURL* gurl, bool* success);
+ void GetTabTitle(int tab_id, std::string* tab_title, bool* success);
+ void GetCookies(
+ int tab_id, const GURL& gurl, std::string* cookies, bool* success);
+ void GetCookieByName(int tab_id,
+ const GURL& gurl,
+ const std::string& cookie_name,
+ std::string* cookie,
+ bool* success);
+ void DeleteCookie(int tab_id,
+ const GURL& gurl,
+ const std::string& cookie_name,
bool* success);
- void SetCookie(const GURL& gurl, const std::string& cookie, bool* success);
+ void SetCookie(
+ int tab_id, const GURL& gurl, const std::string& cookie, bool* success);
+
+ // Get persistent IDs for all the tabs currently open. These IDs can be used
+ // to identify the tab as long as the tab exists.
+ void GetTabIds(std::vector<int>* tab_ids, bool* success);
+
+ // Check if the given tab exists currently.
+ void DoesTabExist(int tab_id, bool* does_exist);
+
+ void CloseTab(int tab_id, bool* success);
private:
- scoped_refptr<BrowserProxy> browser_;
- scoped_refptr<TabProxy> tab_;
+ typedef std::map<int, scoped_refptr<TabProxy> > TabIdMap;
+ TabProxy* GetTabById(int tab_id);
+ // Map from tab ID to |TabProxy|. The tab ID is simply the |AutomationHandle|
+ // for the proxy.
+ TabIdMap tab_id_map_;
ScopedTempDir profile_dir_;
DISALLOW_COPY_AND_ASSIGN(Automation);
diff --git a/chrome/test/webdriver/commands/command.cc b/chrome/test/webdriver/commands/command.cc
index 29ea60f..cb9e670 100644
--- a/chrome/test/webdriver/commands/command.cc
+++ b/chrome/test/webdriver/commands/command.cc
@@ -40,6 +40,13 @@ bool Command::Init(Response* const response) {
return true;
}
+bool Command::IsNullParameter(const std::string& key) const {
+ Value* value;
+ return parameters_.get() &&
+ parameters_->Get(key, &value) &&
+ value->IsType(Value::TYPE_NULL);
+}
+
bool Command::GetStringParameter(const std::string& key,
string16* out) const {
return parameters_.get() != NULL && parameters_->GetString(key, out);
@@ -76,4 +83,3 @@ bool Command::GetListParameter(const std::string& key,
}
} // namespace webdriver
-
diff --git a/chrome/test/webdriver/commands/command.h b/chrome/test/webdriver/commands/command.h
index 75cc9bc..9d3cd4e 100644
--- a/chrome/test/webdriver/commands/command.h
+++ b/chrome/test/webdriver/commands/command.h
@@ -54,7 +54,11 @@ class Command {
return i < path_segments_.size() ? path_segments_.at(i) : "";
}
- // Provides the command parameter with the given |key| as a UTF-16 string.
+ // Returns true if the command parameter with the given |key| exists and is
+ // a null value.
+ bool IsNullParameter(const std::string& key) const;
+
+ // Returns the command parameter with the given |key| as a UTF-16 string.
// Returns true on success.
bool GetStringParameter(const std::string& key, string16* out) const;
@@ -100,4 +104,3 @@ class Command {
} // namespace webdriver
#endif // CHROME_TEST_WEBDRIVER_COMMANDS_COMMAND_H_
-
diff --git a/chrome/test/webdriver/commands/create_session.cc b/chrome/test/webdriver/commands/create_session.cc
index 9f30d15..8634444 100644
--- a/chrome/test/webdriver/commands/create_session.cc
+++ b/chrome/test/webdriver/commands/create_session.cc
@@ -24,28 +24,20 @@ CreateSession::~CreateSession() {}
bool CreateSession::DoesPost() { return true; }
void CreateSession::ExecutePost(Response* const response) {
- SessionManager* session_manager = SessionManager::GetInstance();
- Session* session = session_manager->Create();
- if (!session) {
- SET_WEBDRIVER_ERROR(response,
- "Failed to create session",
- kInternalServerError);
- return;
- }
-
- std::string session_id = session->id();
+ // Session manages its own liftime, so do not call delete.
+ Session* session = new Session();
if (!session->Init()) {
- session_manager->Delete(session_id);
SET_WEBDRIVER_ERROR(response,
"Failed to initialize session",
kInternalServerError);
return;
}
- VLOG(1) << "Created session " << session_id;
+ SessionManager* session_manager = SessionManager::GetInstance();
+ VLOG(1) << "Created session " << session->id();
std::ostringstream stream;
stream << "http://" << session_manager->GetAddress() << "/session/"
- << session_id;
+ << session->id();
response->set_status(kSeeOther);
response->set_value(Value::CreateStringValue(stream.str()));
}
diff --git a/chrome/test/webdriver/commands/session_with_id.cc b/chrome/test/webdriver/commands/session_with_id.cc
index ef3cd64..ef7c1da 100644
--- a/chrome/test/webdriver/commands/session_with_id.cc
+++ b/chrome/test/webdriver/commands/session_with_id.cc
@@ -55,8 +55,8 @@ void SessionWithID::ExecuteGet(Response* const response) {
}
void SessionWithID::ExecuteDelete(Response* const response) {
+ // Session manages its own liftime, so do not call delete.
session_->Terminate();
- SessionManager::GetInstance()->Delete(session_->id());
response->set_status(kSuccess);
}
diff --git a/chrome/test/webdriver/commands/target_locator_commands.cc b/chrome/test/webdriver/commands/target_locator_commands.cc
new file mode 100644
index 0000000..8808ca4
--- /dev/null
+++ b/chrome/test/webdriver/commands/target_locator_commands.cc
@@ -0,0 +1,133 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/test/webdriver/commands/target_locator_commands.h"
+
+#include "base/string_number_conversions.h"
+#include "base/values.h"
+#include "chrome/test/webdriver/commands/response.h"
+#include "chrome/test/webdriver/error_codes.h"
+#include "chrome/test/webdriver/session.h"
+
+namespace webdriver {
+
+WindowHandleCommand::WindowHandleCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebDriverCommand(path_segments, parameters) {}
+
+WindowHandleCommand::~WindowHandleCommand() {}
+
+bool WindowHandleCommand::DoesGet() {
+ return true;
+}
+
+void WindowHandleCommand::ExecuteGet(Response* const response) {
+ response->set_status(kSuccess);
+ response->set_value(new StringValue(
+ base::IntToString(session_->current_window_id())));
+}
+
+WindowHandlesCommand::WindowHandlesCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebDriverCommand(path_segments, parameters) {}
+
+WindowHandlesCommand::~WindowHandlesCommand() {}
+
+bool WindowHandlesCommand::DoesGet() {
+ return true;
+}
+
+void WindowHandlesCommand::ExecuteGet(Response* const response) {
+ std::vector<int> window_ids;
+ if (!session_->GetWindowIds(&window_ids)) {
+ SET_WEBDRIVER_ERROR(
+ response, "Could not get window handles", kInternalServerError);
+ return;
+ }
+ ListValue* id_list = new ListValue();
+ for (size_t i = 0; i < window_ids.size(); ++i)
+ id_list->Append(new StringValue(base::IntToString(window_ids[i])));
+ response->set_status(kSuccess);
+ response->set_value(id_list);
+}
+
+WindowCommand::WindowCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebDriverCommand(path_segments, parameters) {}
+
+WindowCommand::~WindowCommand() {}
+
+bool WindowCommand::DoesPost() {
+ return true;
+}
+
+bool WindowCommand::DoesDelete() {
+ return true;
+}
+
+void WindowCommand::ExecutePost(Response* const response) {
+ std::string name;
+ if (!GetStringParameter("name", &name)) {
+ SET_WEBDRIVER_ERROR(
+ response, "Missing or invalid 'name' parameter", kBadRequest);
+ return;
+ }
+
+ ErrorCode code = session_->SwitchToWindow(name);
+ if (code != kSuccess) {
+ SET_WEBDRIVER_ERROR(response, "Could not switch window", code);
+ return;
+ }
+ response->set_status(kSuccess);
+}
+
+void WindowCommand::ExecuteDelete(Response* const response) {
+ if (!session_->CloseWindow()) {
+ SET_WEBDRIVER_ERROR(
+ response, "Could not close window", kInternalServerError);
+ return;
+ }
+ response->set_status(kSuccess);
+}
+
+SwitchFrameCommand::SwitchFrameCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebDriverCommand(path_segments, parameters) {}
+
+SwitchFrameCommand::~SwitchFrameCommand() {}
+
+bool SwitchFrameCommand::DoesPost() {
+ return true;
+}
+
+void SwitchFrameCommand::ExecutePost(Response* const response) {
+ std::string id;
+ int index = 0;
+ if (GetStringParameter("id", &id)) {
+ ErrorCode code = session_->SwitchToFrameWithNameOrId(id);
+ if (code != kSuccess) {
+ SET_WEBDRIVER_ERROR(response, "Could not switch to frame", code);
+ return;
+ }
+ } else if (GetIntegerParameter("id", &index)) {
+ ErrorCode code = session_->SwitchToFrameWithIndex(index);
+ if (code != kSuccess) {
+ SET_WEBDRIVER_ERROR(response, "Could not switch to frame", code);
+ return;
+ }
+ } else if (IsNullParameter("id")) {
+ session_->set_current_frame_xpath("");
+ } else {
+ SET_WEBDRIVER_ERROR(
+ response, "Missing or invalid 'id' parameter", kBadRequest);
+ return;
+ }
+ response->set_status(kSuccess);
+}
+
+} // namespace webdriver
diff --git a/chrome/test/webdriver/commands/target_locator_commands.h b/chrome/test/webdriver/commands/target_locator_commands.h
new file mode 100644
index 0000000..d9093cc
--- /dev/null
+++ b/chrome/test/webdriver/commands/target_locator_commands.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_TEST_WEBDRIVER_COMMANDS_TARGET_LOCATOR_COMMANDS_H_
+#define CHROME_TEST_WEBDRIVER_COMMANDS_TARGET_LOCATOR_COMMANDS_H_
+
+#include <string>
+#include <vector>
+
+#include "chrome/test/webdriver/commands/webdriver_command.h"
+
+class DictionaryValue;
+
+namespace webdriver {
+
+class Response;
+
+// Gets the current window handle.
+// REST URL: /session/:sessionId/window_handle
+class WindowHandleCommand : public WebDriverCommand {
+ public:
+ WindowHandleCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~WindowHandleCommand();
+
+ virtual bool DoesGet();
+ virtual void ExecuteGet(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WindowHandleCommand);
+};
+
+// Gets a list of all window handles.
+// REST URL: /session/:sessionId/window_handles
+class WindowHandlesCommand : public WebDriverCommand {
+ public:
+ WindowHandlesCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~WindowHandlesCommand();
+
+ virtual bool DoesGet();
+ virtual void ExecuteGet(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WindowHandlesCommand);
+};
+
+// Switches to the given window as the default window to execute commands on
+// or closes it.
+// REST URL: /session/:sessionId/window
+class WindowCommand : public WebDriverCommand {
+ public:
+ WindowCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~WindowCommand();
+
+ virtual bool DoesPost();
+ virtual bool DoesDelete();
+ virtual void ExecutePost(Response* const response);
+ virtual void ExecuteDelete(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WindowCommand);
+};
+
+// Switches to the given frame as the default frame to execute commands in.
+// REST URL: /session/:sessionId/frame
+class SwitchFrameCommand : public WebDriverCommand {
+ public:
+ SwitchFrameCommand(const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters);
+ virtual ~SwitchFrameCommand();
+
+ virtual bool DoesPost();
+ virtual void ExecutePost(Response* const response);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SwitchFrameCommand);
+};
+
+} // namespace webdriver
+
+#endif // CHROME_TEST_WEBDRIVER_COMMANDS_TARGET_LOCATOR_COMMANDS_H_
diff --git a/chrome/test/webdriver/server.cc b/chrome/test/webdriver/server.cc
index 829f088..274820a 100644
--- a/chrome/test/webdriver/server.cc
+++ b/chrome/test/webdriver/server.cc
@@ -38,6 +38,7 @@
#include "chrome/test/webdriver/commands/session_with_id.h"
#include "chrome/test/webdriver/commands/source_command.h"
#include "chrome/test/webdriver/commands/speed_command.h"
+#include "chrome/test/webdriver/commands/target_locator_commands.h"
#include "chrome/test/webdriver/commands/title_command.h"
#include "chrome/test/webdriver/commands/url_command.h"
#include "chrome/test/webdriver/commands/webelement_commands.h"
@@ -79,16 +80,20 @@ void InitCallbacks(struct mg_context* ctx,
base::WaitableEvent* shutdown_event) {
mg_set_uri_callback(ctx, "/shutdown", &Shutdown, shutdown_event);
- SetCallback<CreateSession>(ctx, "/session");
- SetCallback<BackCommand>(ctx, "/session/*/back");
- SetCallback<ExecuteCommand>(ctx, "/session/*/execute");
- SetCallback<ForwardCommand>(ctx, "/session/*/forward");
- SetCallback<RefreshCommand>(ctx, "/session/*/refresh");
- SetCallback<SourceCommand>(ctx, "/session/*/source");
- SetCallback<TitleCommand>(ctx, "/session/*/title");
- SetCallback<URLCommand>(ctx, "/session/*/url");
- SetCallback<SpeedCommand>(ctx, "/session/*/speed");
- SetCallback<ImplicitWaitCommand>(ctx, "/session/*/timeouts/implicit_wait");
+ SetCallback<CreateSession>(ctx, "/session");
+ SetCallback<BackCommand>(ctx, "/session/*/back");
+ SetCallback<ExecuteCommand>(ctx, "/session/*/execute");
+ SetCallback<ForwardCommand>(ctx, "/session/*/forward");
+ SetCallback<RefreshCommand>(ctx, "/session/*/refresh");
+ SetCallback<SourceCommand>(ctx, "/session/*/source");
+ SetCallback<TitleCommand>(ctx, "/session/*/title");
+ SetCallback<URLCommand>(ctx, "/session/*/url");
+ SetCallback<SpeedCommand>(ctx, "/session/*/speed");
+ SetCallback<ImplicitWaitCommand>(ctx, "/session/*/timeouts/implicit_wait");
+ SetCallback<WindowHandleCommand>(ctx, "/session/*/window_handle");
+ SetCallback<WindowHandlesCommand>(ctx, "/session/*/window_handles");
+ SetCallback<WindowCommand>(ctx, "/session/*/window");
+ SetCallback<SwitchFrameCommand>(ctx, "/session/*/frame");
// Cookie functions.
SetCallback<CookieCommand>(ctx, "/session/*/cookie");
diff --git a/chrome/test/webdriver/session.cc b/chrome/test/webdriver/session.cc
index bfbefeb..849e7c6 100644
--- a/chrome/test/webdriver/session.cc
+++ b/chrome/test/webdriver/session.cc
@@ -12,7 +12,9 @@
#include "base/message_loop_proxy.h"
#include "base/process.h"
#include "base/process_util.h"
+#include "base/scoped_ptr.h"
#include "base/stringprintf.h"
+#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
@@ -22,6 +24,7 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/test_launcher_utils.h"
+#include "chrome/test/webdriver/session_manager.h"
#include "chrome/test/webdriver/utility_functions.h"
#include "chrome/test/webdriver/webdriver_key_converter.h"
#include "googleurl/src/gurl.h"
@@ -29,27 +32,31 @@
namespace webdriver {
-Session::Session(const std::string& id)
- : thread_(id.c_str()),
- id_(id),
- window_num_(0),
+Session::Session()
+ : id_(GenerateRandomID()),
+ thread_(id_.c_str()),
implicit_wait_(0),
- current_frame_xpath_("") {
+ current_frame_xpath_(""),
+ current_window_id_(0) {
+ SessionManager::GetInstance()->Add(this);
}
-Session::~Session() {}
+Session::~Session() {
+ SessionManager::GetInstance()->Remove(id_);
+}
bool Session::Init() {
- if (!thread_.Start()) {
+ bool success = false;
+ if (thread_.Start()) {
+ RunSessionTask(NewRunnableMethod(
+ this,
+ &Session::InitOnSessionThread,
+ &success));
+ } else {
LOG(ERROR) << "Cannot start session thread";
- return false;
}
-
- bool success = false;
- RunSessionTask(NewRunnableMethod(
- this,
- &Session::InitOnSessionThread,
- &success));
+ if (!success)
+ delete this;
return success;
}
@@ -57,9 +64,12 @@ void Session::Terminate() {
RunSessionTask(NewRunnableMethod(
this,
&Session::TerminateOnSessionThread));
+ delete this;
}
-ErrorCode Session::ExecuteScript(const std::string& script,
+ErrorCode Session::ExecuteScript(int window_id,
+ const std::string& frame_xpath,
+ const std::string& script,
const ListValue* const args,
Value** value) {
std::string args_as_json;
@@ -80,15 +90,17 @@ ErrorCode Session::ExecuteScript(const std::string& script,
VLOG(1) << "Executing script in frame: " << current_frame_xpath_;
std::string result;
- bool success;
+ bool success = false;
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::ExecuteScript,
- current_frame_xpath_,
+ window_id,
+ frame_xpath,
jscript,
&result,
&success));
if (!success) {
+ LOG(ERROR) << "Automation failed to execute script";
*value = Value::CreateStringValue(
"Unknown internal script execution failure");
return kUnknownError;
@@ -98,12 +110,14 @@ ErrorCode Session::ExecuteScript(const std::string& script,
scoped_ptr<Value> r(base::JSONReader::ReadAndReturnError(
result, true, NULL, NULL));
if (!r.get()) {
+ LOG(ERROR) << "Failed to parse script result";
*value = Value::CreateStringValue(
"Internal script execution error: failed to parse script result");
return kUnknownError;
}
if (r->GetType() != Value::TYPE_DICTIONARY) {
+ LOG(ERROR) << "Execute script returned non-dictionary type";
std::ostringstream stream;
stream << "Internal script execution error: script result must be a "
<< print_valuetype(Value::TYPE_DICTIONARY) << ", but was "
@@ -130,6 +144,13 @@ ErrorCode Session::ExecuteScript(const std::string& script,
return static_cast<ErrorCode>(status);
}
+ErrorCode Session::ExecuteScript(const std::string& script,
+ const ListValue* const args,
+ Value** value) {
+ return ExecuteScript(
+ current_window_id_, current_frame_xpath_, script, args, value);
+}
+
ErrorCode Session::SendKeys(DictionaryValue* element, const string16& keys) {
ListValue args;
args.Append(element);
@@ -138,8 +159,10 @@ ErrorCode Session::SendKeys(DictionaryValue* element, const string16& keys) {
Value* unscoped_result = NULL;
ErrorCode code = ExecuteScript(script, &args, &unscoped_result);
scoped_ptr<Value> result(unscoped_result);
- if (code != kSuccess)
+ if (code != kSuccess) {
+ LOG(ERROR) << "Failed to focus element before sending keys";
return code;
+ }
bool success = false;
RunSessionTask(NewRunnableMethod(
@@ -157,6 +180,7 @@ bool Session::NavigateToURL(const std::string& url) {
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::NavigateToURL,
+ current_window_id_,
url,
&success));
return success;
@@ -167,6 +191,7 @@ bool Session::GoForward() {
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::GoForward,
+ current_window_id_,
&success));
return success;
}
@@ -176,6 +201,7 @@ bool Session::GoBack() {
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::GoBack,
+ current_window_id_,
&success));
return success;
}
@@ -185,6 +211,7 @@ bool Session::Reload() {
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::Reload,
+ current_window_id_,
&success));
return success;
}
@@ -194,6 +221,7 @@ bool Session::GetURL(std::string* url) {
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::GetURL,
+ current_window_id_,
url,
&success));
return success;
@@ -204,6 +232,7 @@ bool Session::GetURL(GURL* gurl) {
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::GetGURL,
+ current_window_id_,
gurl,
&success));
return success;
@@ -214,6 +243,7 @@ bool Session::GetTabTitle(std::string* tab_title) {
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::GetTabTitle,
+ current_window_id_,
tab_title,
&success));
return success;
@@ -224,6 +254,7 @@ bool Session::GetCookies(const GURL& url, std::string* cookies) {
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::GetCookies,
+ current_window_id_,
url,
cookies,
&success));
@@ -237,6 +268,7 @@ bool Session::GetCookieByName(const GURL& url,
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::GetCookieByName,
+ current_window_id_,
url,
cookie_name,
cookie,
@@ -249,6 +281,7 @@ bool Session::DeleteCookie(const GURL& url, const std::string& cookie_name) {
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::DeleteCookie,
+ current_window_id_,
url,
cookie_name,
&success));
@@ -260,12 +293,131 @@ bool Session::SetCookie(const GURL& url, const std::string& cookie) {
RunSessionTask(NewRunnableMethod(
automation_.get(),
&Automation::SetCookie,
+ current_window_id_,
url,
cookie,
&success));
return success;
}
+bool Session::GetWindowIds(std::vector<int>* window_ids) {
+ bool success = false;
+ RunSessionTask(NewRunnableMethod(
+ automation_.get(),
+ &Automation::GetTabIds,
+ window_ids,
+ &success));
+ return success;
+}
+
+ErrorCode Session::SwitchToWindow(const std::string& name) {
+ int switch_to_id = 0;
+ int name_no = 0;
+ if (base::StringToInt(name, &name_no)) {
+ bool does_exist = false;
+ RunSessionTask(NewRunnableMethod(
+ automation_.get(),
+ &Automation::DoesTabExist,
+ name_no,
+ &does_exist));
+ if (does_exist)
+ switch_to_id = name_no;
+ }
+
+ if (!switch_to_id) {
+ std::vector<int> window_ids;
+ GetWindowIds(&window_ids);
+ // See if any of the window names match |name|.
+ for (size_t i = 0; i < window_ids.size(); ++i) {
+ ListValue empty_list;
+ Value* unscoped_name_value;
+ std::string window_name;
+ ErrorCode code = ExecuteScript(window_ids[i],
+ "",
+ "return window.name;",
+ &empty_list,
+ &unscoped_name_value);
+ scoped_ptr<Value> name_value(unscoped_name_value);
+ if (code == kSuccess &&
+ name_value->GetAsString(&window_name) &&
+ name == window_name) {
+ switch_to_id = window_ids[i];
+ break;
+ }
+ }
+ }
+
+ if (!switch_to_id)
+ return kNoSuchWindow;
+ current_window_id_ = switch_to_id;
+ current_frame_xpath_ = "";
+ return kSuccess;
+}
+
+ErrorCode Session::SwitchToFrameWithNameOrId(const std::string& name_or_id) {
+ std::string script =
+ "var arg = arguments[0];"
+ "var xpath = '(/html/body//iframe|/html/frameset/frame)';"
+ "var sub = function(s) { return s.replace(/\\$/g, arg); };"
+ "xpath += sub('[@name=\"$\" or @id=\"$\"]');"
+ "var frame = document.evaluate(xpath, document, null, "
+ " XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
+ "if (!frame) { return null; }"
+ "xpath = frame.tagName == 'IFRAME' ? '/html/body//iframe'"
+ " : '/html/frameset/frame';"
+ "return xpath + sub('[@' + (frame.id == arg ? 'id' : 'name')"
+ " + '=\"$\"]');";
+ ListValue args;
+ args.Append(new StringValue(name_or_id));
+ return SwitchToFrameWithJavaScriptLocatedFrame(script, &args);
+}
+
+ErrorCode Session::SwitchToFrameWithIndex(int index) {
+ // We cannot simply index into window.frames because we need to know the
+ // tagName of the frameElement. If child frame N is from another domain, then
+ // the following will run afoul of the same origin policy:
+ // window.frames[N].frameElement;
+ // Instead of indexing window.frames, we use a an XPath expression to index
+ // into the list of all IFRAME and FRAME elements on the page - if we find
+ // something, then that XPath expression can be used as the new frame's XPath.
+ std::string script =
+ "var index = '[' + (arguments[0] + 1) + ']';"
+ "var xpath = '(/html/body//iframe|/html/frameset/frame)' + "
+ " index;"
+ "console.info('searching for frame by xpath: ' + xpath);"
+ "var frame = document.evaluate(xpath, document, null, "
+ "XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
+ "console.info(frame == null ? 'found nothing' : frame);"
+ "return frame == null ? null : ((frame.tagName == 'IFRAME' ? "
+ " '/html/body//iframe' : '/html/frameset/frame') + index);";
+ ListValue args;
+ args.Append(Value::CreateIntegerValue(index));
+ return SwitchToFrameWithJavaScriptLocatedFrame(script, &args);
+}
+
+bool Session::CloseWindow() {
+ bool success = false;
+ RunSessionTask(NewRunnableMethod(
+ automation_.get(),
+ &Automation::CloseTab,
+ current_window_id_,
+ &success));
+
+ if (success) {
+ std::vector<int> window_ids;
+ if (!GetWindowIds(&window_ids) || window_ids.empty()) {
+ // The automation connection will soon be closed, if not already,
+ // because we supposedly just closed the last window. Terminate the
+ // session.
+ // TODO(kkania): This will cause us problems if GetWindowIds fails for a
+ // reason other than the channel is disconnected. Look into having
+ // |GetWindowIds| tell us if it just closed the last window.
+ Terminate();
+ }
+ }
+ return success;
+}
+
void Session::RunSessionTask(Task* task) {
base::WaitableEvent done_event(false, false);
thread_.message_loop_proxy()->PostTask(FROM_HERE, NewRunnableMethod(
@@ -286,10 +438,26 @@ void Session::RunSessionTaskOnSessionThread(Task* task,
void Session::InitOnSessionThread(bool* success) {
automation_.reset(new Automation());
automation_->Init(success);
+ if (!*success)
+ return;
+
+ std::vector<int> tab_ids;
+ automation_->GetTabIds(&tab_ids, success);
+ if (!*success) {
+ LOG(ERROR) << "Could not get tab ids";
+ return;
+ }
+ if (tab_ids.empty()) {
+ LOG(ERROR) << "No tab ids after initialization";
+ *success = false;
+ } else {
+ current_window_id_ = tab_ids[0];
+ }
}
void Session::TerminateOnSessionThread() {
- automation_->Terminate();
+ if (automation_.get())
+ automation_->Terminate();
automation_.reset();
}
@@ -300,7 +468,8 @@ void Session::SendKeysOnSessionThread(const string16& keys,
ConvertKeysToWebKeyEvents(keys, &key_events);
for (size_t i = 0; i < key_events.size(); ++i) {
bool key_success = false;
- automation_->SendWebKeyEvent(key_events[i], &key_success);
+ automation_->SendWebKeyEvent(
+ current_window_id_, key_events[i], &key_success);
if (!key_success) {
LOG(ERROR) << "Failed to send key event. Event details:\n"
<< "Type: " << key_events[i].type << "\n"
@@ -313,4 +482,22 @@ void Session::SendKeysOnSessionThread(const string16& keys,
}
}
+ErrorCode Session::SwitchToFrameWithJavaScriptLocatedFrame(
+ const std::string& script,
+ ListValue* args) {
+ Value* unscoped_result = NULL;
+ ErrorCode code = ExecuteScript(script, args, &unscoped_result);
+ scoped_ptr<Value> result(unscoped_result);
+ if (code != kSuccess)
+ return code;
+ std::string xpath;
+ if (result->GetAsString(&xpath)) {
+ if (current_frame_xpath_.length())
+ current_frame_xpath_ += "\n";
+ current_frame_xpath_ += xpath;
+ return kSuccess;
+ }
+ return kNoSuchFrame;
+}
+
} // namespace webdriver
diff --git a/chrome/test/webdriver/session.h b/chrome/test/webdriver/session.h
index 8e813d4..99c8f71 100644
--- a/chrome/test/webdriver/session.h
+++ b/chrome/test/webdriver/session.h
@@ -5,6 +5,7 @@
#ifndef CHROME_TEST_WEBDRIVER_SESSION_H_
#define CHROME_TEST_WEBDRIVER_SESSION_H_
+#include <map>
#include <string>
#include "base/scoped_ptr.h"
@@ -25,25 +26,36 @@ namespace webdriver {
// Every connection made by WebDriver maps to a session object.
// This object creates the chrome instance and keeps track of the
// state necessary to control the chrome browser created.
+// A session manages its own lifetime.
// TODO(phajdan.jr): Abstract UITestBase classes, see:
// http://code.google.com/p/chromium/issues/detail?id=56865
class Session {
public:
- explicit Session(const std::string& id);
+ // Adds this |Session| to the |SessionManager|. The session manages its own
+ // lifetime. Do not call delete.
+ Session();
+ // Removes this |Session| from the |SessionManager|.
~Session();
- // Creates a browser.
+ // Starts the session thread and a new browser. Returns true on
+ // success. On failure, the session will delete itself and return false.
bool Init();
- // Terminates this session and disconnects its automation proxy. After
- // invoking this method, the Session can safely be deleted.
+ // Terminates this session and deletes itself.
void Terminate();
- // Executes the given |script| in the context of the frame that is currently
- // the focus of this session. The |script| should be in the form of a
- // function body (e.g. "return arguments[0]"), where |args| is the list of
- // arguments to pass to the function. The caller is responsible for the
- // script result |value|.
+ // Executes the given |script| in the context of the given window and frame.
+ // The |script| should be in the form of a function body
+ // (e.g. "return arguments[0]"), where |args| is the list of arguments to
+ // pass to the function. The caller is responsible for the script result
+ // |value|.
+ ErrorCode ExecuteScript(int window_id,
+ const std::string& frame_xpath,
+ const std::string& script,
+ const ListValue* const args,
+ Value** value);
+
+ // Same as above, but uses the currently targeted window and frame.
ErrorCode ExecuteScript(const std::string& script,
const ListValue* const args,
Value** value);
@@ -65,6 +77,25 @@ class Session {
bool DeleteCookie(const GURL& url, const std::string& cookie_name);
bool SetCookie(const GURL& url, const std::string& cookie);
+ // Gets all the currently existing window IDs. Returns true on success.
+ bool GetWindowIds(std::vector<int>* window_ids);
+
+ // Switches the window used by default. |name| is either an ID returned by
+ // |GetWindowIds| or the name attribute of a DOM window.
+ ErrorCode SwitchToWindow(const std::string& name);
+
+ // Switches the frame used by default. |name_or_id| is either the name or id
+ // of a frame element.
+ ErrorCode SwitchToFrameWithNameOrId(const std::string& name_or_id);
+
+ // Switches the frame used by default. |index| is the zero-based frame index.
+ ErrorCode SwitchToFrameWithIndex(int index);
+
+ // Closes the current window. Returns true on success.
+ // Note: The session will be deleted if this closes the last window in the
+ // session.
+ bool CloseWindow();
+
inline const std::string& id() const { return id_; }
inline int implicit_wait() { return implicit_wait_; }
@@ -86,6 +117,8 @@ class Session {
current_frame_xpath_ = xpath;
}
+ inline int current_window_id() const { return current_window_id_; }
+
private:
void RunSessionTask(Task* task);
void RunSessionTaskOnSessionThread(
@@ -94,13 +127,14 @@ class Session {
void InitOnSessionThread(bool* success);
void TerminateOnSessionThread();
void SendKeysOnSessionThread(const string16& keys, bool* success);
-
- scoped_ptr<Automation> automation_;
- base::Thread thread_;
+ ErrorCode SwitchToFrameWithJavaScriptLocatedFrame(
+ const std::string& script,
+ ListValue* args);
const std::string id_;
- int window_num_;
+ scoped_ptr<Automation> automation_;
+ base::Thread thread_;
int implicit_wait_;
Speed speed_;
@@ -112,6 +146,7 @@ class Session {
// should break into 2 xpaths
// /html/body/table/tbody/tr/td/iframe & /frameset/frame[1].
std::string current_frame_xpath_;
+ int current_window_id_;
DISALLOW_COPY_AND_ASSIGN(Session);
};
diff --git a/chrome/test/webdriver/session_manager.cc b/chrome/test/webdriver/session_manager.cc
index ed9a113..8c52fa2 100644
--- a/chrome/test/webdriver/session_manager.cc
+++ b/chrome/test/webdriver/session_manager.cc
@@ -30,20 +30,9 @@ std::string SessionManager::GetAddress() {
return hostname + ":" + port_;
}
-Session* SessionManager::Create() {
- std::string id = GenerateRandomID();
- {
- base::AutoLock lock(map_lock_);
- if (map_.find(id) != map_.end()) {
- LOG(ERROR) << "Failed to generate a unique session ID";
- return NULL;
- }
- }
-
- Session* session = new Session(id);
+void SessionManager::Add(Session* session) {
base::AutoLock lock(map_lock_);
- map_[id] = session;
- return session;
+ map_[session->id()] = session;
}
bool SessionManager::Has(const std::string& id) const {
@@ -51,23 +40,17 @@ bool SessionManager::Has(const std::string& id) const {
return map_.find(id) != map_.end();
}
-bool SessionManager::Delete(const std::string& id) {
+bool SessionManager::Remove(const std::string& id) {
std::map<std::string, Session*>::iterator it;
-
Session* session;
- {
- base::AutoLock lock(map_lock_);
- it = map_.find(id);
- if (it == map_.end()) {
- VLOG(1) << "No such session with ID " << id;
- return false;
- }
- session = it->second;
- map_.erase(it);
+ base::AutoLock lock(map_lock_);
+ it = map_.find(id);
+ if (it == map_.end()) {
+ VLOG(1) << "No such session with ID " << id;
+ return false;
}
-
- VLOG(1) << "Deleting session with ID " << id;
- delete session;
+ session = it->second;
+ map_.erase(it);
return true;
}
diff --git a/chrome/test/webdriver/session_manager.h b/chrome/test/webdriver/session_manager.h
index 1096d83..5742e3a 100644
--- a/chrome/test/webdriver/session_manager.h
+++ b/chrome/test/webdriver/session_manager.h
@@ -26,8 +26,8 @@ class SessionManager {
std::string GetAddress();
- Session* Create();
- bool Delete(const std::string& id);
+ void Add(Session* session);
+ bool Remove(const std::string& id);
bool Has(const std::string& id) const;
Session* GetSession(const std::string& id) const;