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 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
956 if (error) | 958 if (error) |
957 return error; | 959 return error; |
958 if (!is_displayed) | 960 if (!is_displayed) |
959 return new Error(kElementNotVisible, "Element must be displayed to click"); | 961 return new Error(kElementNotVisible, "Element must be displayed to click"); |
960 | 962 |
961 gfx::Rect rect; | 963 gfx::Rect rect; |
962 error = GetElementFirstClientRect(current_target_, element, &rect); | 964 error = GetElementFirstClientRect(current_target_, element, &rect); |
963 if (error) | 965 if (error) |
964 return error; | 966 return error; |
965 | 967 |
966 error = GetElementRegionInView(element, rect, true /* center */, location); | 968 error = GetElementRegionInView( |
| 969 element, rect, true /* center */, true /* verify_clickable_at_middle */, |
| 970 location); |
967 if (error) | 971 if (error) |
968 return error; | 972 return error; |
969 location->Offset(rect.width() / 2, rect.height() / 2); | 973 location->Offset(rect.width() / 2, rect.height() / 2); |
970 return NULL; | 974 return NULL; |
971 } | 975 } |
972 | 976 |
973 Error* Session::GetAttribute(const WebElementId& element, | 977 Error* Session::GetAttribute(const WebElementId& element, |
974 const std::string& key, Value** value) { | 978 const std::string& key, Value** value) { |
975 std::string script = base::StringPrintf( | 979 std::string script = base::StringPrintf( |
976 "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE); | 980 "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE); |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1304 elements->push_back(element); | 1308 elements->push_back(element); |
1305 } else { | 1309 } else { |
1306 return new Error( | 1310 return new Error( |
1307 kUnknownError, | 1311 kUnknownError, |
1308 "Find element script returned unsupported type: " + | 1312 "Find element script returned unsupported type: " + |
1309 JsonStringify(value.get())); | 1313 JsonStringify(value.get())); |
1310 } | 1314 } |
1311 return NULL; | 1315 return NULL; |
1312 } | 1316 } |
1313 | 1317 |
| 1318 Error* Session::VerifyElementIsClickable( |
| 1319 const FrameId& frame_id, |
| 1320 const WebElementId& element, |
| 1321 const gfx::Point& location) { |
| 1322 std::string jscript = base::StringPrintf( |
| 1323 "return (%s).apply(null, arguments);", atoms::IS_ELEMENT_CLICKABLE); |
| 1324 ListValue jscript_args; |
| 1325 jscript_args.Append(element.ToValue()); |
| 1326 DictionaryValue* location_dict = new DictionaryValue(); |
| 1327 location_dict->SetInteger("x", location.x()); |
| 1328 location_dict->SetInteger("y", location.y()); |
| 1329 jscript_args.Append(location_dict); |
| 1330 Value* unscoped_value = NULL; |
| 1331 Error* error = ExecuteScript(frame_id, jscript, &jscript_args, |
| 1332 &unscoped_value); |
| 1333 if (error) |
| 1334 return error; |
| 1335 |
| 1336 scoped_ptr<Value> value(unscoped_value); |
| 1337 if (!value->IsType(Value::TYPE_DICTIONARY)) { |
| 1338 return new Error( |
| 1339 kUnknownError, |
| 1340 "isElementClickable atom returned non-dictionary type: " + |
| 1341 JsonStringify(value.get())); |
| 1342 } |
| 1343 DictionaryValue* dict = static_cast<DictionaryValue*>(value.get()); |
| 1344 bool clickable = false; |
| 1345 if (!dict->GetBoolean("clickable", &clickable)) { |
| 1346 return new Error( |
| 1347 kUnknownError, |
| 1348 "isElementClickable atom returned bad invalid dictionary: " + |
| 1349 JsonStringify(dict)); |
| 1350 } |
| 1351 std::string message; |
| 1352 dict->GetString("message", &message); |
| 1353 if (!clickable) { |
| 1354 if (message.empty()) |
| 1355 message = "element is not clickable"; |
| 1356 return new Error(kUnknownError, message); |
| 1357 } |
| 1358 if (message.length()) { |
| 1359 LOG(WARNING) << message; |
| 1360 } |
| 1361 return NULL; |
| 1362 } |
| 1363 |
1314 Error* Session::GetElementRegionInViewHelper( | 1364 Error* Session::GetElementRegionInViewHelper( |
1315 const FrameId& frame_id, | 1365 const FrameId& frame_id, |
1316 const WebElementId& element, | 1366 const WebElementId& element, |
1317 const gfx::Rect& region, | 1367 const gfx::Rect& region, |
1318 bool center, | 1368 bool center, |
| 1369 bool verify_clickable_at_middle, |
1319 gfx::Point* location) { | 1370 gfx::Point* location) { |
1320 std::string jscript = base::StringPrintf( | 1371 std::string jscript = base::StringPrintf( |
1321 "return (%s).apply(null, arguments);", atoms::GET_LOCATION_IN_VIEW); | 1372 "return (%s).apply(null, arguments);", atoms::GET_LOCATION_IN_VIEW); |
1322 ListValue jscript_args; | 1373 ListValue jscript_args; |
1323 jscript_args.Append(element.ToValue()); | 1374 jscript_args.Append(element.ToValue()); |
1324 jscript_args.Append(Value::CreateBooleanValue(center)); | 1375 jscript_args.Append(Value::CreateBooleanValue(center)); |
1325 DictionaryValue* elem_offset_dict = new DictionaryValue(); | 1376 DictionaryValue* elem_offset_dict = new DictionaryValue(); |
1326 elem_offset_dict->SetInteger("left", region.x()); | 1377 elem_offset_dict->SetInteger("left", region.x()); |
1327 elem_offset_dict->SetInteger("top", region.y()); | 1378 elem_offset_dict->SetInteger("top", region.y()); |
1328 elem_offset_dict->SetInteger("width", region.width()); | 1379 elem_offset_dict->SetInteger("width", region.width()); |
1329 elem_offset_dict->SetInteger("height", region.height()); | 1380 elem_offset_dict->SetInteger("height", region.height()); |
1330 jscript_args.Append(elem_offset_dict); | 1381 jscript_args.Append(elem_offset_dict); |
1331 Value* unscoped_value = NULL; | 1382 Value* unscoped_value = NULL; |
1332 Error* error = ExecuteScript(frame_id, jscript, &jscript_args, | 1383 Error* error = ExecuteScript(frame_id, jscript, &jscript_args, |
1333 &unscoped_value); | 1384 &unscoped_value); |
1334 scoped_ptr<Value> value(unscoped_value); | 1385 scoped_ptr<Value> value(unscoped_value); |
1335 if (error) | 1386 if (error) |
1336 return error; | 1387 return error; |
| 1388 |
1337 if (!value->IsType(Value::TYPE_DICTIONARY)) { | 1389 if (!value->IsType(Value::TYPE_DICTIONARY)) { |
1338 return new Error( | 1390 return new Error( |
1339 kUnknownError, | 1391 kUnknownError, |
1340 "Location atom returned non-dictionary type: " + | 1392 "Location atom returned non-dictionary type: " + |
1341 JsonStringify(value.get())); | 1393 JsonStringify(value.get())); |
1342 } | 1394 } |
1343 DictionaryValue* loc_dict = static_cast<DictionaryValue*>(value.get()); | 1395 DictionaryValue* loc_dict = static_cast<DictionaryValue*>(value.get()); |
1344 int x = 0, y = 0; | 1396 int x = 0, y = 0; |
1345 if (!loc_dict->GetInteger("x", &x) || | 1397 if (!loc_dict->GetInteger("x", &x) || |
1346 !loc_dict->GetInteger("y", &y)) { | 1398 !loc_dict->GetInteger("y", &y)) { |
1347 return new Error( | 1399 return new Error( |
1348 kUnknownError, | 1400 kUnknownError, |
1349 "Location atom returned bad coordinate dictionary: " + | 1401 "Location atom returned bad coordinate dictionary: " + |
1350 JsonStringify(loc_dict)); | 1402 JsonStringify(loc_dict)); |
1351 } | 1403 } |
1352 *location = gfx::Point(x, y); | 1404 gfx::Point temp_location = gfx::Point(x, y); |
| 1405 |
| 1406 if (verify_clickable_at_middle) { |
| 1407 gfx::Point middle_point = temp_location; |
| 1408 middle_point.Offset(region.width() / 2, region.height() / 2); |
| 1409 error = VerifyElementIsClickable(frame_id, element, middle_point); |
| 1410 if (error) |
| 1411 return error; |
| 1412 } |
| 1413 *location = temp_location; |
1353 return NULL; | 1414 return NULL; |
1354 } | 1415 } |
1355 | 1416 |
1356 Error* Session::GetScreenShot(std::string* png) { | 1417 Error* Session::GetScreenShot(std::string* png) { |
1357 Error* error = NULL; | 1418 Error* error = NULL; |
1358 ScopedTempDir screenshots_dir; | 1419 ScopedTempDir screenshots_dir; |
1359 if (!screenshots_dir.CreateUniqueTempDir()) { | 1420 if (!screenshots_dir.CreateUniqueTempDir()) { |
1360 return new Error(kUnknownError, | 1421 return new Error(kUnknownError, |
1361 "Could not create temp directory for screenshot"); | 1422 "Could not create temp directory for screenshot"); |
1362 } | 1423 } |
1363 | 1424 |
1364 FilePath path = screenshots_dir.path().AppendASCII("screen"); | 1425 FilePath path = screenshots_dir.path().AppendASCII("screen"); |
1365 RunSessionTask(NewRunnableMethod( | 1426 RunSessionTask(NewRunnableMethod( |
1366 automation_.get(), | 1427 automation_.get(), |
1367 &Automation::CaptureEntirePageAsPNG, | 1428 &Automation::CaptureEntirePageAsPNG, |
1368 current_target_.window_id, | 1429 current_target_.window_id, |
1369 path, | 1430 path, |
1370 &error)); | 1431 &error)); |
1371 if (error) | 1432 if (error) |
1372 return error; | 1433 return error; |
1373 if (!file_util::ReadFileToString(path, png)) | 1434 if (!file_util::ReadFileToString(path, png)) |
1374 return new Error(kUnknownError, "Could not read screenshot file"); | 1435 return new Error(kUnknownError, "Could not read screenshot file"); |
1375 return NULL; | 1436 return NULL; |
1376 } | 1437 } |
1377 | 1438 |
1378 } // namespace webdriver | 1439 } // namespace webdriver |
OLD | NEW |