Index: chrome/test/chromedriver/window_commands.cc |
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc |
index d1a4263062575c0007daa8b6d29010cc7bac8a0b..0ea9014511de33e706b6efc0cff44c9568de39fd 100644 |
--- a/chrome/test/chromedriver/window_commands.cc |
+++ b/chrome/test/chromedriver/window_commands.cc |
@@ -29,6 +29,7 @@ |
#include "chrome/test/chromedriver/chrome/ui_events.h" |
#include "chrome/test/chromedriver/chrome/web_view.h" |
#include "chrome/test/chromedriver/element_util.h" |
+#include "chrome/test/chromedriver/net/timeout.h" |
#include "chrome/test/chromedriver/session.h" |
#include "chrome/test/chromedriver/util.h" |
@@ -202,6 +203,7 @@ Status ExecuteWindowCommand(const WindowCommand& command, |
Session* session, |
const base::DictionaryValue& params, |
std::unique_ptr<base::Value>* value) { |
+ Timeout timeout; |
WebView* web_view = NULL; |
Status status = session->GetTargetWindow(&web_view); |
if (status.IsError()) |
@@ -232,19 +234,22 @@ Status ExecuteWindowCommand(const WindowCommand& command, |
} |
nav_status = web_view->WaitForPendingNavigations( |
- session->GetCurrentFrameId(), session->page_load_timeout, true); |
+ session->GetCurrentFrameId(), |
+ Timeout(session->page_load_timeout, &timeout), true); |
if (nav_status.IsError()) |
return nav_status; |
- status = command.Run(session, web_view, params, value); |
- if (status.code() == kNoSuchExecutionContext) { |
+ status = command.Run(session, web_view, params, value, &timeout); |
+ if (status.code() == kNoSuchExecutionContext || status.code() == kTimeout) { |
+ // If the command timed out, let WaitForPendingNavigations cancel |
+ // the navigation if there is one. |
continue; |
} else if (status.IsError()) { |
// If the command failed while a new page or frame started loading, retry |
// the command after the pending navigation has completed. |
bool is_pending = false; |
nav_status = web_view->IsPendingNavigation(session->GetCurrentFrameId(), |
- &is_pending); |
+ &timeout, &is_pending); |
if (nav_status.IsError()) |
return nav_status; |
else if (is_pending) |
@@ -254,7 +259,8 @@ Status ExecuteWindowCommand(const WindowCommand& command, |
} |
nav_status = web_view->WaitForPendingNavigations( |
- session->GetCurrentFrameId(), session->page_load_timeout, true); |
+ session->GetCurrentFrameId(), |
+ Timeout(session->page_load_timeout, &timeout), true); |
if (status.IsOk() && nav_status.IsError() && |
nav_status.code() != kUnexpectedAlertOpen) |
@@ -267,11 +273,13 @@ Status ExecuteWindowCommand(const WindowCommand& command, |
Status ExecuteGet(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
+ timeout->SetDuration(session->page_load_timeout); |
std::string url; |
if (!params.GetString("url", &url)) |
return Status(kUnknownError, "'url' must be a string"); |
- Status status = web_view->Load(url); |
+ Status status = web_view->Load(url, timeout); |
if (status.IsError()) |
return status; |
session->SwitchToTopFrame(); |
@@ -281,7 +289,8 @@ Status ExecuteGet(Session* session, |
Status ExecuteExecuteScript(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
std::string script; |
if (!params.GetString("script", &script)) |
return Status(kUnknownError, "'script' must be a string"); |
@@ -304,7 +313,8 @@ Status ExecuteExecuteScript(Session* session, |
Status ExecuteExecuteAsyncScript(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
std::string script; |
if (!params.GetString("script", &script)) |
return Status(kUnknownError, "'script' must be a string"); |
@@ -320,7 +330,8 @@ Status ExecuteExecuteAsyncScript(Session* session, |
Status ExecuteSwitchToFrame(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
const base::Value* id; |
if (!params.Get("id", &id)) |
return Status(kUnknownError, "missing 'id'"); |
@@ -390,7 +401,8 @@ Status ExecuteSwitchToFrame(Session* session, |
Status ExecuteSwitchToParentFrame(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
session->SwitchToParentFrame(); |
return Status(kOk); |
} |
@@ -398,7 +410,8 @@ Status ExecuteSwitchToParentFrame(Session* session, |
Status ExecuteGetTitle(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
const char kGetTitleScript[] = "function() { return document.title;}"; |
base::ListValue args; |
return web_view->CallFunction(std::string(), kGetTitleScript, args, value); |
@@ -407,7 +420,8 @@ Status ExecuteGetTitle(Session* session, |
Status ExecuteGetPageSource(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
const char kGetPageSource[] = |
"function() {" |
" return new XMLSerializer().serializeToString(document);" |
@@ -421,7 +435,8 @@ Status ExecuteFindElement(int interval_ms, |
Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
return FindElement(interval_ms, true, NULL, session, web_view, params, value); |
} |
@@ -429,7 +444,8 @@ Status ExecuteFindElements(int interval_ms, |
Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
return FindElement( |
interval_ms, false, NULL, session, web_view, params, value); |
} |
@@ -437,7 +453,8 @@ Status ExecuteFindElements(int interval_ms, |
Status ExecuteGetCurrentUrl(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
std::string url; |
Status status = GetUrl(web_view, std::string(), &url); |
if (status.IsError()) |
@@ -463,7 +480,8 @@ Status ExecuteGetCurrentUrl(Session* session, |
Status ExecuteGoBack(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
Status status = web_view->TraverseHistory(-1); |
if (status.IsError()) |
return status; |
@@ -474,7 +492,8 @@ Status ExecuteGoBack(Session* session, |
Status ExecuteGoForward(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
Status status = web_view->TraverseHistory(1); |
if (status.IsError()) |
return status; |
@@ -485,7 +504,8 @@ Status ExecuteGoForward(Session* session, |
Status ExecuteRefresh(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
Status status = web_view->Reload(); |
if (status.IsError()) |
return status; |
@@ -496,7 +516,8 @@ Status ExecuteRefresh(Session* session, |
Status ExecuteMouseMoveTo(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
std::string element_id; |
bool has_element = params.GetString("element", &element_id); |
int x_offset = 0; |
@@ -533,7 +554,8 @@ Status ExecuteMouseMoveTo(Session* session, |
Status ExecuteMouseClick(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
MouseButton button; |
Status status = GetMouseButton(params, &button); |
if (status.IsError()) |
@@ -553,7 +575,8 @@ Status ExecuteMouseClick(Session* session, |
Status ExecuteMouseButtonDown(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
MouseButton button; |
Status status = GetMouseButton(params, &button); |
if (status.IsError()) |
@@ -569,7 +592,8 @@ Status ExecuteMouseButtonDown(Session* session, |
Status ExecuteMouseButtonUp(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
MouseButton button; |
Status status = GetMouseButton(params, &button); |
if (status.IsError()) |
@@ -585,7 +609,8 @@ Status ExecuteMouseButtonUp(Session* session, |
Status ExecuteMouseDoubleClick(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
MouseButton button; |
Status status = GetMouseButton(params, &button); |
if (status.IsError()) |
@@ -605,28 +630,32 @@ Status ExecuteMouseDoubleClick(Session* session, |
Status ExecuteTouchDown(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
return ExecuteTouchEvent(session, web_view, kTouchStart, params); |
} |
Status ExecuteTouchUp(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
return ExecuteTouchEvent(session, web_view, kTouchEnd, params); |
} |
Status ExecuteTouchMove(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
return ExecuteTouchEvent(session, web_view, kTouchMove, params); |
} |
Status ExecuteTouchScroll(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
if (session->chrome->GetBrowserInfo()->build_no < 2286) { |
// TODO(samuong): remove this once we stop supporting M41. |
return Status(kUnknownCommand, "Touch scroll action requires Chrome 42+"); |
@@ -652,7 +681,8 @@ Status ExecuteTouchScroll(Session* session, |
Status ExecuteTouchPinch(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
if (session->chrome->GetBrowserInfo()->build_no < 2286) { |
// TODO(samuong): remove this once we stop supporting M41. |
return Status(kUnknownCommand, "Pinch action requires Chrome 42+"); |
@@ -671,14 +701,16 @@ Status ExecuteTouchPinch(Session* session, |
Status ExecuteGetActiveElement(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
return GetActiveElement(session, web_view, value); |
} |
Status ExecuteSendKeysToActiveElement(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
const base::ListValue* key_list; |
if (!params.GetList("value", &key_list)) |
return Status(kUnknownError, "'value' must be a list"); |
@@ -689,7 +721,8 @@ Status ExecuteSendKeysToActiveElement(Session* session, |
Status ExecuteGetAppCacheStatus(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
return web_view->EvaluateScript( |
session->GetCurrentFrameId(), |
"applicationCache.status", |
@@ -699,7 +732,8 @@ Status ExecuteGetAppCacheStatus(Session* session, |
Status ExecuteIsBrowserOnline(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
return web_view->EvaluateScript( |
session->GetCurrentFrameId(), |
"navigator.onLine", |
@@ -710,7 +744,8 @@ Status ExecuteGetStorageItem(const char* storage, |
Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
std::string key; |
if (!params.GetString("key", &key)) |
return Status(kUnknownError, "'key' must be a string"); |
@@ -727,7 +762,8 @@ Status ExecuteGetStorageKeys(const char* storage, |
Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
const char script[] = |
"var keys = [];" |
"for (var key in %s) {" |
@@ -744,7 +780,8 @@ Status ExecuteSetStorageItem(const char* storage, |
Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
std::string key; |
if (!params.GetString("key", &key)) |
return Status(kUnknownError, "'key' must be a string"); |
@@ -765,7 +802,8 @@ Status ExecuteRemoveStorageItem(const char* storage, |
Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
std::string key; |
if (!params.GetString("key", &key)) |
return Status(kUnknownError, "'key' must be a string"); |
@@ -782,7 +820,8 @@ Status ExecuteClearStorage(const char* storage, |
Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
return web_view->EvaluateScript( |
session->GetCurrentFrameId(), |
base::StringPrintf("%s.clear()", storage), |
@@ -793,7 +832,8 @@ Status ExecuteGetStorageSize(const char* storage, |
Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
return web_view->EvaluateScript( |
session->GetCurrentFrameId(), |
base::StringPrintf("%s.length", storage), |
@@ -803,7 +843,8 @@ Status ExecuteGetStorageSize(const char* storage, |
Status ExecuteScreenshot(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
Status status = session->chrome->ActivateWebView(web_view->GetId()); |
if (status.IsError()) |
return status; |
@@ -834,7 +875,8 @@ Status ExecuteScreenshot(Session* session, |
Status ExecuteGetCookies(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
std::list<Cookie> cookies; |
Status status = GetVisibleCookies(web_view, &cookies); |
if (status.IsError()) |
@@ -851,7 +893,8 @@ Status ExecuteGetCookies(Session* session, |
Status ExecuteAddCookie(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
const base::DictionaryValue* cookie; |
if (!params.GetDictionary("cookie", &cookie)) |
return Status(kUnknownError, "missing 'cookie'"); |
@@ -865,7 +908,8 @@ Status ExecuteAddCookie(Session* session, |
Status ExecuteDeleteCookie(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
std::string name; |
if (!params.GetString("name", &name)) |
return Status(kUnknownError, "missing 'name'"); |
@@ -881,7 +925,8 @@ Status ExecuteDeleteCookie(Session* session, |
Status ExecuteDeleteAllCookies(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
std::list<Cookie> cookies; |
Status status = GetVisibleCookies(web_view, &cookies); |
if (status.IsError()) |
@@ -908,7 +953,8 @@ Status ExecuteDeleteAllCookies(Session* session, |
Status ExecuteSetLocation(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
const base::DictionaryValue* location = NULL; |
Geoposition geoposition; |
if (!params.GetDictionary("location", &location) || |
@@ -933,7 +979,8 @@ Status ExecuteSetLocation(Session* session, |
Status ExecuteSetNetworkConditions(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
std::string network_name; |
const base::DictionaryValue* conditions = NULL; |
std::unique_ptr<NetworkConditions> network_conditions( |
@@ -993,7 +1040,8 @@ Status ExecuteSetNetworkConditions(Session* session, |
Status ExecuteDeleteNetworkConditions(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
// Chrome does not have any command to stop overriding network conditions, so |
// we just override the network conditions with the "No throttling" preset. |
NetworkConditions network_conditions; |
@@ -1015,6 +1063,7 @@ Status ExecuteDeleteNetworkConditions(Session* session, |
Status ExecuteTakeHeapSnapshot(Session* session, |
WebView* web_view, |
const base::DictionaryValue& params, |
- std::unique_ptr<base::Value>* value) { |
+ std::unique_ptr<base::Value>* value, |
+ Timeout* timeout) { |
return web_view->TakeHeapSnapshot(value); |
} |