| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/renderer/accessibility/accessibility_node_serializer.h" | 5 #include "content/renderer/accessibility/accessibility_node_serializer.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 // |ancestor| is the *first* ancestor that isn't marked as | 39 // |ancestor| is the *first* ancestor that isn't marked as |
| 40 // accessibilityIsIgnored(). | 40 // accessibilityIsIgnored(). |
| 41 bool IsParentUnignoredOf(const WebAccessibilityObject& ancestor, | 41 bool IsParentUnignoredOf(const WebAccessibilityObject& ancestor, |
| 42 const WebAccessibilityObject& child) { | 42 const WebAccessibilityObject& child) { |
| 43 WebAccessibilityObject parent = child.parentObject(); | 43 WebAccessibilityObject parent = child.parentObject(); |
| 44 while (!parent.isDetached() && parent.accessibilityIsIgnored()) | 44 while (!parent.isDetached() && parent.accessibilityIsIgnored()) |
| 45 parent = parent.parentObject(); | 45 parent = parent.parentObject(); |
| 46 return parent.equals(ancestor); | 46 return parent.equals(ancestor); |
| 47 } | 47 } |
| 48 | 48 |
| 49 bool IsTrue(std::string html_value) { |
| 50 return LowerCaseEqualsASCII(html_value, "true"); |
| 51 } |
| 52 |
| 49 // Provides a conversion between the WebKit::WebAccessibilityRole and a role | 53 // Provides a conversion between the WebKit::WebAccessibilityRole and a role |
| 50 // supported on the Browser side. Listed alphabetically by the | 54 // supported on the Browser side. Listed alphabetically by the |
| 51 // WebKit::WebAccessibilityRole (except for default role). | 55 // WebKit::WebAccessibilityRole (except for default role). |
| 52 AccessibilityNodeData::Role ConvertRole(WebKit::WebAccessibilityRole role) { | 56 AccessibilityNodeData::Role ConvertRole(WebKit::WebAccessibilityRole role) { |
| 53 switch (role) { | 57 switch (role) { |
| 54 case WebKit::WebAccessibilityRoleAnnotation: | 58 case WebKit::WebAccessibilityRoleAnnotation: |
| 55 return AccessibilityNodeData::ROLE_ANNOTATION; | 59 return AccessibilityNodeData::ROLE_ANNOTATION; |
| 56 case WebKit::WebAccessibilityRoleApplication: | 60 case WebKit::WebAccessibilityRoleApplication: |
| 57 return AccessibilityNodeData::ROLE_APPLICATION; | 61 return AccessibilityNodeData::ROLE_APPLICATION; |
| 58 case WebKit::WebAccessibilityRoleApplicationAlert: | 62 case WebKit::WebAccessibilityRoleApplicationAlert: |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 state |= (1 << AccessibilityNodeData::STATE_VISITED); | 348 state |= (1 << AccessibilityNodeData::STATE_VISITED); |
| 345 | 349 |
| 346 return state; | 350 return state; |
| 347 } | 351 } |
| 348 | 352 |
| 349 } // Anonymous namespace | 353 } // Anonymous namespace |
| 350 | 354 |
| 351 void SerializeAccessibilityNode( | 355 void SerializeAccessibilityNode( |
| 352 const WebAccessibilityObject& src, | 356 const WebAccessibilityObject& src, |
| 353 AccessibilityNodeData* dst) { | 357 AccessibilityNodeData* dst) { |
| 354 dst->name = src.title(); | |
| 355 dst->role = ConvertRole(src.roleValue()); | 358 dst->role = ConvertRole(src.roleValue()); |
| 356 dst->state = ConvertState(src); | 359 dst->state = ConvertState(src); |
| 357 dst->location = src.boundingBoxRect(); | 360 dst->location = src.boundingBoxRect(); |
| 358 dst->id = src.axID(); | 361 dst->id = src.axID(); |
| 362 std::string name = UTF16ToUTF8(src.title()); |
| 359 | 363 |
| 360 if (src.valueDescription().length()) | 364 std::string value; |
| 361 dst->value = src.valueDescription(); | 365 if (src.valueDescription().length()) { |
| 362 else | 366 dst->AddStringAttribute(dst->ATTR_VALUE, |
| 363 dst->value = src.stringValue(); | 367 UTF16ToUTF8(src.valueDescription())); |
| 368 } else { |
| 369 dst->AddStringAttribute(dst->ATTR_VALUE, UTF16ToUTF8(src.stringValue())); |
| 370 } |
| 364 | 371 |
| 365 if (dst->role == AccessibilityNodeData::ROLE_COLOR_WELL) { | 372 if (dst->role == AccessibilityNodeData::ROLE_COLOR_WELL) { |
| 366 int r, g, b; | 373 int r, g, b; |
| 367 src.colorValue(r, g, b); | 374 src.colorValue(r, g, b); |
| 368 dst->int_attributes[dst->ATTR_COLOR_VALUE_RED] = r; | 375 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_RED, r); |
| 369 dst->int_attributes[dst->ATTR_COLOR_VALUE_GREEN] = g; | 376 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_GREEN, g); |
| 370 dst->int_attributes[dst->ATTR_COLOR_VALUE_BLUE] = b; | 377 dst->AddIntAttribute(dst->ATTR_COLOR_VALUE_BLUE, b); |
| 371 } | 378 } |
| 372 | 379 |
| 373 if (src.accessKey().length()) | 380 if (src.accessKey().length()) |
| 374 dst->string_attributes[dst->ATTR_ACCESS_KEY] = src.accessKey(); | 381 dst->AddStringAttribute(dst->ATTR_ACCESS_KEY, UTF16ToUTF8(src.accessKey())); |
| 375 if (src.actionVerb().length()) | 382 if (src.actionVerb().length()) |
| 376 dst->string_attributes[dst->ATTR_ACTION] = src.actionVerb(); | 383 dst->AddStringAttribute(dst->ATTR_ACTION, UTF16ToUTF8(src.actionVerb())); |
| 377 if (src.isAriaReadOnly()) | 384 if (src.isAriaReadOnly()) |
| 378 dst->bool_attributes[dst->ATTR_ARIA_READONLY] = true; | 385 dst->AddBoolAttribute(dst->ATTR_ARIA_READONLY, true); |
| 379 if (src.isButtonStateMixed()) | 386 if (src.isButtonStateMixed()) |
| 380 dst->bool_attributes[dst->ATTR_BUTTON_MIXED] = true; | 387 dst->AddBoolAttribute(dst->ATTR_BUTTON_MIXED, true); |
| 381 if (src.canSetValueAttribute()) | 388 if (src.canSetValueAttribute()) |
| 382 dst->bool_attributes[dst->ATTR_CAN_SET_VALUE] = true; | 389 dst->AddBoolAttribute(dst->ATTR_CAN_SET_VALUE, true); |
| 383 if (src.accessibilityDescription().length()) | 390 if (src.accessibilityDescription().length()) { |
| 384 dst->string_attributes[dst->ATTR_DESCRIPTION] = | 391 dst->AddStringAttribute(dst->ATTR_DESCRIPTION, |
| 385 src.accessibilityDescription(); | 392 UTF16ToUTF8(src.accessibilityDescription())); |
| 386 if (src.hasComputedStyle()) | 393 } |
| 387 dst->string_attributes[dst->ATTR_DISPLAY] = src.computedStyleDisplay(); | 394 if (src.hasComputedStyle()) { |
| 395 dst->AddStringAttribute(dst->ATTR_DISPLAY, |
| 396 UTF16ToUTF8(src.computedStyleDisplay())); |
| 397 } |
| 388 if (src.helpText().length()) | 398 if (src.helpText().length()) |
| 389 dst->string_attributes[dst->ATTR_HELP] = src.helpText(); | 399 dst->AddStringAttribute(dst->ATTR_HELP, UTF16ToUTF8(src.helpText())); |
| 390 if (src.keyboardShortcut().length()) | 400 if (src.keyboardShortcut().length()) { |
| 391 dst->string_attributes[dst->ATTR_SHORTCUT] = src.keyboardShortcut(); | 401 dst->AddStringAttribute(dst->ATTR_SHORTCUT, |
| 402 UTF16ToUTF8(src.keyboardShortcut())); |
| 403 } |
| 392 if (!src.titleUIElement().isDetached()) { | 404 if (!src.titleUIElement().isDetached()) { |
| 393 dst->int_attributes[dst->ATTR_TITLE_UI_ELEMENT] = | 405 dst->AddIntAttribute(dst->ATTR_TITLE_UI_ELEMENT, |
| 394 src.titleUIElement().axID(); | 406 src.titleUIElement().axID()); |
| 395 } | 407 } |
| 396 if (!src.url().isEmpty()) | 408 if (!src.url().isEmpty()) |
| 397 dst->string_attributes[dst->ATTR_URL] = src.url().spec().utf16(); | 409 dst->AddStringAttribute(dst->ATTR_URL, src.url().spec()); |
| 398 | 410 |
| 399 if (dst->role == dst->ROLE_HEADING) | 411 if (dst->role == dst->ROLE_HEADING) |
| 400 dst->int_attributes[dst->ATTR_HIERARCHICAL_LEVEL] = src.headingLevel(); | 412 dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.headingLevel()); |
| 401 else if ((dst->role == dst->ROLE_TREE_ITEM || dst->role == dst->ROLE_ROW) && | 413 else if ((dst->role == dst->ROLE_TREE_ITEM || dst->role == dst->ROLE_ROW) && |
| 402 src.hierarchicalLevel() > 0) { | 414 src.hierarchicalLevel() > 0) { |
| 403 dst->int_attributes[dst->ATTR_HIERARCHICAL_LEVEL] = src.hierarchicalLevel(); | 415 dst->AddIntAttribute(dst->ATTR_HIERARCHICAL_LEVEL, src.hierarchicalLevel()); |
| 404 } | 416 } |
| 405 | 417 |
| 406 // Treat the active list box item as focused. | 418 // Treat the active list box item as focused. |
| 407 if (dst->role == dst->ROLE_LISTBOX_OPTION && src.isSelectedOptionActive()) | 419 if (dst->role == dst->ROLE_LISTBOX_OPTION && src.isSelectedOptionActive()) |
| 408 dst->state |= (1 << AccessibilityNodeData::STATE_FOCUSED); | 420 dst->state |= (1 << AccessibilityNodeData::STATE_FOCUSED); |
| 409 | 421 |
| 410 if (src.canvasHasFallbackContent()) | 422 if (src.canvasHasFallbackContent()) |
| 411 dst->role = AccessibilityNodeData::ROLE_CANVAS_WITH_FALLBACK_CONTENT; | 423 dst->role = AccessibilityNodeData::ROLE_CANVAS_WITH_FALLBACK_CONTENT; |
| 412 | 424 |
| 413 WebNode node = src.node(); | 425 WebNode node = src.node(); |
| 414 bool is_iframe = false; | 426 bool is_iframe = false; |
| 427 std::string live_atomic; |
| 428 std::string live_busy; |
| 429 std::string live_status; |
| 430 std::string live_relevant; |
| 415 | 431 |
| 416 if (!node.isNull() && node.isElementNode()) { | 432 if (!node.isNull() && node.isElementNode()) { |
| 417 WebElement element = node.to<WebElement>(); | 433 WebElement element = node.to<WebElement>(); |
| 418 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); | 434 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); |
| 419 | 435 |
| 420 if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true")) | 436 if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true")) |
| 421 dst->state |= (1 << AccessibilityNodeData::STATE_EXPANDED); | 437 dst->state |= (1 << AccessibilityNodeData::STATE_EXPANDED); |
| 422 | 438 |
| 423 // TODO(ctguil): The tagName in WebKit is lower cased but | 439 // TODO(ctguil): The tagName in WebKit is lower cased but |
| 424 // HTMLElement::nodeName calls localNameUpper. Consider adding | 440 // HTMLElement::nodeName calls localNameUpper. Consider adding |
| 425 // a WebElement method that returns the original lower cased tagName. | 441 // a WebElement method that returns the original lower cased tagName. |
| 426 dst->string_attributes[dst->ATTR_HTML_TAG] = | 442 dst->AddStringAttribute( |
| 427 StringToLowerASCII(string16(element.tagName())); | 443 dst->ATTR_HTML_TAG, |
| 444 StringToLowerASCII(UTF16ToUTF8(element.tagName()))); |
| 428 for (unsigned i = 0; i < element.attributeCount(); ++i) { | 445 for (unsigned i = 0; i < element.attributeCount(); ++i) { |
| 429 string16 name = StringToLowerASCII(string16( | 446 std::string name = StringToLowerASCII(UTF16ToUTF8( |
| 430 element.attributeLocalName(i))); | 447 element.attributeLocalName(i))); |
| 431 string16 value = element.attributeValue(i); | 448 std::string value = UTF16ToUTF8(element.attributeValue(i)); |
| 432 dst->html_attributes.push_back( | 449 dst->html_attributes.push_back(std::make_pair(name, value)); |
| 433 std::pair<string16, string16>(name, value)); | |
| 434 } | 450 } |
| 435 | 451 |
| 436 if (dst->role == dst->ROLE_EDITABLE_TEXT || | 452 if (dst->role == dst->ROLE_EDITABLE_TEXT || |
| 437 dst->role == dst->ROLE_TEXTAREA || | 453 dst->role == dst->ROLE_TEXTAREA || |
| 438 dst->role == dst->ROLE_TEXT_FIELD) { | 454 dst->role == dst->ROLE_TEXT_FIELD) { |
| 439 dst->int_attributes[dst->ATTR_TEXT_SEL_START] = src.selectionStart(); | 455 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_START, src.selectionStart()); |
| 440 dst->int_attributes[dst->ATTR_TEXT_SEL_END] = src.selectionEnd(); | 456 dst->AddIntAttribute(dst->ATTR_TEXT_SEL_END, src.selectionEnd()); |
| 441 | 457 |
| 442 WebVector<int> src_line_breaks; | 458 WebVector<int> src_line_breaks; |
| 443 src.lineBreaks(src_line_breaks); | 459 src.lineBreaks(src_line_breaks); |
| 444 dst->line_breaks.reserve(src_line_breaks.size()); | 460 if (src_line_breaks.size() > 0) { |
| 445 for (size_t i = 0; i < src_line_breaks.size(); ++i) | 461 std::vector<int32> line_breaks; |
| 446 dst->line_breaks.push_back(src_line_breaks[i]); | 462 line_breaks.reserve(src_line_breaks.size()); |
| 463 for (size_t i = 0; i < src_line_breaks.size(); ++i) |
| 464 line_breaks.push_back(src_line_breaks[i]); |
| 465 dst->AddIntListAttribute(dst->ATTR_LINE_BREAKS, line_breaks); |
| 466 } |
| 447 } | 467 } |
| 448 | 468 |
| 449 // ARIA role. | 469 // ARIA role. |
| 450 if (element.hasAttribute("role")) { | 470 if (element.hasAttribute("role")) { |
| 451 dst->string_attributes[dst->ATTR_ROLE] = element.getAttribute("role"); | 471 dst->AddStringAttribute(dst->ATTR_ROLE, |
| 472 UTF16ToUTF8(element.getAttribute("role"))); |
| 452 } | 473 } |
| 453 | 474 |
| 454 // Live region attributes | 475 // Live region attributes |
| 455 if (element.hasAttribute("aria-atomic")) { | 476 live_atomic = UTF16ToUTF8(element.getAttribute("aria-atomic")); |
| 456 dst->bool_attributes[dst->ATTR_LIVE_ATOMIC] = | 477 live_busy = UTF16ToUTF8(element.getAttribute("aria-busy")); |
| 457 LowerCaseEqualsASCII(element.getAttribute("aria-atomic"), "true"); | 478 live_status = UTF16ToUTF8(element.getAttribute("aria-live")); |
| 458 } | 479 live_relevant = UTF16ToUTF8(element.getAttribute("aria-relevant")); |
| 459 if (element.hasAttribute("aria-busy")) { | |
| 460 dst->bool_attributes[dst->ATTR_LIVE_BUSY] = | |
| 461 LowerCaseEqualsASCII(element.getAttribute("aria-busy"), "true"); | |
| 462 } | |
| 463 if (element.hasAttribute("aria-live")) { | |
| 464 dst->string_attributes[dst->ATTR_LIVE_STATUS] = | |
| 465 element.getAttribute("aria-live"); | |
| 466 } | |
| 467 if (element.hasAttribute("aria-relevant")) { | |
| 468 dst->string_attributes[dst->ATTR_LIVE_RELEVANT] = | |
| 469 element.getAttribute("aria-relevant"); | |
| 470 } | |
| 471 } | 480 } |
| 472 | 481 |
| 473 // Walk up the parent chain to set live region attributes of containers | 482 // Walk up the parent chain to set live region attributes of containers |
| 474 | 483 std::string container_live_atomic; |
| 484 std::string container_live_busy; |
| 485 std::string container_live_status; |
| 486 std::string container_live_relevant; |
| 475 WebAccessibilityObject container_accessible = src; | 487 WebAccessibilityObject container_accessible = src; |
| 476 while (!container_accessible.isDetached()) { | 488 while (!container_accessible.isDetached()) { |
| 477 WebNode container_node = container_accessible.node(); | 489 WebNode container_node = container_accessible.node(); |
| 478 if (!container_node.isNull() && container_node.isElementNode()) { | 490 if (!container_node.isNull() && container_node.isElementNode()) { |
| 479 WebElement container_elem = | 491 WebElement container_elem = container_node.to<WebElement>(); |
| 480 container_node.to<WebElement>(); | |
| 481 if (container_elem.hasAttribute("aria-atomic") && | 492 if (container_elem.hasAttribute("aria-atomic") && |
| 482 dst->bool_attributes.find(dst->ATTR_CONTAINER_LIVE_ATOMIC) == | 493 container_live_atomic.empty()) { |
| 483 dst->bool_attributes.end()) { | 494 container_live_atomic = |
| 484 dst->bool_attributes[dst->ATTR_CONTAINER_LIVE_ATOMIC] = | 495 UTF16ToUTF8(container_elem.getAttribute("aria-atomic")); |
| 485 LowerCaseEqualsASCII(container_elem.getAttribute("aria-atomic"), | |
| 486 "true"); | |
| 487 } | 496 } |
| 488 if (container_elem.hasAttribute("aria-busy") && | 497 if (container_elem.hasAttribute("aria-busy") && |
| 489 dst->bool_attributes.find(dst->ATTR_CONTAINER_LIVE_BUSY) == | 498 container_live_busy.empty()) { |
| 490 dst->bool_attributes.end()) { | 499 container_live_busy = |
| 491 dst->bool_attributes[dst->ATTR_CONTAINER_LIVE_BUSY] = | 500 UTF16ToUTF8(container_elem.getAttribute("aria-busy")); |
| 492 LowerCaseEqualsASCII(container_elem.getAttribute("aria-busy"), | |
| 493 "true"); | |
| 494 } | 501 } |
| 495 if (container_elem.hasAttribute("aria-live") && | 502 if (container_elem.hasAttribute("aria-live") && |
| 496 dst->string_attributes.find(dst->ATTR_CONTAINER_LIVE_STATUS) == | 503 container_live_status.empty()) { |
| 497 dst->string_attributes.end()) { | 504 container_live_status = |
| 498 dst->string_attributes[dst->ATTR_CONTAINER_LIVE_STATUS] = | 505 UTF16ToUTF8(container_elem.getAttribute("aria-live")); |
| 499 container_elem.getAttribute("aria-live"); | |
| 500 } | 506 } |
| 501 if (container_elem.hasAttribute("aria-relevant") && | 507 if (container_elem.hasAttribute("aria-relevant") && |
| 502 dst->string_attributes.find(dst->ATTR_CONTAINER_LIVE_RELEVANT) == | 508 container_live_relevant.empty()) { |
| 503 dst->string_attributes.end()) { | 509 container_live_relevant = |
| 504 dst->string_attributes[dst->ATTR_CONTAINER_LIVE_RELEVANT] = | 510 UTF16ToUTF8(container_elem.getAttribute("aria-relevant")); |
| 505 container_elem.getAttribute("aria-relevant"); | |
| 506 } | 511 } |
| 507 } | 512 } |
| 508 container_accessible = container_accessible.parentObject(); | 513 container_accessible = container_accessible.parentObject(); |
| 509 } | 514 } |
| 510 | 515 |
| 516 if (!live_atomic.empty()) |
| 517 dst->AddBoolAttribute(dst->ATTR_LIVE_ATOMIC, IsTrue(live_atomic)); |
| 518 if (!live_busy.empty()) |
| 519 dst->AddBoolAttribute(dst->ATTR_LIVE_BUSY, IsTrue(live_busy)); |
| 520 if (!live_status.empty()) |
| 521 dst->AddStringAttribute(dst->ATTR_LIVE_STATUS, live_status); |
| 522 if (!live_relevant.empty()) |
| 523 dst->AddStringAttribute(dst->ATTR_LIVE_RELEVANT, live_relevant); |
| 524 |
| 525 if (!container_live_atomic.empty()) { |
| 526 dst->AddBoolAttribute(dst->ATTR_CONTAINER_LIVE_ATOMIC, |
| 527 IsTrue(container_live_atomic)); |
| 528 } |
| 529 if (!container_live_busy.empty()) { |
| 530 dst->AddBoolAttribute(dst->ATTR_CONTAINER_LIVE_BUSY, |
| 531 IsTrue(container_live_busy)); |
| 532 } |
| 533 if (!container_live_status.empty()) { |
| 534 dst->AddStringAttribute(dst->ATTR_CONTAINER_LIVE_STATUS, |
| 535 container_live_status); |
| 536 } |
| 537 if (!container_live_relevant.empty()) { |
| 538 dst->AddStringAttribute(dst->ATTR_CONTAINER_LIVE_RELEVANT, |
| 539 container_live_relevant); |
| 540 } |
| 541 |
| 511 if (dst->role == dst->ROLE_PROGRESS_INDICATOR || | 542 if (dst->role == dst->ROLE_PROGRESS_INDICATOR || |
| 512 dst->role == dst->ROLE_SCROLLBAR || | 543 dst->role == dst->ROLE_SCROLLBAR || |
| 513 dst->role == dst->ROLE_SLIDER || | 544 dst->role == dst->ROLE_SLIDER || |
| 514 dst->role == dst->ROLE_SPIN_BUTTON) { | 545 dst->role == dst->ROLE_SPIN_BUTTON) { |
| 515 dst->float_attributes[dst->ATTR_VALUE_FOR_RANGE] = src.valueForRange(); | 546 dst->AddFloatAttribute(dst->ATTR_VALUE_FOR_RANGE, src.valueForRange()); |
| 516 dst->float_attributes[dst->ATTR_MAX_VALUE_FOR_RANGE] = | 547 dst->AddFloatAttribute(dst->ATTR_MAX_VALUE_FOR_RANGE, |
| 517 src.maxValueForRange(); | 548 src.maxValueForRange()); |
| 518 dst->float_attributes[dst->ATTR_MIN_VALUE_FOR_RANGE] = | 549 dst->AddFloatAttribute(dst->ATTR_MIN_VALUE_FOR_RANGE, |
| 519 src.minValueForRange(); | 550 src.minValueForRange()); |
| 520 } | 551 } |
| 521 | 552 |
| 522 if (dst->role == dst->ROLE_DOCUMENT || | 553 if (dst->role == dst->ROLE_DOCUMENT || |
| 523 dst->role == dst->ROLE_WEB_AREA) { | 554 dst->role == dst->ROLE_WEB_AREA) { |
| 524 dst->string_attributes[dst->ATTR_HTML_TAG] = ASCIIToUTF16("#document"); | 555 dst->AddStringAttribute(dst->ATTR_HTML_TAG, "#document"); |
| 525 const WebDocument& document = src.document(); | 556 const WebDocument& document = src.document(); |
| 526 if (dst->name.empty()) | 557 if (name.empty()) |
| 527 dst->name = document.title(); | 558 name = UTF16ToUTF8(document.title()); |
| 528 dst->string_attributes[dst->ATTR_DOC_TITLE] = document.title(); | 559 dst->AddStringAttribute(dst->ATTR_DOC_TITLE, UTF16ToUTF8(document.title())); |
| 529 dst->string_attributes[dst->ATTR_DOC_URL] = document.url().spec().utf16(); | 560 dst->AddStringAttribute(dst->ATTR_DOC_URL, document.url().spec()); |
| 530 dst->string_attributes[dst->ATTR_DOC_MIMETYPE] = | 561 dst->AddStringAttribute( |
| 531 ASCIIToUTF16(document.isXHTMLDocument() ? "text/xhtml" : "text/html"); | 562 dst->ATTR_DOC_MIMETYPE, |
| 532 dst->bool_attributes[dst->ATTR_DOC_LOADED] = src.isLoaded(); | 563 document.isXHTMLDocument() ? "text/xhtml" : "text/html"); |
| 533 dst->float_attributes[dst->ATTR_DOC_LOADING_PROGRESS] = | 564 dst->AddBoolAttribute(dst->ATTR_DOC_LOADED, src.isLoaded()); |
| 534 src.estimatedLoadingProgress(); | 565 dst->AddFloatAttribute(dst->ATTR_DOC_LOADING_PROGRESS, |
| 566 src.estimatedLoadingProgress()); |
| 535 | 567 |
| 536 const WebDocumentType& doctype = document.doctype(); | 568 const WebDocumentType& doctype = document.doctype(); |
| 537 if (!doctype.isNull()) | 569 if (!doctype.isNull()) { |
| 538 dst->string_attributes[dst->ATTR_DOC_DOCTYPE] = doctype.name(); | 570 dst->AddStringAttribute(dst->ATTR_DOC_DOCTYPE, |
| 571 UTF16ToUTF8(doctype.name())); |
| 572 } |
| 539 | 573 |
| 540 const gfx::Size& scroll_offset = document.frame()->scrollOffset(); | 574 const gfx::Size& scroll_offset = document.frame()->scrollOffset(); |
| 541 dst->int_attributes[dst->ATTR_SCROLL_X] = scroll_offset.width(); | 575 dst->AddIntAttribute(dst->ATTR_SCROLL_X, scroll_offset.width()); |
| 542 dst->int_attributes[dst->ATTR_SCROLL_Y] = scroll_offset.height(); | 576 dst->AddIntAttribute(dst->ATTR_SCROLL_Y, scroll_offset.height()); |
| 543 | 577 |
| 544 const gfx::Size& min_offset = document.frame()->minimumScrollOffset(); | 578 const gfx::Size& min_offset = document.frame()->minimumScrollOffset(); |
| 545 dst->int_attributes[dst->ATTR_SCROLL_X_MIN] = min_offset.width(); | 579 dst->AddIntAttribute(dst->ATTR_SCROLL_X_MIN, min_offset.width()); |
| 546 dst->int_attributes[dst->ATTR_SCROLL_Y_MIN] = min_offset.height(); | 580 dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MIN, min_offset.height()); |
| 547 | 581 |
| 548 const gfx::Size& max_offset = document.frame()->maximumScrollOffset(); | 582 const gfx::Size& max_offset = document.frame()->maximumScrollOffset(); |
| 549 dst->int_attributes[dst->ATTR_SCROLL_X_MAX] = max_offset.width(); | 583 dst->AddIntAttribute(dst->ATTR_SCROLL_X_MAX, max_offset.width()); |
| 550 dst->int_attributes[dst->ATTR_SCROLL_Y_MAX] = max_offset.height(); | 584 dst->AddIntAttribute(dst->ATTR_SCROLL_Y_MAX, max_offset.height()); |
| 551 } | 585 } |
| 552 | 586 |
| 553 if (dst->role == dst->ROLE_TABLE) { | 587 if (dst->role == dst->ROLE_TABLE) { |
| 554 int column_count = src.columnCount(); | 588 int column_count = src.columnCount(); |
| 555 int row_count = src.rowCount(); | 589 int row_count = src.rowCount(); |
| 556 if (column_count > 0 && row_count > 0) { | 590 if (column_count > 0 && row_count > 0) { |
| 557 std::set<int> unique_cell_id_set; | 591 std::set<int32> unique_cell_id_set; |
| 558 dst->int_attributes[dst->ATTR_TABLE_COLUMN_COUNT] = column_count; | 592 std::vector<int32> cell_ids; |
| 559 dst->int_attributes[dst->ATTR_TABLE_ROW_COUNT] = row_count; | 593 std::vector<int32> unique_cell_ids; |
| 594 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_COUNT, column_count); |
| 595 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_COUNT, row_count); |
| 560 WebAccessibilityObject header = src.headerContainerObject(); | 596 WebAccessibilityObject header = src.headerContainerObject(); |
| 561 if (!header.isDetached()) | 597 if (!header.isDetached()) |
| 562 dst->int_attributes[dst->ATTR_TABLE_HEADER_ID] = header.axID(); | 598 dst->AddIntAttribute(dst->ATTR_TABLE_HEADER_ID, header.axID()); |
| 563 for (int i = 0; i < column_count * row_count; ++i) { | 599 for (int i = 0; i < column_count * row_count; ++i) { |
| 564 WebAccessibilityObject cell = src.cellForColumnAndRow( | 600 WebAccessibilityObject cell = src.cellForColumnAndRow( |
| 565 i % column_count, i / column_count); | 601 i % column_count, i / column_count); |
| 566 int cell_id = -1; | 602 int cell_id = -1; |
| 567 if (!cell.isDetached()) { | 603 if (!cell.isDetached()) { |
| 568 cell_id = cell.axID(); | 604 cell_id = cell.axID(); |
| 569 if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) { | 605 if (unique_cell_id_set.find(cell_id) == unique_cell_id_set.end()) { |
| 570 unique_cell_id_set.insert(cell_id); | 606 unique_cell_id_set.insert(cell_id); |
| 571 dst->unique_cell_ids.push_back(cell_id); | 607 unique_cell_ids.push_back(cell_id); |
| 572 } | 608 } |
| 573 } | 609 } |
| 574 dst->cell_ids.push_back(cell_id); | 610 cell_ids.push_back(cell_id); |
| 575 } | 611 } |
| 612 dst->AddIntListAttribute(dst->ATTR_CELL_IDS, cell_ids); |
| 613 dst->AddIntListAttribute(dst->ATTR_UNIQUE_CELL_IDS, unique_cell_ids); |
| 576 } | 614 } |
| 577 } | 615 } |
| 578 | 616 |
| 579 if (dst->role == dst->ROLE_ROW) { | 617 if (dst->role == dst->ROLE_ROW) { |
| 580 dst->int_attributes[dst->ATTR_TABLE_ROW_INDEX] = src.rowIndex(); | 618 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_INDEX, src.rowIndex()); |
| 581 WebAccessibilityObject header = src.rowHeader(); | 619 WebAccessibilityObject header = src.rowHeader(); |
| 582 if (!header.isDetached()) | 620 if (!header.isDetached()) |
| 583 dst->int_attributes[dst->ATTR_TABLE_ROW_HEADER_ID] = header.axID(); | 621 dst->AddIntAttribute(dst->ATTR_TABLE_ROW_HEADER_ID, header.axID()); |
| 584 } | 622 } |
| 585 | 623 |
| 586 if (dst->role == dst->ROLE_COLUMN) { | 624 if (dst->role == dst->ROLE_COLUMN) { |
| 587 dst->int_attributes[dst->ATTR_TABLE_COLUMN_INDEX] = src.columnIndex(); | 625 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_INDEX, src.columnIndex()); |
| 588 WebAccessibilityObject header = src.columnHeader(); | 626 WebAccessibilityObject header = src.columnHeader(); |
| 589 if (!header.isDetached()) | 627 if (!header.isDetached()) |
| 590 dst->int_attributes[dst->ATTR_TABLE_COLUMN_HEADER_ID] = header.axID(); | 628 dst->AddIntAttribute(dst->ATTR_TABLE_COLUMN_HEADER_ID, header.axID()); |
| 591 } | 629 } |
| 592 | 630 |
| 593 if (dst->role == dst->ROLE_CELL || | 631 if (dst->role == dst->ROLE_CELL || |
| 594 dst->role == dst->ROLE_ROW_HEADER || | 632 dst->role == dst->ROLE_ROW_HEADER || |
| 595 dst->role == dst->ROLE_COLUMN_HEADER) { | 633 dst->role == dst->ROLE_COLUMN_HEADER) { |
| 596 dst->int_attributes[dst->ATTR_TABLE_CELL_COLUMN_INDEX] = | 634 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_COLUMN_INDEX, src.cellRowIndex()); |
| 597 src.cellColumnIndex(); | 635 dst->AddIntAttribute(dst->ATTR_TABLE_CELL_ROW_SPAN, src.cellRowSpan()); |
| 598 dst->int_attributes[dst->ATTR_TABLE_CELL_COLUMN_SPAN] = | |
| 599 src.cellColumnSpan(); | |
| 600 dst->int_attributes[dst->ATTR_TABLE_CELL_ROW_INDEX] = src.cellRowIndex(); | |
| 601 dst->int_attributes[dst->ATTR_TABLE_CELL_ROW_SPAN] = src.cellRowSpan(); | |
| 602 } | 636 } |
| 603 | 637 |
| 638 dst->AddStringAttribute(dst->ATTR_NAME, name); |
| 639 |
| 604 // Add the ids of *indirect* children - those who are children of this node, | 640 // Add the ids of *indirect* children - those who are children of this node, |
| 605 // but whose parent is *not* this node. One example is a table | 641 // but whose parent is *not* this node. One example is a table |
| 606 // cell, which is a child of both a row and a column. Because the cell's | 642 // cell, which is a child of both a row and a column. Because the cell's |
| 607 // parent is the row, the row adds it as a child, and the column adds it | 643 // parent is the row, the row adds it as a child, and the column adds it |
| 608 // as an indirect child. | 644 // as an indirect child. |
| 609 int child_count = src.childCount(); | 645 int child_count = src.childCount(); |
| 610 for (int i = 0; i < child_count; ++i) { | 646 for (int i = 0; i < child_count; ++i) { |
| 611 WebAccessibilityObject child = src.childAt(i); | 647 WebAccessibilityObject child = src.childAt(i); |
| 648 std::vector<int32> indirect_child_ids; |
| 612 if (!is_iframe && !child.isDetached() && !IsParentUnignoredOf(src, child)) | 649 if (!is_iframe && !child.isDetached() && !IsParentUnignoredOf(src, child)) |
| 613 dst->indirect_child_ids.push_back(child.axID()); | 650 indirect_child_ids.push_back(child.axID()); |
| 651 if (indirect_child_ids.size() > 0) { |
| 652 dst->AddIntListAttribute( |
| 653 dst->ATTR_INDIRECT_CHILD_IDS, indirect_child_ids); |
| 654 } |
| 614 } | 655 } |
| 615 } | 656 } |
| 616 | 657 |
| 617 bool ShouldIncludeChildNode( | 658 bool ShouldIncludeChildNode( |
| 618 const WebAccessibilityObject& parent, | 659 const WebAccessibilityObject& parent, |
| 619 const WebAccessibilityObject& child) { | 660 const WebAccessibilityObject& child) { |
| 620 switch(parent.roleValue()) { | 661 switch(parent.roleValue()) { |
| 621 case WebKit::WebAccessibilityRoleSlider: | 662 case WebKit::WebAccessibilityRoleSlider: |
| 622 case WebKit::WebAccessibilityRoleEditableText: | 663 case WebKit::WebAccessibilityRoleEditableText: |
| 623 case WebKit::WebAccessibilityRoleTextArea: | 664 case WebKit::WebAccessibilityRoleTextArea: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 640 WebNode node = parent.node(); | 681 WebNode node = parent.node(); |
| 641 if (!node.isNull() && node.isElementNode()) { | 682 if (!node.isNull() && node.isElementNode()) { |
| 642 WebElement element = node.to<WebElement>(); | 683 WebElement element = node.to<WebElement>(); |
| 643 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); | 684 is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME")); |
| 644 } | 685 } |
| 645 | 686 |
| 646 return (is_iframe || IsParentUnignoredOf(parent, child)); | 687 return (is_iframe || IsParentUnignoredOf(parent, child)); |
| 647 } | 688 } |
| 648 | 689 |
| 649 } // namespace content | 690 } // namespace content |
| OLD | NEW |