| 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 |