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