Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: chrome/test/webdriver/session.cc

Issue 6507015: Implement the target locator commands for ChromeDriver. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/test/webdriver/session.h ('k') | chrome/test/webdriver/session_manager.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/test/webdriver/session_manager.h" 5 #include "chrome/test/webdriver/session_manager.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/message_loop_proxy.h" 12 #include "base/message_loop_proxy.h"
13 #include "base/process.h" 13 #include "base/process.h"
14 #include "base/process_util.h" 14 #include "base/process_util.h"
15 #include "base/scoped_ptr.h"
15 #include "base/stringprintf.h" 16 #include "base/stringprintf.h"
17 #include "base/string_number_conversions.h"
16 #include "base/string_util.h" 18 #include "base/string_util.h"
17 #include "base/json/json_reader.h" 19 #include "base/json/json_reader.h"
18 #include "base/json/json_writer.h" 20 #include "base/json/json_writer.h"
19 #include "base/test/test_timeouts.h" 21 #include "base/test/test_timeouts.h"
20 #include "base/utf_string_conversions.h" 22 #include "base/utf_string_conversions.h"
21 #include "chrome/app/chrome_command_ids.h" 23 #include "chrome/app/chrome_command_ids.h"
22 #include "chrome/common/chrome_constants.h" 24 #include "chrome/common/chrome_constants.h"
23 #include "chrome/common/chrome_switches.h" 25 #include "chrome/common/chrome_switches.h"
24 #include "chrome/test/test_launcher_utils.h" 26 #include "chrome/test/test_launcher_utils.h"
27 #include "chrome/test/webdriver/session_manager.h"
25 #include "chrome/test/webdriver/utility_functions.h" 28 #include "chrome/test/webdriver/utility_functions.h"
26 #include "chrome/test/webdriver/webdriver_key_converter.h" 29 #include "chrome/test/webdriver/webdriver_key_converter.h"
27 #include "googleurl/src/gurl.h" 30 #include "googleurl/src/gurl.h"
28 #include "third_party/webdriver/atoms.h" 31 #include "third_party/webdriver/atoms.h"
29 32
30 namespace webdriver { 33 namespace webdriver {
31 34
32 Session::Session(const std::string& id) 35 Session::Session()
33 : thread_(id.c_str()), 36 : id_(GenerateRandomID()),
34 id_(id), 37 thread_(id_.c_str()),
35 window_num_(0),
36 implicit_wait_(0), 38 implicit_wait_(0),
37 current_frame_xpath_("") { 39 current_frame_xpath_(""),
40 current_window_id_(0) {
41 SessionManager::GetInstance()->Add(this);
38 } 42 }
39 43
40 Session::~Session() {} 44 Session::~Session() {
45 SessionManager::GetInstance()->Remove(id_);
46 }
41 47
42 bool Session::Init() { 48 bool Session::Init() {
43 if (!thread_.Start()) { 49 bool success = false;
50 if (thread_.Start()) {
51 RunSessionTask(NewRunnableMethod(
52 this,
53 &Session::InitOnSessionThread,
54 &success));
55 } else {
44 LOG(ERROR) << "Cannot start session thread"; 56 LOG(ERROR) << "Cannot start session thread";
45 return false;
46 } 57 }
47 58 if (!success)
48 bool success = false; 59 delete this;
49 RunSessionTask(NewRunnableMethod(
50 this,
51 &Session::InitOnSessionThread,
52 &success));
53 return success; 60 return success;
54 } 61 }
55 62
56 void Session::Terminate() { 63 void Session::Terminate() {
57 RunSessionTask(NewRunnableMethod( 64 RunSessionTask(NewRunnableMethod(
58 this, 65 this,
59 &Session::TerminateOnSessionThread)); 66 &Session::TerminateOnSessionThread));
67 delete this;
60 } 68 }
61 69
62 ErrorCode Session::ExecuteScript(const std::string& script, 70 ErrorCode Session::ExecuteScript(int window_id,
71 const std::string& frame_xpath,
72 const std::string& script,
63 const ListValue* const args, 73 const ListValue* const args,
64 Value** value) { 74 Value** value) {
65 std::string args_as_json; 75 std::string args_as_json;
66 base::JSONWriter::Write(static_cast<const Value* const>(args), 76 base::JSONWriter::Write(static_cast<const Value* const>(args),
67 /*pretty_print=*/false, 77 /*pretty_print=*/false,
68 &args_as_json); 78 &args_as_json);
69 79
70 // Every injected script is fed through the executeScript atom. This atom 80 // Every injected script is fed through the executeScript atom. This atom
71 // will catch any errors that are thrown and convert them to the 81 // will catch any errors that are thrown and convert them to the
72 // appropriate JSON structure. 82 // appropriate JSON structure.
73 std::string jscript = base::StringPrintf( 83 std::string jscript = base::StringPrintf(
74 "window.domAutomationController.send((%s).apply(null," 84 "window.domAutomationController.send((%s).apply(null,"
75 "[function(){%s\n},%s,true]));", 85 "[function(){%s\n},%s,true]));",
76 atoms::EXECUTE_SCRIPT, script.c_str(), args_as_json.c_str()); 86 atoms::EXECUTE_SCRIPT, script.c_str(), args_as_json.c_str());
77 87
78 // Should we also log the script that's being executed? It could be several KB 88 // Should we also log the script that's being executed? It could be several KB
79 // in size and will add lots of noise to the logs. 89 // in size and will add lots of noise to the logs.
80 VLOG(1) << "Executing script in frame: " << current_frame_xpath_; 90 VLOG(1) << "Executing script in frame: " << current_frame_xpath_;
81 91
82 std::string result; 92 std::string result;
83 bool success; 93 bool success = false;
84 RunSessionTask(NewRunnableMethod( 94 RunSessionTask(NewRunnableMethod(
85 automation_.get(), 95 automation_.get(),
86 &Automation::ExecuteScript, 96 &Automation::ExecuteScript,
87 current_frame_xpath_, 97 window_id,
98 frame_xpath,
88 jscript, 99 jscript,
89 &result, 100 &result,
90 &success)); 101 &success));
91 if (!success) { 102 if (!success) {
103 LOG(ERROR) << "Automation failed to execute script";
92 *value = Value::CreateStringValue( 104 *value = Value::CreateStringValue(
93 "Unknown internal script execution failure"); 105 "Unknown internal script execution failure");
94 return kUnknownError; 106 return kUnknownError;
95 } 107 }
96 108
97 VLOG(1) << "...script result: " << result; 109 VLOG(1) << "...script result: " << result;
98 scoped_ptr<Value> r(base::JSONReader::ReadAndReturnError( 110 scoped_ptr<Value> r(base::JSONReader::ReadAndReturnError(
99 result, true, NULL, NULL)); 111 result, true, NULL, NULL));
100 if (!r.get()) { 112 if (!r.get()) {
113 LOG(ERROR) << "Failed to parse script result";
101 *value = Value::CreateStringValue( 114 *value = Value::CreateStringValue(
102 "Internal script execution error: failed to parse script result"); 115 "Internal script execution error: failed to parse script result");
103 return kUnknownError; 116 return kUnknownError;
104 } 117 }
105 118
106 if (r->GetType() != Value::TYPE_DICTIONARY) { 119 if (r->GetType() != Value::TYPE_DICTIONARY) {
120 LOG(ERROR) << "Execute script returned non-dictionary type";
107 std::ostringstream stream; 121 std::ostringstream stream;
108 stream << "Internal script execution error: script result must be a " 122 stream << "Internal script execution error: script result must be a "
109 << print_valuetype(Value::TYPE_DICTIONARY) << ", but was " 123 << print_valuetype(Value::TYPE_DICTIONARY) << ", but was "
110 << print_valuetype(r->GetType()) << ": " << result; 124 << print_valuetype(r->GetType()) << ": " << result;
111 *value = Value::CreateStringValue(stream.str()); 125 *value = Value::CreateStringValue(stream.str());
112 return kUnknownError; 126 return kUnknownError;
113 } 127 }
114 128
115 DictionaryValue* result_dict = static_cast<DictionaryValue*>(r.get()); 129 DictionaryValue* result_dict = static_cast<DictionaryValue*>(r.get());
116 130
117 Value* tmp; 131 Value* tmp;
118 if (result_dict->Get("value", &tmp)) { 132 if (result_dict->Get("value", &tmp)) {
119 // result_dict owns the returned value, so we need to make a copy. 133 // result_dict owns the returned value, so we need to make a copy.
120 *value = tmp->DeepCopy(); 134 *value = tmp->DeepCopy();
121 } else { 135 } else {
122 // "value" was not defined in the returned dictionary, set to null. 136 // "value" was not defined in the returned dictionary, set to null.
123 *value = Value::CreateNullValue(); 137 *value = Value::CreateNullValue();
124 } 138 }
125 139
126 int status; 140 int status;
127 if (!result_dict->GetInteger("status", &status)) { 141 if (!result_dict->GetInteger("status", &status)) {
128 NOTREACHED() << "...script did not return a status flag."; 142 NOTREACHED() << "...script did not return a status flag.";
129 } 143 }
130 return static_cast<ErrorCode>(status); 144 return static_cast<ErrorCode>(status);
131 } 145 }
132 146
147 ErrorCode Session::ExecuteScript(const std::string& script,
148 const ListValue* const args,
149 Value** value) {
150 return ExecuteScript(
151 current_window_id_, current_frame_xpath_, script, args, value);
152 }
153
133 ErrorCode Session::SendKeys(DictionaryValue* element, const string16& keys) { 154 ErrorCode Session::SendKeys(DictionaryValue* element, const string16& keys) {
134 ListValue args; 155 ListValue args;
135 args.Append(element); 156 args.Append(element);
136 // TODO(jleyba): Update this to use the correct atom. 157 // TODO(jleyba): Update this to use the correct atom.
137 std::string script = "document.activeElement.blur();arguments[0].focus();"; 158 std::string script = "document.activeElement.blur();arguments[0].focus();";
138 Value* unscoped_result = NULL; 159 Value* unscoped_result = NULL;
139 ErrorCode code = ExecuteScript(script, &args, &unscoped_result); 160 ErrorCode code = ExecuteScript(script, &args, &unscoped_result);
140 scoped_ptr<Value> result(unscoped_result); 161 scoped_ptr<Value> result(unscoped_result);
141 if (code != kSuccess) 162 if (code != kSuccess) {
163 LOG(ERROR) << "Failed to focus element before sending keys";
142 return code; 164 return code;
165 }
143 166
144 bool success = false; 167 bool success = false;
145 RunSessionTask(NewRunnableMethod( 168 RunSessionTask(NewRunnableMethod(
146 this, 169 this,
147 &Session::SendKeysOnSessionThread, 170 &Session::SendKeysOnSessionThread,
148 keys, 171 keys,
149 &success)); 172 &success));
150 if (!success) 173 if (!success)
151 return kUnknownError; 174 return kUnknownError;
152 return kSuccess; 175 return kSuccess;
153 } 176 }
154 177
155 bool Session::NavigateToURL(const std::string& url) { 178 bool Session::NavigateToURL(const std::string& url) {
156 bool success = false; 179 bool success = false;
157 RunSessionTask(NewRunnableMethod( 180 RunSessionTask(NewRunnableMethod(
158 automation_.get(), 181 automation_.get(),
159 &Automation::NavigateToURL, 182 &Automation::NavigateToURL,
183 current_window_id_,
160 url, 184 url,
161 &success)); 185 &success));
162 return success; 186 return success;
163 } 187 }
164 188
165 bool Session::GoForward() { 189 bool Session::GoForward() {
166 bool success = false; 190 bool success = false;
167 RunSessionTask(NewRunnableMethod( 191 RunSessionTask(NewRunnableMethod(
168 automation_.get(), 192 automation_.get(),
169 &Automation::GoForward, 193 &Automation::GoForward,
194 current_window_id_,
170 &success)); 195 &success));
171 return success; 196 return success;
172 } 197 }
173 198
174 bool Session::GoBack() { 199 bool Session::GoBack() {
175 bool success = false; 200 bool success = false;
176 RunSessionTask(NewRunnableMethod( 201 RunSessionTask(NewRunnableMethod(
177 automation_.get(), 202 automation_.get(),
178 &Automation::GoBack, 203 &Automation::GoBack,
204 current_window_id_,
179 &success)); 205 &success));
180 return success; 206 return success;
181 } 207 }
182 208
183 bool Session::Reload() { 209 bool Session::Reload() {
184 bool success = false; 210 bool success = false;
185 RunSessionTask(NewRunnableMethod( 211 RunSessionTask(NewRunnableMethod(
186 automation_.get(), 212 automation_.get(),
187 &Automation::Reload, 213 &Automation::Reload,
214 current_window_id_,
188 &success)); 215 &success));
189 return success; 216 return success;
190 } 217 }
191 218
192 bool Session::GetURL(std::string* url) { 219 bool Session::GetURL(std::string* url) {
193 bool success = false; 220 bool success = false;
194 RunSessionTask(NewRunnableMethod( 221 RunSessionTask(NewRunnableMethod(
195 automation_.get(), 222 automation_.get(),
196 &Automation::GetURL, 223 &Automation::GetURL,
224 current_window_id_,
197 url, 225 url,
198 &success)); 226 &success));
199 return success; 227 return success;
200 } 228 }
201 229
202 bool Session::GetURL(GURL* gurl) { 230 bool Session::GetURL(GURL* gurl) {
203 bool success = false; 231 bool success = false;
204 RunSessionTask(NewRunnableMethod( 232 RunSessionTask(NewRunnableMethod(
205 automation_.get(), 233 automation_.get(),
206 &Automation::GetGURL, 234 &Automation::GetGURL,
235 current_window_id_,
207 gurl, 236 gurl,
208 &success)); 237 &success));
209 return success; 238 return success;
210 } 239 }
211 240
212 bool Session::GetTabTitle(std::string* tab_title) { 241 bool Session::GetTabTitle(std::string* tab_title) {
213 bool success = false; 242 bool success = false;
214 RunSessionTask(NewRunnableMethod( 243 RunSessionTask(NewRunnableMethod(
215 automation_.get(), 244 automation_.get(),
216 &Automation::GetTabTitle, 245 &Automation::GetTabTitle,
246 current_window_id_,
217 tab_title, 247 tab_title,
218 &success)); 248 &success));
219 return success; 249 return success;
220 } 250 }
221 251
222 bool Session::GetCookies(const GURL& url, std::string* cookies) { 252 bool Session::GetCookies(const GURL& url, std::string* cookies) {
223 bool success = false; 253 bool success = false;
224 RunSessionTask(NewRunnableMethod( 254 RunSessionTask(NewRunnableMethod(
225 automation_.get(), 255 automation_.get(),
226 &Automation::GetCookies, 256 &Automation::GetCookies,
257 current_window_id_,
227 url, 258 url,
228 cookies, 259 cookies,
229 &success)); 260 &success));
230 return success; 261 return success;
231 } 262 }
232 263
233 bool Session::GetCookieByName(const GURL& url, 264 bool Session::GetCookieByName(const GURL& url,
234 const std::string& cookie_name, 265 const std::string& cookie_name,
235 std::string* cookie) { 266 std::string* cookie) {
236 bool success = false; 267 bool success = false;
237 RunSessionTask(NewRunnableMethod( 268 RunSessionTask(NewRunnableMethod(
238 automation_.get(), 269 automation_.get(),
239 &Automation::GetCookieByName, 270 &Automation::GetCookieByName,
271 current_window_id_,
240 url, 272 url,
241 cookie_name, 273 cookie_name,
242 cookie, 274 cookie,
243 &success)); 275 &success));
244 return success; 276 return success;
245 } 277 }
246 278
247 bool Session::DeleteCookie(const GURL& url, const std::string& cookie_name) { 279 bool Session::DeleteCookie(const GURL& url, const std::string& cookie_name) {
248 bool success = false; 280 bool success = false;
249 RunSessionTask(NewRunnableMethod( 281 RunSessionTask(NewRunnableMethod(
250 automation_.get(), 282 automation_.get(),
251 &Automation::DeleteCookie, 283 &Automation::DeleteCookie,
284 current_window_id_,
252 url, 285 url,
253 cookie_name, 286 cookie_name,
254 &success)); 287 &success));
255 return success; 288 return success;
256 } 289 }
257 290
258 bool Session::SetCookie(const GURL& url, const std::string& cookie) { 291 bool Session::SetCookie(const GURL& url, const std::string& cookie) {
259 bool success = false; 292 bool success = false;
260 RunSessionTask(NewRunnableMethod( 293 RunSessionTask(NewRunnableMethod(
261 automation_.get(), 294 automation_.get(),
262 &Automation::SetCookie, 295 &Automation::SetCookie,
296 current_window_id_,
263 url, 297 url,
264 cookie, 298 cookie,
265 &success)); 299 &success));
266 return success; 300 return success;
267 } 301 }
268 302
303 bool Session::GetWindowIds(std::vector<int>* window_ids) {
304 bool success = false;
305 RunSessionTask(NewRunnableMethod(
306 automation_.get(),
307 &Automation::GetTabIds,
308 window_ids,
309 &success));
310 return success;
311 }
312
313 ErrorCode Session::SwitchToWindow(const std::string& name) {
314 int switch_to_id = 0;
315 int name_no = 0;
316 if (base::StringToInt(name, &name_no)) {
317 bool does_exist = false;
318 RunSessionTask(NewRunnableMethod(
319 automation_.get(),
320 &Automation::DoesTabExist,
321 name_no,
322 &does_exist));
323 if (does_exist)
324 switch_to_id = name_no;
325 }
326
327 if (!switch_to_id) {
328 std::vector<int> window_ids;
329 GetWindowIds(&window_ids);
330 // See if any of the window names match |name|.
331 for (size_t i = 0; i < window_ids.size(); ++i) {
332 ListValue empty_list;
333 Value* unscoped_name_value;
334 std::string window_name;
335 ErrorCode code = ExecuteScript(window_ids[i],
336 "",
337 "return window.name;",
338 &empty_list,
339 &unscoped_name_value);
340 scoped_ptr<Value> name_value(unscoped_name_value);
341 if (code == kSuccess &&
342 name_value->GetAsString(&window_name) &&
343 name == window_name) {
344 switch_to_id = window_ids[i];
345 break;
346 }
347 }
348 }
349
350 if (!switch_to_id)
351 return kNoSuchWindow;
352 current_window_id_ = switch_to_id;
353 current_frame_xpath_ = "";
354 return kSuccess;
355 }
356
357 ErrorCode Session::SwitchToFrameWithNameOrId(const std::string& name_or_id) {
358 std::string script =
359 "var arg = arguments[0];"
360 "var xpath = '(/html/body//iframe|/html/frameset/frame)';"
361 "var sub = function(s) { return s.replace(/\\$/g, arg); };"
362 "xpath += sub('[@name=\"$\" or @id=\"$\"]');"
363 "var frame = document.evaluate(xpath, document, null, "
364 " XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
365 "if (!frame) { return null; }"
366 "xpath = frame.tagName == 'IFRAME' ? '/html/body//iframe'"
367 " : '/html/frameset/frame';"
368 "return xpath + sub('[@' + (frame.id == arg ? 'id' : 'name')"
369 " + '=\"$\"]');";
370 ListValue args;
371 args.Append(new StringValue(name_or_id));
372 return SwitchToFrameWithJavaScriptLocatedFrame(script, &args);
373 }
374
375 ErrorCode Session::SwitchToFrameWithIndex(int index) {
376 // We cannot simply index into window.frames because we need to know the
377 // tagName of the frameElement. If child frame N is from another domain, then
378 // the following will run afoul of the same origin policy:
379 // window.frames[N].frameElement;
380 // Instead of indexing window.frames, we use a an XPath expression to index
381 // into the list of all IFRAME and FRAME elements on the page - if we find
382 // something, then that XPath expression can be used as the new frame's XPath.
383 std::string script =
384 "var index = '[' + (arguments[0] + 1) + ']';"
385 "var xpath = '(/html/body//iframe|/html/frameset/frame)' + "
386 " index;"
387 "console.info('searching for frame by xpath: ' + xpath);"
388 "var frame = document.evaluate(xpath, document, null, "
389 "XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
390 "console.info(frame == null ? 'found nothing' : frame);"
391 "return frame == null ? null : ((frame.tagName == 'IFRAME' ? "
392 " '/html/body//iframe' : '/html/frameset/frame') + index);";
393 ListValue args;
394 args.Append(Value::CreateIntegerValue(index));
395 return SwitchToFrameWithJavaScriptLocatedFrame(script, &args);
396 }
397
398 bool Session::CloseWindow() {
399 bool success = false;
400 RunSessionTask(NewRunnableMethod(
401 automation_.get(),
402 &Automation::CloseTab,
403 current_window_id_,
404 &success));
405
406 if (success) {
407 std::vector<int> window_ids;
408 if (!GetWindowIds(&window_ids) || window_ids.empty()) {
409 // The automation connection will soon be closed, if not already,
410 // because we supposedly just closed the last window. Terminate the
411 // session.
412 // TODO(kkania): This will cause us problems if GetWindowIds fails for a
413 // reason other than the channel is disconnected. Look into having
414 // |GetWindowIds| tell us if it just closed the last window.
415 Terminate();
416 }
417 }
418 return success;
419 }
420
269 void Session::RunSessionTask(Task* task) { 421 void Session::RunSessionTask(Task* task) {
270 base::WaitableEvent done_event(false, false); 422 base::WaitableEvent done_event(false, false);
271 thread_.message_loop_proxy()->PostTask(FROM_HERE, NewRunnableMethod( 423 thread_.message_loop_proxy()->PostTask(FROM_HERE, NewRunnableMethod(
272 this, 424 this,
273 &Session::RunSessionTaskOnSessionThread, 425 &Session::RunSessionTaskOnSessionThread,
274 task, 426 task,
275 &done_event)); 427 &done_event));
276 done_event.Wait(); 428 done_event.Wait();
277 } 429 }
278 430
279 void Session::RunSessionTaskOnSessionThread(Task* task, 431 void Session::RunSessionTaskOnSessionThread(Task* task,
280 base::WaitableEvent* done_event) { 432 base::WaitableEvent* done_event) {
281 task->Run(); 433 task->Run();
282 delete task; 434 delete task;
283 done_event->Signal(); 435 done_event->Signal();
284 } 436 }
285 437
286 void Session::InitOnSessionThread(bool* success) { 438 void Session::InitOnSessionThread(bool* success) {
287 automation_.reset(new Automation()); 439 automation_.reset(new Automation());
288 automation_->Init(success); 440 automation_->Init(success);
441 if (!*success)
442 return;
443
444 std::vector<int> tab_ids;
445 automation_->GetTabIds(&tab_ids, success);
446 if (!*success) {
447 LOG(ERROR) << "Could not get tab ids";
448 return;
449 }
450 if (tab_ids.empty()) {
451 LOG(ERROR) << "No tab ids after initialization";
452 *success = false;
453 } else {
454 current_window_id_ = tab_ids[0];
455 }
289 } 456 }
290 457
291 void Session::TerminateOnSessionThread() { 458 void Session::TerminateOnSessionThread() {
292 automation_->Terminate(); 459 if (automation_.get())
460 automation_->Terminate();
293 automation_.reset(); 461 automation_.reset();
294 } 462 }
295 463
296 void Session::SendKeysOnSessionThread(const string16& keys, 464 void Session::SendKeysOnSessionThread(const string16& keys,
297 bool* success) { 465 bool* success) {
298 *success = true; 466 *success = true;
299 std::vector<WebKeyEvent> key_events; 467 std::vector<WebKeyEvent> key_events;
300 ConvertKeysToWebKeyEvents(keys, &key_events); 468 ConvertKeysToWebKeyEvents(keys, &key_events);
301 for (size_t i = 0; i < key_events.size(); ++i) { 469 for (size_t i = 0; i < key_events.size(); ++i) {
302 bool key_success = false; 470 bool key_success = false;
303 automation_->SendWebKeyEvent(key_events[i], &key_success); 471 automation_->SendWebKeyEvent(
472 current_window_id_, key_events[i], &key_success);
304 if (!key_success) { 473 if (!key_success) {
305 LOG(ERROR) << "Failed to send key event. Event details:\n" 474 LOG(ERROR) << "Failed to send key event. Event details:\n"
306 << "Type: " << key_events[i].type << "\n" 475 << "Type: " << key_events[i].type << "\n"
307 << "KeyCode: " << key_events[i].key_code << "\n" 476 << "KeyCode: " << key_events[i].key_code << "\n"
308 << "UnmodifiedText: " << key_events[i].unmodified_text << "\n" 477 << "UnmodifiedText: " << key_events[i].unmodified_text << "\n"
309 << "ModifiedText: " << key_events[i].modified_text << "\n" 478 << "ModifiedText: " << key_events[i].modified_text << "\n"
310 << "Modifiers: " << key_events[i].modifiers << "\n"; 479 << "Modifiers: " << key_events[i].modifiers << "\n";
311 *success = false; 480 *success = false;
312 } 481 }
313 } 482 }
314 } 483 }
315 484
485 ErrorCode Session::SwitchToFrameWithJavaScriptLocatedFrame(
486 const std::string& script,
487 ListValue* args) {
488 Value* unscoped_result = NULL;
489 ErrorCode code = ExecuteScript(script, args, &unscoped_result);
490 scoped_ptr<Value> result(unscoped_result);
491 if (code != kSuccess)
492 return code;
493 std::string xpath;
494 if (result->GetAsString(&xpath)) {
495 if (current_frame_xpath_.length())
496 current_frame_xpath_ += "\n";
497 current_frame_xpath_ += xpath;
498 return kSuccess;
499 }
500 return kNoSuchFrame;
501 }
502
316 } // namespace webdriver 503 } // namespace webdriver
OLDNEW
« no previous file with comments | « chrome/test/webdriver/session.h ('k') | chrome/test/webdriver/session_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698