OLD | NEW |
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.h" | 5 #include "chrome/test/webdriver/session.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 | 705 |
706 Error* Session::GetElementLocationInView( | 706 Error* Session::GetElementLocationInView( |
707 const WebElementId& element, | 707 const WebElementId& element, |
708 gfx::Point* location) { | 708 gfx::Point* location) { |
709 gfx::Size size; | 709 gfx::Size size; |
710 Error* error = GetElementSize(current_target_, element, &size); | 710 Error* error = GetElementSize(current_target_, element, &size); |
711 if (error) | 711 if (error) |
712 return error; | 712 return error; |
713 return GetElementRegionInView( | 713 return GetElementRegionInView( |
714 element, gfx::Rect(gfx::Point(0, 0), size), | 714 element, gfx::Rect(gfx::Point(0, 0), size), |
715 false /* center */, location); | 715 false /* center */, false /* verify_clickable_at_middle */, location); |
716 } | 716 } |
717 | 717 |
718 Error* Session::GetElementRegionInView( | 718 Error* Session::GetElementRegionInView( |
719 const WebElementId& element, | 719 const WebElementId& element, |
720 const gfx::Rect& region, | 720 const gfx::Rect& region, |
721 bool center, | 721 bool center, |
| 722 bool verify_clickable_at_middle, |
722 gfx::Point* location) { | 723 gfx::Point* location) { |
723 CHECK(element.is_valid()); | 724 CHECK(element.is_valid()); |
724 | 725 |
725 gfx::Point region_offset = region.origin(); | 726 gfx::Point region_offset = region.origin(); |
726 gfx::Size region_size = region.size(); | 727 gfx::Size region_size = region.size(); |
727 Error* error = GetElementRegionInViewHelper( | 728 Error* error = GetElementRegionInViewHelper( |
728 current_target_, element, region, center, ®ion_offset); | 729 current_target_, element, region, center, verify_clickable_at_middle, |
| 730 ®ion_offset); |
729 if (error) | 731 if (error) |
730 return error; | 732 return error; |
731 | 733 |
732 for (FramePath frame_path = current_target_.frame_path; | 734 for (FramePath frame_path = current_target_.frame_path; |
733 frame_path.IsSubframe(); | 735 frame_path.IsSubframe(); |
734 frame_path = frame_path.Parent()) { | 736 frame_path = frame_path.Parent()) { |
735 // Find the frame element for the current frame path. | 737 // Find the frame element for the current frame path. |
736 FrameId frame_id(current_target_.window_id, frame_path.Parent()); | 738 FrameId frame_id(current_target_.window_id, frame_path.Parent()); |
737 WebElementId frame_element; | 739 WebElementId frame_element; |
738 error = FindElement( | 740 error = FindElement( |
(...skipping 10 matching lines...) Expand all Loading... |
749 // Modify |region_offset| by the frame's border. | 751 // Modify |region_offset| by the frame's border. |
750 int border_left, border_top; | 752 int border_left, border_top; |
751 error = GetElementBorder( | 753 error = GetElementBorder( |
752 frame_id, frame_element, &border_left, &border_top); | 754 frame_id, frame_element, &border_left, &border_top); |
753 if (error) | 755 if (error) |
754 return error; | 756 return error; |
755 region_offset.Offset(border_left, border_top); | 757 region_offset.Offset(border_left, border_top); |
756 | 758 |
757 error = GetElementRegionInViewHelper( | 759 error = GetElementRegionInViewHelper( |
758 frame_id, frame_element, gfx::Rect(region_offset, region_size), | 760 frame_id, frame_element, gfx::Rect(region_offset, region_size), |
759 center, ®ion_offset); | 761 center, verify_clickable_at_middle, ®ion_offset); |
760 if (error) | 762 if (error) |
761 return error; | 763 return error; |
762 } | 764 } |
763 *location = region_offset; | 765 *location = region_offset; |
764 return NULL; | 766 return NULL; |
765 } | 767 } |
766 | 768 |
767 Error* Session::GetElementSize(const FrameId& frame_id, | 769 Error* Session::GetElementSize(const FrameId& frame_id, |
768 const WebElementId& element, | 770 const WebElementId& element, |
769 gfx::Size* size) { | 771 gfx::Size* size) { |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 if (error) | 960 if (error) |
959 return error; | 961 return error; |
960 if (!is_displayed) | 962 if (!is_displayed) |
961 return new Error(kElementNotVisible, "Element must be displayed to click"); | 963 return new Error(kElementNotVisible, "Element must be displayed to click"); |
962 | 964 |
963 gfx::Rect rect; | 965 gfx::Rect rect; |
964 error = GetElementFirstClientRect(current_target_, element, &rect); | 966 error = GetElementFirstClientRect(current_target_, element, &rect); |
965 if (error) | 967 if (error) |
966 return error; | 968 return error; |
967 | 969 |
968 error = GetElementRegionInView(element, rect, true /* center */, location); | 970 error = GetElementRegionInView( |
| 971 element, rect, true /* center */, true /* verify_clickable_at_middle */, |
| 972 location); |
969 if (error) | 973 if (error) |
970 return error; | 974 return error; |
971 location->Offset(rect.width() / 2, rect.height() / 2); | 975 location->Offset(rect.width() / 2, rect.height() / 2); |
972 return NULL; | 976 return NULL; |
973 } | 977 } |
974 | 978 |
975 Error* Session::GetAttribute(const WebElementId& element, | 979 Error* Session::GetAttribute(const WebElementId& element, |
976 const std::string& key, Value** value) { | 980 const std::string& key, Value** value) { |
977 std::string script = base::StringPrintf( | 981 std::string script = base::StringPrintf( |
978 "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE); | 982 "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE); |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1306 elements->push_back(element); | 1310 elements->push_back(element); |
1307 } else { | 1311 } else { |
1308 return new Error( | 1312 return new Error( |
1309 kUnknownError, | 1313 kUnknownError, |
1310 "Find element script returned unsupported type: " + | 1314 "Find element script returned unsupported type: " + |
1311 JsonStringify(value.get())); | 1315 JsonStringify(value.get())); |
1312 } | 1316 } |
1313 return NULL; | 1317 return NULL; |
1314 } | 1318 } |
1315 | 1319 |
| 1320 Error* Session::VerifyElementIsClickable( |
| 1321 const FrameId& frame_id, |
| 1322 const WebElementId& element, |
| 1323 const gfx::Point& location) { |
| 1324 std::string jscript = base::StringPrintf( |
| 1325 "return (%s).apply(null, arguments);", atoms::IS_ELEMENT_CLICKABLE); |
| 1326 ListValue jscript_args; |
| 1327 jscript_args.Append(element.ToValue()); |
| 1328 DictionaryValue* location_dict = new DictionaryValue(); |
| 1329 location_dict->SetInteger("x", location.x()); |
| 1330 location_dict->SetInteger("y", location.y()); |
| 1331 jscript_args.Append(location_dict); |
| 1332 Value* unscoped_value = NULL; |
| 1333 Error* error = ExecuteScript(frame_id, jscript, &jscript_args, |
| 1334 &unscoped_value); |
| 1335 if (error) |
| 1336 return error; |
| 1337 |
| 1338 scoped_ptr<Value> value(unscoped_value); |
| 1339 if (!value->IsType(Value::TYPE_DICTIONARY)) { |
| 1340 return new Error( |
| 1341 kUnknownError, |
| 1342 "isElementClickable atom returned non-dictionary type: " + |
| 1343 JsonStringify(value.get())); |
| 1344 } |
| 1345 DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); |
| 1346 bool clickable = false; |
| 1347 if (!dict->GetBoolean("clickable", &clickable)) { |
| 1348 return new Error( |
| 1349 kUnknownError, |
| 1350 "isElementClickable atom returned bad invalid dictionary: " + |
| 1351 JsonStringify(dict)); |
| 1352 } |
| 1353 std::string message; |
| 1354 dict->GetString("message", &message); |
| 1355 if (!clickable) { |
| 1356 if (message.empty()) |
| 1357 message = "element is not clickable"; |
| 1358 return new Error(kUnknownError, message); |
| 1359 } |
| 1360 if (message.length()) { |
| 1361 LOG(WARNING) << message; |
| 1362 } |
| 1363 return NULL; |
| 1364 } |
| 1365 |
1316 Error* Session::GetElementRegionInViewHelper( | 1366 Error* Session::GetElementRegionInViewHelper( |
1317 const FrameId& frame_id, | 1367 const FrameId& frame_id, |
1318 const WebElementId& element, | 1368 const WebElementId& element, |
1319 const gfx::Rect& region, | 1369 const gfx::Rect& region, |
1320 bool center, | 1370 bool center, |
| 1371 bool verify_clickable_at_middle, |
1321 gfx::Point* location) { | 1372 gfx::Point* location) { |
1322 std::string jscript = base::StringPrintf( | 1373 std::string jscript = base::StringPrintf( |
1323 "return (%s).apply(null, arguments);", atoms::GET_LOCATION_IN_VIEW); | 1374 "return (%s).apply(null, arguments);", atoms::GET_LOCATION_IN_VIEW); |
1324 ListValue jscript_args; | 1375 ListValue jscript_args; |
1325 jscript_args.Append(element.ToValue()); | 1376 jscript_args.Append(element.ToValue()); |
1326 jscript_args.Append(Value::CreateBooleanValue(center)); | 1377 jscript_args.Append(Value::CreateBooleanValue(center)); |
1327 DictionaryValue* elem_offset_dict = new DictionaryValue(); | 1378 DictionaryValue* elem_offset_dict = new DictionaryValue(); |
1328 elem_offset_dict->SetInteger("left", region.x()); | 1379 elem_offset_dict->SetInteger("left", region.x()); |
1329 elem_offset_dict->SetInteger("top", region.y()); | 1380 elem_offset_dict->SetInteger("top", region.y()); |
1330 elem_offset_dict->SetInteger("width", region.width()); | 1381 elem_offset_dict->SetInteger("width", region.width()); |
1331 elem_offset_dict->SetInteger("height", region.height()); | 1382 elem_offset_dict->SetInteger("height", region.height()); |
1332 jscript_args.Append(elem_offset_dict); | 1383 jscript_args.Append(elem_offset_dict); |
1333 Value* unscoped_value = NULL; | 1384 Value* unscoped_value = NULL; |
1334 Error* error = ExecuteScript(frame_id, jscript, &jscript_args, | 1385 Error* error = ExecuteScript(frame_id, jscript, &jscript_args, |
1335 &unscoped_value); | 1386 &unscoped_value); |
1336 scoped_ptr<Value> value(unscoped_value); | 1387 scoped_ptr<Value> value(unscoped_value); |
1337 if (error) | 1388 if (error) |
1338 return error; | 1389 return error; |
| 1390 |
1339 if (!value->IsType(Value::TYPE_DICTIONARY)) { | 1391 if (!value->IsType(Value::TYPE_DICTIONARY)) { |
1340 return new Error( | 1392 return new Error( |
1341 kUnknownError, | 1393 kUnknownError, |
1342 "Location atom returned non-dictionary type: " + | 1394 "Location atom returned non-dictionary type: " + |
1343 JsonStringify(value.get())); | 1395 JsonStringify(value.get())); |
1344 } | 1396 } |
1345 DictionaryValue* loc_dict = static_cast<DictionaryValue*>(value.get()); | 1397 DictionaryValue* loc_dict = static_cast<DictionaryValue*>(value.get()); |
1346 int x = 0, y = 0; | 1398 int x = 0, y = 0; |
1347 if (!loc_dict->GetInteger("x", &x) || | 1399 if (!loc_dict->GetInteger("x", &x) || |
1348 !loc_dict->GetInteger("y", &y)) { | 1400 !loc_dict->GetInteger("y", &y)) { |
1349 return new Error( | 1401 return new Error( |
1350 kUnknownError, | 1402 kUnknownError, |
1351 "Location atom returned bad coordinate dictionary: " + | 1403 "Location atom returned bad coordinate dictionary: " + |
1352 JsonStringify(loc_dict)); | 1404 JsonStringify(loc_dict)); |
1353 } | 1405 } |
1354 *location = gfx::Point(x, y); | 1406 gfx::Point temp_location = gfx::Point(x, y); |
| 1407 |
| 1408 if (verify_clickable_at_middle) { |
| 1409 gfx::Point middle_point = temp_location; |
| 1410 middle_point.Offset(region.width() / 2, region.height() / 2); |
| 1411 error = VerifyElementIsClickable(frame_id, element, middle_point); |
| 1412 if (error) |
| 1413 return error; |
| 1414 } |
| 1415 *location = temp_location; |
1355 return NULL; | 1416 return NULL; |
1356 } | 1417 } |
1357 | 1418 |
1358 Error* Session::GetScreenShot(std::string* png) { | 1419 Error* Session::GetScreenShot(std::string* png) { |
1359 Error* error = NULL; | 1420 Error* error = NULL; |
1360 ScopedTempDir screenshots_dir; | 1421 ScopedTempDir screenshots_dir; |
1361 if (!screenshots_dir.CreateUniqueTempDir()) { | 1422 if (!screenshots_dir.CreateUniqueTempDir()) { |
1362 return new Error(kUnknownError, | 1423 return new Error(kUnknownError, |
1363 "Could not create temp directory for screenshot"); | 1424 "Could not create temp directory for screenshot"); |
1364 } | 1425 } |
1365 | 1426 |
1366 FilePath path = screenshots_dir.path().AppendASCII("screen"); | 1427 FilePath path = screenshots_dir.path().AppendASCII("screen"); |
1367 RunSessionTask(NewRunnableMethod( | 1428 RunSessionTask(NewRunnableMethod( |
1368 automation_.get(), | 1429 automation_.get(), |
1369 &Automation::CaptureEntirePageAsPNG, | 1430 &Automation::CaptureEntirePageAsPNG, |
1370 current_target_.window_id, | 1431 current_target_.window_id, |
1371 path, | 1432 path, |
1372 &error)); | 1433 &error)); |
1373 if (error) | 1434 if (error) |
1374 return error; | 1435 return error; |
1375 if (!file_util::ReadFileToString(path, png)) | 1436 if (!file_util::ReadFileToString(path, png)) |
1376 return new Error(kUnknownError, "Could not read screenshot file"); | 1437 return new Error(kUnknownError, "Could not read screenshot file"); |
1377 return NULL; | 1438 return NULL; |
1378 } | 1439 } |
1379 | 1440 |
1380 } // namespace webdriver | 1441 } // namespace webdriver |
OLD | NEW |