| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/chromedriver/element_util.h" | 5 #include "chrome/test/chromedriver/element_util.h" |
| 6 | 6 |
| 7 #include "base/string_util.h" | 7 #include "base/string_util.h" |
| 8 #include "base/stringprintf.h" | 8 #include "base/stringprintf.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/threading/platform_thread.h" | 10 #include "base/threading/platform_thread.h" |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 args.Append(CreateValueFrom(location)); | 107 args.Append(CreateValueFrom(location)); |
| 108 scoped_ptr<base::Value> result; | 108 scoped_ptr<base::Value> result; |
| 109 Status status = CallAtomsJs( | 109 Status status = CallAtomsJs( |
| 110 frame, web_view, webdriver::atoms::IS_ELEMENT_CLICKABLE, | 110 frame, web_view, webdriver::atoms::IS_ELEMENT_CLICKABLE, |
| 111 args, &result); | 111 args, &result); |
| 112 if (status.IsError()) | 112 if (status.IsError()) |
| 113 return status; | 113 return status; |
| 114 base::DictionaryValue* dict; | 114 base::DictionaryValue* dict; |
| 115 bool is_clickable; | 115 bool is_clickable; |
| 116 if (!result->GetAsDictionary(&dict) || | 116 if (!result->GetAsDictionary(&dict) || |
| 117 !dict->GetBoolean("clickable", &is_clickable)) | 117 !dict->GetBoolean("clickable", &is_clickable)) { |
| 118 return Status(kUnknownError, "fail to parse value of IS_ELEMENT_CLICKABLE"); | 118 return Status(kUnknownError, |
| 119 "failed to parse value of IS_ELEMENT_CLICKABLE"); |
| 120 } |
| 119 | 121 |
| 120 if (!is_clickable) { | 122 if (!is_clickable) { |
| 121 std::string message; | 123 std::string message; |
| 122 if (!dict->GetString("message", &message)) | 124 if (!dict->GetString("message", &message)) |
| 123 message = "element is not clickable"; | 125 message = "element is not clickable"; |
| 124 return Status(kUnknownError, message); | 126 return Status(kUnknownError, message); |
| 125 } | 127 } |
| 126 return Status(kOk); | 128 return Status(kOk); |
| 127 } | 129 } |
| 128 | 130 |
| 129 Status ScrollElementRegionIntoViewHelper( | 131 Status ScrollElementRegionIntoViewHelper( |
| 130 const std::string& frame, | 132 const std::string& frame, |
| 131 WebView* web_view, | 133 WebView* web_view, |
| 132 const std::string& element_id, | 134 const std::string& element_id, |
| 133 const WebRect& region, | 135 const WebRect& region, |
| 134 bool center, | 136 bool center, |
| 135 bool verify_clickable, | 137 bool verify_clickable, |
| 136 WebPoint* location) { | 138 WebPoint* location) { |
| 137 WebPoint tmp_location = *location; | 139 WebPoint tmp_location = *location; |
| 138 base::ListValue args; | 140 base::ListValue args; |
| 139 args.Append(CreateElement(element_id)); | 141 args.Append(CreateElement(element_id)); |
| 140 args.AppendBoolean(center); | 142 args.AppendBoolean(center); |
| 141 args.Append(CreateValueFrom(region)); | 143 args.Append(CreateValueFrom(region)); |
| 142 scoped_ptr<base::Value> result; | 144 scoped_ptr<base::Value> result; |
| 143 Status status = web_view->CallFunction( | 145 Status status = web_view->CallFunction( |
| 144 frame, webdriver::atoms::asString(webdriver::atoms::GET_LOCATION_IN_VIEW), | 146 frame, webdriver::atoms::asString(webdriver::atoms::GET_LOCATION_IN_VIEW), |
| 145 args, &result); | 147 args, &result); |
| 146 if (status.IsError()) | 148 if (status.IsError()) |
| 147 return status; | 149 return status; |
| 148 if (!ParseFromValue(result.get(), &tmp_location)) | 150 if (!ParseFromValue(result.get(), &tmp_location)) { |
| 149 return Status(kUnknownError, "fail to parse value of GET_LOCATION_IN_VIEW"); | 151 return Status(kUnknownError, |
| 152 "failed to parse value of GET_LOCATION_IN_VIEW"); |
| 153 } |
| 150 if (verify_clickable) { | 154 if (verify_clickable) { |
| 151 WebPoint middle = tmp_location; | 155 WebPoint middle = tmp_location; |
| 152 middle.Offset(region.Width() / 2, region.Height() / 2); | 156 middle.Offset(region.Width() / 2, region.Height() / 2); |
| 153 status = VerifyElementClickable(frame, web_view, element_id, middle); | 157 status = VerifyElementClickable(frame, web_view, element_id, middle); |
| 154 if (status.IsError()) | 158 if (status.IsError()) |
| 155 return status; | 159 return status; |
| 156 } | 160 } |
| 157 *location = tmp_location; | 161 *location = tmp_location; |
| 158 return Status(kOk); | 162 return Status(kOk); |
| 159 } | 163 } |
| 160 | 164 |
| 161 Status GetElementEffectiveStyle( | 165 Status GetElementEffectiveStyle( |
| 162 const std::string& frame, | 166 const std::string& frame, |
| 163 WebView* web_view, | 167 WebView* web_view, |
| 164 const std::string& element_id, | 168 const std::string& element_id, |
| 165 const std::string& property, | 169 const std::string& property, |
| 166 std::string* value) { | 170 std::string* value) { |
| 167 base::ListValue args; | 171 base::ListValue args; |
| 168 args.Append(CreateElement(element_id)); | 172 args.Append(CreateElement(element_id)); |
| 169 args.AppendString(property); | 173 args.AppendString(property); |
| 170 scoped_ptr<base::Value> result; | 174 scoped_ptr<base::Value> result; |
| 171 Status status = web_view->CallFunction( | 175 Status status = web_view->CallFunction( |
| 172 frame, webdriver::atoms::asString(webdriver::atoms::GET_EFFECTIVE_STYLE), | 176 frame, webdriver::atoms::asString(webdriver::atoms::GET_EFFECTIVE_STYLE), |
| 173 args, &result); | 177 args, &result); |
| 174 if (status.IsError()) | 178 if (status.IsError()) |
| 175 return status; | 179 return status; |
| 176 if (!result->GetAsString(value)) | 180 if (!result->GetAsString(value)) { |
| 177 return Status(kUnknownError, "fail to parse value of GET_EFFECTIVE_STYLE"); | 181 return Status(kUnknownError, |
| 182 "failed to parse value of GET_EFFECTIVE_STYLE"); |
| 183 } |
| 178 return Status(kOk); | 184 return Status(kOk); |
| 179 } | 185 } |
| 180 | 186 |
| 181 Status GetElementBorder( | 187 Status GetElementBorder( |
| 182 const std::string& frame, | 188 const std::string& frame, |
| 183 WebView* web_view, | 189 WebView* web_view, |
| 184 const std::string& element_id, | 190 const std::string& element_id, |
| 185 int* border_left, | 191 int* border_left, |
| 186 int* border_top) { | 192 int* border_top) { |
| 187 std::string border_left_str; | 193 std::string border_left_str; |
| 188 Status status = GetElementEffectiveStyle( | 194 Status status = GetElementEffectiveStyle( |
| 189 frame, web_view, element_id, "border-left-width", &border_left_str); | 195 frame, web_view, element_id, "border-left-width", &border_left_str); |
| 190 if (status.IsError()) | 196 if (status.IsError()) |
| 191 return status; | 197 return status; |
| 192 std::string border_top_str; | 198 std::string border_top_str; |
| 193 status = GetElementEffectiveStyle( | 199 status = GetElementEffectiveStyle( |
| 194 frame, web_view, element_id, "border-top-width", &border_top_str); | 200 frame, web_view, element_id, "border-top-width", &border_top_str); |
| 195 if (status.IsError()) | 201 if (status.IsError()) |
| 196 return status; | 202 return status; |
| 197 int border_left_tmp = -1; | 203 int border_left_tmp = -1; |
| 198 int border_top_tmp = -1; | 204 int border_top_tmp = -1; |
| 199 base::StringToInt(border_left_str, &border_left_tmp); | 205 base::StringToInt(border_left_str, &border_left_tmp); |
| 200 base::StringToInt(border_top_str, &border_top_tmp); | 206 base::StringToInt(border_top_str, &border_top_tmp); |
| 201 if (border_left_tmp == -1 || border_top_tmp == -1) | 207 if (border_left_tmp == -1 || border_top_tmp == -1) |
| 202 return Status(kUnknownError, "fail to get border width of element"); | 208 return Status(kUnknownError, "failed to get border width of element"); |
| 203 *border_left = border_left_tmp; | 209 *border_left = border_left_tmp; |
| 204 *border_top = border_top_tmp; | 210 *border_top = border_top_tmp; |
| 205 return Status(kOk); | 211 return Status(kOk); |
| 206 } | 212 } |
| 207 | 213 |
| 208 } // namespace | 214 } // namespace |
| 209 | 215 |
| 210 base::DictionaryValue* CreateElement(const std::string& element_id) { | 216 base::DictionaryValue* CreateElement(const std::string& element_id) { |
| 211 base::DictionaryValue* element = new base::DictionaryValue(); | 217 base::DictionaryValue* element = new base::DictionaryValue(); |
| 212 element->SetString(kElementKey, element_id); | 218 element->SetString(kElementKey, element_id); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 | 339 |
| 334 status = ScrollElementRegionIntoView( | 340 status = ScrollElementRegionIntoView( |
| 335 session, web_view, element_id, rect, | 341 session, web_view, element_id, rect, |
| 336 true /* center */, true /* verify_clickable */, location); | 342 true /* center */, true /* verify_clickable */, location); |
| 337 if (status.IsError()) | 343 if (status.IsError()) |
| 338 return status; | 344 return status; |
| 339 location->Offset(rect.Width() / 2, rect.Height() / 2); | 345 location->Offset(rect.Width() / 2, rect.Height() / 2); |
| 340 return Status(kOk); | 346 return Status(kOk); |
| 341 } | 347 } |
| 342 | 348 |
| 349 Status GetElementEffectiveStyle( |
| 350 Session* session, |
| 351 WebView* web_view, |
| 352 const std::string& element_id, |
| 353 const std::string& property_name, |
| 354 std::string* property_value) { |
| 355 return GetElementEffectiveStyle(session->GetCurrentFrameId(), web_view, |
| 356 element_id, property_name, property_value); |
| 357 } |
| 358 |
| 343 Status GetElementRegion( | 359 Status GetElementRegion( |
| 344 Session* session, | 360 Session* session, |
| 345 WebView* web_view, | 361 WebView* web_view, |
| 346 const std::string& element_id, | 362 const std::string& element_id, |
| 347 WebRect* rect) { | 363 WebRect* rect) { |
| 348 base::ListValue args; | 364 base::ListValue args; |
| 349 args.Append(CreateElement(element_id)); | 365 args.Append(CreateElement(element_id)); |
| 350 scoped_ptr<base::Value> result; | 366 scoped_ptr<base::Value> result; |
| 351 Status status = web_view->CallFunction( | 367 Status status = web_view->CallFunction( |
| 352 session->GetCurrentFrameId(), kGetElementRegionScript, args, &result); | 368 session->GetCurrentFrameId(), kGetElementRegionScript, args, &result); |
| 353 if (status.IsError()) | 369 if (status.IsError()) |
| 354 return status; | 370 return status; |
| 355 if (!ParseFromValue(result.get(), rect)) { | 371 if (!ParseFromValue(result.get(), rect)) { |
| 356 return Status(kUnknownError, | 372 return Status(kUnknownError, |
| 357 "fail to parse value of getElementRegion"); | 373 "failed to parse value of getElementRegion"); |
| 358 } | 374 } |
| 359 return Status(kOk); | 375 return Status(kOk); |
| 360 } | 376 } |
| 361 | 377 |
| 362 Status GetElementTagName( | 378 Status GetElementTagName( |
| 363 Session* session, | 379 Session* session, |
| 364 WebView* web_view, | 380 WebView* web_view, |
| 365 const std::string& element_id, | 381 const std::string& element_id, |
| 366 std::string* name) { | 382 std::string* name) { |
| 367 base::ListValue args; | 383 base::ListValue args; |
| 368 args.Append(CreateElement(element_id)); | 384 args.Append(CreateElement(element_id)); |
| 369 scoped_ptr<base::Value> result; | 385 scoped_ptr<base::Value> result; |
| 370 Status status = web_view->CallFunction( | 386 Status status = web_view->CallFunction( |
| 371 session->GetCurrentFrameId(), | 387 session->GetCurrentFrameId(), |
| 372 "function(elem) { return elem.tagName.toLowerCase(); }", | 388 "function(elem) { return elem.tagName.toLowerCase(); }", |
| 373 args, &result); | 389 args, &result); |
| 374 if (status.IsError()) | 390 if (status.IsError()) |
| 375 return status; | 391 return status; |
| 376 if (!result->GetAsString(name)) | 392 if (!result->GetAsString(name)) |
| 377 return Status(kUnknownError, "fail to get element tag name"); | 393 return Status(kUnknownError, "failed to get element tag name"); |
| 378 return Status(kOk); | 394 return Status(kOk); |
| 379 } | 395 } |
| 380 | 396 |
| 381 Status GetElementSize( | 397 Status GetElementSize( |
| 382 Session* session, | 398 Session* session, |
| 383 WebView* web_view, | 399 WebView* web_view, |
| 384 const std::string& element_id, | 400 const std::string& element_id, |
| 385 WebSize* size) { | 401 WebSize* size) { |
| 386 base::ListValue args; | 402 base::ListValue args; |
| 387 args.Append(CreateElement(element_id)); | 403 args.Append(CreateElement(element_id)); |
| 388 scoped_ptr<base::Value> result; | 404 scoped_ptr<base::Value> result; |
| 389 Status status = CallAtomsJs( | 405 Status status = CallAtomsJs( |
| 390 session->GetCurrentFrameId(), web_view, webdriver::atoms::GET_SIZE, | 406 session->GetCurrentFrameId(), web_view, webdriver::atoms::GET_SIZE, |
| 391 args, &result); | 407 args, &result); |
| 392 if (status.IsError()) | 408 if (status.IsError()) |
| 393 return status; | 409 return status; |
| 394 if (!ParseFromValue(result.get(), size)) | 410 if (!ParseFromValue(result.get(), size)) |
| 395 return Status(kUnknownError, "fail to parse value of GET_SIZE"); | 411 return Status(kUnknownError, "failed to parse value of GET_SIZE"); |
| 396 return Status(kOk); | 412 return Status(kOk); |
| 397 } | 413 } |
| 398 | 414 |
| 399 Status IsElementDisplayed( | 415 Status IsElementDisplayed( |
| 400 Session* session, | 416 Session* session, |
| 401 WebView* web_view, | 417 WebView* web_view, |
| 402 const std::string& element_id, | 418 const std::string& element_id, |
| 403 bool ignore_opacity, | 419 bool ignore_opacity, |
| 404 bool* is_displayed) { | 420 bool* is_displayed) { |
| 405 base::ListValue args; | 421 base::ListValue args; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 bool* is_togglable) { | 475 bool* is_togglable) { |
| 460 base::ListValue args; | 476 base::ListValue args; |
| 461 args.Append(CreateElement(element_id)); | 477 args.Append(CreateElement(element_id)); |
| 462 scoped_ptr<base::Value> result; | 478 scoped_ptr<base::Value> result; |
| 463 Status status = web_view->CallFunction( | 479 Status status = web_view->CallFunction( |
| 464 session->GetCurrentFrameId(), kIsOptionElementToggleableScript, | 480 session->GetCurrentFrameId(), kIsOptionElementToggleableScript, |
| 465 args, &result); | 481 args, &result); |
| 466 if (status.IsError()) | 482 if (status.IsError()) |
| 467 return status; | 483 return status; |
| 468 if (!result->GetAsBoolean(is_togglable)) | 484 if (!result->GetAsBoolean(is_togglable)) |
| 469 return Status(kUnknownError, "fail check if option togglable or not"); | 485 return Status(kUnknownError, "failed check if option togglable or not"); |
| 470 return Status(kOk); | 486 return Status(kOk); |
| 471 } | 487 } |
| 472 | 488 |
| 473 Status SetOptionElementSelected( | 489 Status SetOptionElementSelected( |
| 474 Session* session, | 490 Session* session, |
| 475 WebView* web_view, | 491 WebView* web_view, |
| 476 const std::string& element_id, | 492 const std::string& element_id, |
| 477 bool selected) { | 493 bool selected) { |
| 478 // TODO(171034): need to fix throwing error if an alert is triggered. | 494 // TODO(171034): need to fix throwing error if an alert is triggered. |
| 479 base::ListValue args; | 495 base::ListValue args; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 540 scoped_ptr<base::Value> result; | 556 scoped_ptr<base::Value> result; |
| 541 status = web_view->CallFunction( | 557 status = web_view->CallFunction( |
| 542 rit->parent_frame_id, kFindSubFrameScript, args, &result); | 558 rit->parent_frame_id, kFindSubFrameScript, args, &result); |
| 543 if (status.IsError()) | 559 if (status.IsError()) |
| 544 return status; | 560 return status; |
| 545 const base::DictionaryValue* element_dict; | 561 const base::DictionaryValue* element_dict; |
| 546 if (!result->GetAsDictionary(&element_dict)) | 562 if (!result->GetAsDictionary(&element_dict)) |
| 547 return Status(kUnknownError, "no element reference returned by script"); | 563 return Status(kUnknownError, "no element reference returned by script"); |
| 548 std::string frame_element_id; | 564 std::string frame_element_id; |
| 549 if (!element_dict->GetString(kElementKey, &frame_element_id)) | 565 if (!element_dict->GetString(kElementKey, &frame_element_id)) |
| 550 return Status(kUnknownError, "fail to locate a sub frame"); | 566 return Status(kUnknownError, "failed to locate a sub frame"); |
| 551 | 567 |
| 552 // Modify |region_offset| by the frame's border. | 568 // Modify |region_offset| by the frame's border. |
| 553 int border_left = -1; | 569 int border_left = -1; |
| 554 int border_top = -1; | 570 int border_top = -1; |
| 555 status = GetElementBorder( | 571 status = GetElementBorder( |
| 556 rit->parent_frame_id, web_view, frame_element_id, | 572 rit->parent_frame_id, web_view, frame_element_id, |
| 557 &border_left, &border_top); | 573 &border_left, &border_top); |
| 558 if (status.IsError()) | 574 if (status.IsError()) |
| 559 return status; | 575 return status; |
| 560 region_offset.Offset(border_left, border_top); | 576 region_offset.Offset(border_left, border_top); |
| 561 | 577 |
| 562 status = ScrollElementRegionIntoViewHelper( | 578 status = ScrollElementRegionIntoViewHelper( |
| 563 rit->parent_frame_id, web_view, frame_element_id, | 579 rit->parent_frame_id, web_view, frame_element_id, |
| 564 WebRect(region_offset, region_size), | 580 WebRect(region_offset, region_size), |
| 565 center, verify_clickable, ®ion_offset); | 581 center, verify_clickable, ®ion_offset); |
| 566 if (status.IsError()) | 582 if (status.IsError()) |
| 567 return status; | 583 return status; |
| 568 } | 584 } |
| 569 *location = region_offset; | 585 *location = region_offset; |
| 570 return Status(kOk); | 586 return Status(kOk); |
| 571 } | 587 } |
| OLD | NEW |