summaryrefslogtreecommitdiffstats
path: root/content/shell/renderer
diff options
context:
space:
mode:
authorhajimehoshi@chromium.org <hajimehoshi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-27 14:54:12 +0000
committerhajimehoshi@chromium.org <hajimehoshi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-27 14:54:12 +0000
commit36e66360086cd1e015f0721b898debb9c0e724d0 (patch)
tree2ba2574161a68da6573d8738ca37cbcb29da41b7 /content/shell/renderer
parent0df555e1d98032506a1984cba3f855dce929948b (diff)
downloadchromium_src-36e66360086cd1e015f0721b898debb9c0e724d0.zip
chromium_src-36e66360086cd1e015f0721b898debb9c0e724d0.tar.gz
chromium_src-36e66360086cd1e015f0721b898debb9c0e724d0.tar.bz2
Move WebAXObjectProxy and AccessibleController from CppBoundClass to gin::Wrappable
BUG=297480, 331301 Review URL: https://codereview.chromium.org/172263002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@253821 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/shell/renderer')
-rw-r--r--content/shell/renderer/test_runner/AccessibilityController.cpp184
-rw-r--r--content/shell/renderer/test_runner/AccessibilityController.h71
-rw-r--r--content/shell/renderer/test_runner/TestInterfaces.cpp18
-rw-r--r--content/shell/renderer/test_runner/TestInterfaces.h6
-rw-r--r--content/shell/renderer/test_runner/WebAXObjectProxy.cpp1178
-rw-r--r--content/shell/renderer/test_runner/WebAXObjectProxy.h146
-rw-r--r--content/shell/renderer/test_runner/WebTestProxy.cpp8
-rw-r--r--content/shell/renderer/test_runner/accessibility_controller.cc272
-rw-r--r--content/shell/renderer/test_runner/accessibility_controller.h77
-rw-r--r--content/shell/renderer/test_runner/unsafe_persistent.h50
-rw-r--r--content/shell/renderer/test_runner/web_ax_object_proxy.cc1024
-rw-r--r--content/shell/renderer/test_runner/web_ax_object_proxy.h168
12 files changed, 1607 insertions, 1595 deletions
diff --git a/content/shell/renderer/test_runner/AccessibilityController.cpp b/content/shell/renderer/test_runner/AccessibilityController.cpp
deleted file mode 100644
index fcf4951..0000000
--- a/content/shell/renderer/test_runner/AccessibilityController.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/shell/renderer/test_runner/AccessibilityController.h"
-
-#include "content/shell/renderer/test_runner/WebTestDelegate.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
-#include "third_party/WebKit/public/web/WebAXObject.h"
-#include "third_party/WebKit/public/web/WebElement.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebNode.h"
-#include "third_party/WebKit/public/web/WebView.h"
-
-using namespace blink;
-
-namespace WebTestRunner {
-
-AccessibilityController::AccessibilityController()
- : m_logAccessibilityEvents(false)
-{
-
- bindMethod("logAccessibilityEvents", &AccessibilityController::logAccessibilityEventsCallback);
- bindMethod("addNotificationListener", &AccessibilityController::addNotificationListenerCallback);
- bindMethod("removeNotificationListener", &AccessibilityController::removeNotificationListenerCallback);
-
- bindProperty("focusedElement", &AccessibilityController::focusedElementGetterCallback);
- bindProperty("rootElement", &AccessibilityController::rootElementGetterCallback);
-
- bindMethod("accessibleElementById", &AccessibilityController::accessibleElementByIdGetterCallback);
-
- bindFallbackMethod(&AccessibilityController::fallbackCallback);
-}
-
-AccessibilityController::~AccessibilityController()
-{
-}
-
-void AccessibilityController::bindToJavascript(WebFrame* frame, const WebString& classname)
-{
- WebAXObject::enableAccessibility();
- WebAXObject::enableInlineTextBoxAccessibility();
- CppBoundClass::bindToJavascript(frame, classname);
-}
-
-void AccessibilityController::reset()
-{
- m_rootElement = WebAXObject();
- m_focusedElement = WebAXObject();
- m_elements.clear();
- m_notificationCallbacks.clear();
-
- m_logAccessibilityEvents = false;
-}
-
-void AccessibilityController::setFocusedElement(const WebAXObject& focusedElement)
-{
- m_focusedElement = focusedElement;
-}
-
-WebAXObjectProxy* AccessibilityController::getFocusedElement()
-{
- if (m_focusedElement.isNull())
- m_focusedElement = m_webView->accessibilityObject();
- return m_elements.getOrCreate(m_focusedElement);
-}
-
-WebAXObjectProxy* AccessibilityController::getRootElement()
-{
- if (m_rootElement.isNull())
- m_rootElement = m_webView->accessibilityObject();
- return m_elements.createRoot(m_rootElement);
-}
-
-WebAXObjectProxy* AccessibilityController::findAccessibleElementByIdRecursive(const WebAXObject& obj, const WebString& id)
-{
- if (obj.isNull() || obj.isDetached())
- return 0;
-
- WebNode node = obj.node();
- if (!node.isNull() && node.isElementNode()) {
- WebElement element = node.to<WebElement>();
- element.getAttribute("id");
- if (element.getAttribute("id") == id)
- return m_elements.getOrCreate(obj);
- }
-
- unsigned childCount = obj.childCount();
- for (unsigned i = 0; i < childCount; i++) {
- if (WebAXObjectProxy* result = findAccessibleElementByIdRecursive(obj.childAt(i), id))
- return result;
- }
-
- return 0;
-}
-
-WebAXObjectProxy* AccessibilityController::getAccessibleElementById(const std::string& id)
-{
- if (m_rootElement.isNull())
- m_rootElement = m_webView->accessibilityObject();
-
- if (!m_rootElement.updateBackingStoreAndCheckValidity())
- return 0;
-
- return findAccessibleElementByIdRecursive(m_rootElement, WebString::fromUTF8(id.c_str()));
-}
-
-bool AccessibilityController::shouldLogAccessibilityEvents()
-{
- return m_logAccessibilityEvents;
-}
-
-void AccessibilityController::notificationReceived(const blink::WebAXObject& target, const char* notificationName)
-{
- // Call notification listeners on the element.
- WebAXObjectProxy* element = m_elements.getOrCreate(target);
- element->notificationReceived(notificationName);
-
- // Call global notification listeners.
- size_t callbackCount = m_notificationCallbacks.size();
- for (size_t i = 0; i < callbackCount; i++) {
- CppVariant arguments[2];
- arguments[0].set(*element->getAsCppVariant());
- arguments[1].set(notificationName);
- CppVariant invokeResult;
- m_notificationCallbacks[i].invokeDefault(arguments, 2, invokeResult);
- }
-}
-
-void AccessibilityController::logAccessibilityEventsCallback(const CppArgumentList&, CppVariant* result)
-{
- m_logAccessibilityEvents = true;
- result->setNull();
-}
-
-void AccessibilityController::addNotificationListenerCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- if (arguments.size() < 1 || !arguments[0].isObject()) {
- result->setNull();
- return;
- }
-
- m_notificationCallbacks.push_back(arguments[0]);
- result->setNull();
-}
-
-void AccessibilityController::removeNotificationListenerCallback(const CppArgumentList&, CppVariant* result)
-{
- // FIXME: Implement this.
- result->setNull();
-}
-
-void AccessibilityController::focusedElementGetterCallback(CppVariant* result)
-{
- result->set(*(getFocusedElement()->getAsCppVariant()));
-}
-
-void AccessibilityController::rootElementGetterCallback(CppVariant* result)
-{
- result->set(*(getRootElement()->getAsCppVariant()));
-}
-
-void AccessibilityController::accessibleElementByIdGetterCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- if (arguments.size() < 1 || !arguments[0].isString())
- return;
-
- std::string id = arguments[0].toString();
- WebAXObjectProxy* foundElement = getAccessibleElementById(id);
- if (!foundElement)
- return;
-
- result->set(*(foundElement->getAsCppVariant()));
-}
-
-void AccessibilityController::fallbackCallback(const CppArgumentList&, CppVariant* result)
-{
- m_delegate->printMessage("CONSOLE MESSAGE: JavaScript ERROR: unknown method called on AccessibilityController\n");
- result->setNull();
-}
-
-}
diff --git a/content/shell/renderer/test_runner/AccessibilityController.h b/content/shell/renderer/test_runner/AccessibilityController.h
deleted file mode 100644
index 976616a9..0000000
--- a/content/shell/renderer/test_runner/AccessibilityController.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_ACCESSIBILITYCONTROLLER_H_
-#define CONTENT_SHELL_RENDERER_TEST_RUNNER_ACCESSIBILITYCONTROLLER_H_
-
-#include "content/shell/renderer/test_runner/CppBoundClass.h"
-#include "content/shell/renderer/test_runner/WebAXObjectProxy.h"
-
-namespace blink {
-class WebAXObject;
-class WebFrame;
-class WebView;
-}
-
-namespace WebTestRunner {
-
-class WebTestDelegate;
-
-class AccessibilityController : public CppBoundClass {
-public:
- AccessibilityController();
- virtual ~AccessibilityController();
-
- // Shadow to include accessibility initialization.
- void bindToJavascript(blink::WebFrame*, const blink::WebString& classname);
- void reset();
-
- void setFocusedElement(const blink::WebAXObject&);
- WebAXObjectProxy* getFocusedElement();
- WebAXObjectProxy* getRootElement();
- WebAXObjectProxy* getAccessibleElementById(const std::string& id);
-
- bool shouldLogAccessibilityEvents();
-
- void notificationReceived(const blink::WebAXObject& target, const char* notificationName);
-
- void setDelegate(WebTestDelegate* delegate) { m_delegate = delegate; }
- void setWebView(blink::WebView* webView) { m_webView = webView; }
-
-private:
- // If true, will log all accessibility notifications.
- bool m_logAccessibilityEvents;
-
- // Bound methods and properties
- void logAccessibilityEventsCallback(const CppArgumentList&, CppVariant*);
- void fallbackCallback(const CppArgumentList&, CppVariant*);
- void addNotificationListenerCallback(const CppArgumentList&, CppVariant*);
- void removeNotificationListenerCallback(const CppArgumentList&, CppVariant*);
-
- void focusedElementGetterCallback(CppVariant*);
- void rootElementGetterCallback(CppVariant*);
- void accessibleElementByIdGetterCallback(const CppArgumentList&, CppVariant*);
-
- WebAXObjectProxy* findAccessibleElementByIdRecursive(const blink::WebAXObject&, const blink::WebString& id);
-
- blink::WebAXObject m_focusedElement;
- blink::WebAXObject m_rootElement;
-
- WebAXObjectProxyList m_elements;
-
- std::vector<CppVariant> m_notificationCallbacks;
-
- WebTestDelegate* m_delegate;
- blink::WebView* m_webView;
-};
-
-}
-
-#endif // CONTENT_SHELL_RENDERER_TEST_RUNNER_ACCESSIBILITYCONTROLLER_H_
diff --git a/content/shell/renderer/test_runner/TestInterfaces.cpp b/content/shell/renderer/test_runner/TestInterfaces.cpp
index 426f652..277de98 100644
--- a/content/shell/renderer/test_runner/TestInterfaces.cpp
+++ b/content/shell/renderer/test_runner/TestInterfaces.cpp
@@ -7,10 +7,10 @@
#include <string>
#include "base/strings/stringprintf.h"
-#include "content/shell/renderer/test_runner/AccessibilityController.h"
#include "content/shell/renderer/test_runner/EventSender.h"
#include "content/shell/renderer/test_runner/TestRunner.h"
#include "content/shell/renderer/test_runner/WebTestProxy.h"
+#include "content/shell/renderer/test_runner/accessibility_controller.h"
#include "content/shell/renderer/test_runner/gamepad_controller.h"
#include "content/shell/renderer/test_runner/text_input_controller.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -26,7 +26,7 @@ using namespace std;
namespace WebTestRunner {
TestInterfaces::TestInterfaces()
- : m_accessibilityController(new AccessibilityController())
+ : m_accessibilityController(new content::AccessibilityController())
, m_eventSender(new EventSender(this))
, m_gamepadController(new content::GamepadController())
, m_textInputController(new content::TextInputController())
@@ -43,13 +43,13 @@ TestInterfaces::TestInterfaces()
TestInterfaces::~TestInterfaces()
{
- m_accessibilityController->setWebView(0);
+ m_accessibilityController->SetWebView(0);
m_eventSender->setWebView(0);
// m_gamepadController doesn't depend on WebView.
m_textInputController->SetWebView(NULL);
m_testRunner->setWebView(0, 0);
- m_accessibilityController->setDelegate(0);
+ m_accessibilityController->SetDelegate(0);
m_eventSender->setDelegate(0);
m_gamepadController->SetDelegate(0);
// m_textInputController doesn't depend on WebTestDelegate.
@@ -59,7 +59,7 @@ TestInterfaces::~TestInterfaces()
void TestInterfaces::setWebView(WebView* webView, WebTestProxyBase* proxy)
{
m_proxy = proxy;
- m_accessibilityController->setWebView(webView);
+ m_accessibilityController->SetWebView(webView);
m_eventSender->setWebView(webView);
// m_gamepadController doesn't depend on WebView.
m_textInputController->SetWebView(webView);
@@ -68,7 +68,7 @@ void TestInterfaces::setWebView(WebView* webView, WebTestProxyBase* proxy)
void TestInterfaces::setDelegate(WebTestDelegate* delegate)
{
- m_accessibilityController->setDelegate(delegate);
+ m_accessibilityController->SetDelegate(delegate);
m_eventSender->setDelegate(delegate);
m_gamepadController->SetDelegate(delegate);
// m_textInputController doesn't depend on WebTestDelegate.
@@ -78,7 +78,7 @@ void TestInterfaces::setDelegate(WebTestDelegate* delegate)
void TestInterfaces::bindTo(WebFrame* frame)
{
- m_accessibilityController->bindToJavascript(frame, WebString::fromUTF8("accessibilityController"));
+ m_accessibilityController->Install(frame);
m_eventSender->bindToJavascript(frame, WebString::fromUTF8("eventSender"));
m_gamepadController->Install(frame);
m_textInputController->Install(frame);
@@ -88,7 +88,7 @@ void TestInterfaces::bindTo(WebFrame* frame)
void TestInterfaces::resetTestHelperControllers()
{
- m_accessibilityController->reset();
+ m_accessibilityController->Reset();
m_eventSender->reset();
m_gamepadController->Reset();
// m_textInputController doesn't have any state to reset.
@@ -153,7 +153,7 @@ void TestInterfaces::windowClosed(WebTestProxyBase* proxy)
m_windowList.erase(pos);
}
-AccessibilityController* TestInterfaces::accessibilityController()
+content::AccessibilityController* TestInterfaces::accessibilityController()
{
return m_accessibilityController.get();
}
diff --git a/content/shell/renderer/test_runner/TestInterfaces.h b/content/shell/renderer/test_runner/TestInterfaces.h
index 69e490c..21c6d6a 100644
--- a/content/shell/renderer/test_runner/TestInterfaces.h
+++ b/content/shell/renderer/test_runner/TestInterfaces.h
@@ -25,13 +25,13 @@ class WebView;
}
namespace content {
+class AccessibilityController;
class GamepadController;
class TextInputController;
}
namespace WebTestRunner {
-class AccessibilityController;
class EventSender;
class TestRunner;
class WebTestDelegate;
@@ -53,7 +53,7 @@ public:
void windowOpened(WebTestProxyBase*);
void windowClosed(WebTestProxyBase*);
- AccessibilityController* accessibilityController();
+ content::AccessibilityController* accessibilityController();
EventSender* eventSender();
TestRunner* testRunner();
WebTestDelegate* delegate();
@@ -62,7 +62,7 @@ public:
blink::WebThemeEngine* themeEngine();
private:
- scoped_ptr<AccessibilityController> m_accessibilityController;
+ scoped_ptr<content::AccessibilityController> m_accessibilityController;
scoped_ptr<EventSender> m_eventSender;
scoped_ptr<content::GamepadController> m_gamepadController;
scoped_ptr<content::TextInputController> m_textInputController;
diff --git a/content/shell/renderer/test_runner/WebAXObjectProxy.cpp b/content/shell/renderer/test_runner/WebAXObjectProxy.cpp
deleted file mode 100644
index 1690fee..0000000
--- a/content/shell/renderer/test_runner/WebAXObjectProxy.cpp
+++ /dev/null
@@ -1,1178 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/shell/renderer/test_runner/WebAXObjectProxy.h"
-
-#include "content/shell/renderer/test_runner/TestCommon.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
-#include "third_party/WebKit/public/platform/WebPoint.h"
-#include "third_party/WebKit/public/platform/WebRect.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-
-using namespace blink;
-using namespace std;
-
-namespace WebTestRunner {
-
-namespace {
-
-// Map role value to string, matching Safari/Mac platform implementation to
-// avoid rebaselining layout tests.
-string roleToString(WebAXRole role)
-{
- string result = "AXRole: AX";
- switch (role) {
- case WebAXRoleAlertDialog:
- return result.append("AlertDialog");
- case WebAXRoleAlert:
- return result.append("Alert");
- case WebAXRoleAnnotation:
- return result.append("Annotation");
- case WebAXRoleApplication:
- return result.append("Application");
- case WebAXRoleArticle:
- return result.append("Article");
- case WebAXRoleBanner:
- return result.append("Banner");
- case WebAXRoleBrowser:
- return result.append("Browser");
- case WebAXRoleBusyIndicator:
- return result.append("BusyIndicator");
- case WebAXRoleButton:
- return result.append("Button");
- case WebAXRoleCanvas:
- return result.append("Canvas");
- case WebAXRoleCell:
- return result.append("Cell");
- case WebAXRoleCheckBox:
- return result.append("CheckBox");
- case WebAXRoleColorWell:
- return result.append("ColorWell");
- case WebAXRoleColumnHeader:
- return result.append("ColumnHeader");
- case WebAXRoleColumn:
- return result.append("Column");
- case WebAXRoleComboBox:
- return result.append("ComboBox");
- case WebAXRoleComplementary:
- return result.append("Complementary");
- case WebAXRoleContentInfo:
- return result.append("ContentInfo");
- case WebAXRoleDefinition:
- return result.append("Definition");
- case WebAXRoleDescriptionListDetail:
- return result.append("DescriptionListDetail");
- case WebAXRoleDescriptionListTerm:
- return result.append("DescriptionListTerm");
- case WebAXRoleDialog:
- return result.append("Dialog");
- case WebAXRoleDirectory:
- return result.append("Directory");
- case WebAXRoleDisclosureTriangle:
- return result.append("DisclosureTriangle");
- case WebAXRoleDiv:
- return result.append("Div");
- case WebAXRoleDocument:
- return result.append("Document");
- case WebAXRoleDrawer:
- return result.append("Drawer");
- case WebAXRoleEditableText:
- return result.append("EditableText");
- case WebAXRoleFooter:
- return result.append("Footer");
- case WebAXRoleForm:
- return result.append("Form");
- case WebAXRoleGrid:
- return result.append("Grid");
- case WebAXRoleGroup:
- return result.append("Group");
- case WebAXRoleGrowArea:
- return result.append("GrowArea");
- case WebAXRoleHeading:
- return result.append("Heading");
- case WebAXRoleHelpTag:
- return result.append("HelpTag");
- case WebAXRoleHorizontalRule:
- return result.append("HorizontalRule");
- case WebAXRoleIgnored:
- return result.append("Ignored");
- case WebAXRoleImageMapLink:
- return result.append("ImageMapLink");
- case WebAXRoleImageMap:
- return result.append("ImageMap");
- case WebAXRoleImage:
- return result.append("Image");
- case WebAXRoleIncrementor:
- return result.append("Incrementor");
- case WebAXRoleInlineTextBox:
- return result.append("InlineTextBox");
- case WebAXRoleLabel:
- return result.append("Label");
- case WebAXRoleLegend:
- return result.append("Legend");
- case WebAXRoleLink:
- return result.append("Link");
- case WebAXRoleListBoxOption:
- return result.append("ListBoxOption");
- case WebAXRoleListBox:
- return result.append("ListBox");
- case WebAXRoleListItem:
- return result.append("ListItem");
- case WebAXRoleListMarker:
- return result.append("ListMarker");
- case WebAXRoleList:
- return result.append("List");
- case WebAXRoleLog:
- return result.append("Log");
- case WebAXRoleMain:
- return result.append("Main");
- case WebAXRoleMarquee:
- return result.append("Marquee");
- case WebAXRoleMathElement:
- return result.append("MathElement");
- case WebAXRoleMath:
- return result.append("Math");
- case WebAXRoleMatte:
- return result.append("Matte");
- case WebAXRoleMenuBar:
- return result.append("MenuBar");
- case WebAXRoleMenuButton:
- return result.append("MenuButton");
- case WebAXRoleMenuItem:
- return result.append("MenuItem");
- case WebAXRoleMenuListOption:
- return result.append("MenuListOption");
- case WebAXRoleMenuListPopup:
- return result.append("MenuListPopup");
- case WebAXRoleMenu:
- return result.append("Menu");
- case WebAXRoleNavigation:
- return result.append("Navigation");
- case WebAXRoleNote:
- return result.append("Note");
- case WebAXRoleOutline:
- return result.append("Outline");
- case WebAXRoleParagraph:
- return result.append("Paragraph");
- case WebAXRolePopUpButton:
- return result.append("PopUpButton");
- case WebAXRolePresentational:
- return result.append("Presentational");
- case WebAXRoleProgressIndicator:
- return result.append("ProgressIndicator");
- case WebAXRoleRadioButton:
- return result.append("RadioButton");
- case WebAXRoleRadioGroup:
- return result.append("RadioGroup");
- case WebAXRoleRegion:
- return result.append("Region");
- case WebAXRoleRootWebArea:
- return result.append("RootWebArea");
- case WebAXRoleRowHeader:
- return result.append("RowHeader");
- case WebAXRoleRow:
- return result.append("Row");
- case WebAXRoleRulerMarker:
- return result.append("RulerMarker");
- case WebAXRoleRuler:
- return result.append("Ruler");
- case WebAXRoleSVGRoot:
- return result.append("SVGRoot");
- case WebAXRoleScrollArea:
- return result.append("ScrollArea");
- case WebAXRoleScrollBar:
- return result.append("ScrollBar");
- case WebAXRoleSeamlessWebArea:
- return result.append("SeamlessWebArea");
- case WebAXRoleSearch:
- return result.append("Search");
- case WebAXRoleSheet:
- return result.append("Sheet");
- case WebAXRoleSlider:
- return result.append("Slider");
- case WebAXRoleSliderThumb:
- return result.append("SliderThumb");
- case WebAXRoleSpinButtonPart:
- return result.append("SpinButtonPart");
- case WebAXRoleSpinButton:
- return result.append("SpinButton");
- case WebAXRoleSplitGroup:
- return result.append("SplitGroup");
- case WebAXRoleSplitter:
- return result.append("Splitter");
- case WebAXRoleStaticText:
- return result.append("StaticText");
- case WebAXRoleStatus:
- return result.append("Status");
- case WebAXRoleSystemWide:
- return result.append("SystemWide");
- case WebAXRoleTabGroup:
- return result.append("TabGroup");
- case WebAXRoleTabList:
- return result.append("TabList");
- case WebAXRoleTabPanel:
- return result.append("TabPanel");
- case WebAXRoleTab:
- return result.append("Tab");
- case WebAXRoleTableHeaderContainer:
- return result.append("TableHeaderContainer");
- case WebAXRoleTable:
- return result.append("Table");
- case WebAXRoleTextArea:
- return result.append("TextArea");
- case WebAXRoleTextField:
- return result.append("TextField");
- case WebAXRoleTimer:
- return result.append("Timer");
- case WebAXRoleToggleButton:
- return result.append("ToggleButton");
- case WebAXRoleToolbar:
- return result.append("Toolbar");
- case WebAXRoleTreeGrid:
- return result.append("TreeGrid");
- case WebAXRoleTreeItem:
- return result.append("TreeItem");
- case WebAXRoleTree:
- return result.append("Tree");
- case WebAXRoleUnknown:
- return result.append("Unknown");
- case WebAXRoleUserInterfaceTooltip:
- return result.append("UserInterfaceTooltip");
- case WebAXRoleValueIndicator:
- return result.append("ValueIndicator");
- case WebAXRoleWebArea:
- return result.append("WebArea");
- case WebAXRoleWindow:
- return result.append("Window");
- default:
- return result.append("Unknown");
- }
-}
-
-string getDescription(const WebAXObject& object)
-{
- string description = object.accessibilityDescription().utf8();
- return description.insert(0, "AXDescription: ");
-}
-
-string getHelpText(const WebAXObject& object)
-{
- string helpText = object.helpText().utf8();
- return helpText.insert(0, "AXHelp: ");
-}
-
-string getStringValue(const WebAXObject& object)
-{
- string value;
- if (object.role() == WebAXRoleColorWell) {
- int r, g, b;
- char buffer[100];
- object.colorValue(r, g, b);
- snprintf(buffer, sizeof(buffer), "rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.);
- value = buffer;
- } else {
- value = object.stringValue().utf8();
- }
- return value.insert(0, "AXValue: ");
-}
-
-string getRole(const WebAXObject& object)
-{
- string roleString = roleToString(object.role());
-
- // Special-case canvas with fallback content because Chromium wants to
- // treat this as essentially a separate role that it can map differently depending
- // on the platform.
- if (object.role() == WebAXRoleCanvas && object.canvasHasFallbackContent())
- roleString += "WithFallbackContent";
-
- return roleString;
-}
-
-string getTitle(const WebAXObject& object)
-{
- string title = object.title().utf8();
- return title.insert(0, "AXTitle: ");
-}
-
-string getOrientation(const WebAXObject& object)
-{
- if (object.isVertical())
- return "AXOrientation: AXVerticalOrientation";
-
- return "AXOrientation: AXHorizontalOrientation";
-}
-
-string getValueDescription(const WebAXObject& object)
-{
- string valueDescription = object.valueDescription().utf8();
- return valueDescription.insert(0, "AXValueDescription: ");
-}
-
-string getAttributes(const WebAXObject& object)
-{
- // FIXME: Concatenate all attributes of the AXObject.
- string attributes(getTitle(object));
- attributes.append("\n");
- attributes.append(getRole(object));
- attributes.append("\n");
- attributes.append(getDescription(object));
- return attributes;
-}
-
-WebRect boundsForCharacter(const WebAXObject& object, int characterIndex)
-{
- BLINK_ASSERT(object.role() == WebAXRoleStaticText);
- int end = 0;
- for (unsigned i = 0; i < object.childCount(); i++) {
- WebAXObject inlineTextBox = object.childAt(i);
- BLINK_ASSERT(inlineTextBox.role() == WebAXRoleInlineTextBox);
- int start = end;
- end += inlineTextBox.stringValue().length();
- if (end <= characterIndex)
- continue;
- WebRect inlineTextBoxRect = inlineTextBox.boundingBoxRect();
- int localIndex = characterIndex - start;
- WebVector<int> characterOffsets;
- inlineTextBox.characterOffsets(characterOffsets);
- BLINK_ASSERT(characterOffsets.size() > 0 && characterOffsets.size() == inlineTextBox.stringValue().length());
- switch (inlineTextBox.textDirection()) {
- case WebAXTextDirectionLR: {
- if (localIndex) {
- int left = inlineTextBoxRect.x + characterOffsets[localIndex - 1];
- int width = characterOffsets[localIndex] - characterOffsets[localIndex - 1];
- return WebRect(left, inlineTextBoxRect.y, width, inlineTextBoxRect.height);
- }
- return WebRect(inlineTextBoxRect.x, inlineTextBoxRect.y, characterOffsets[0], inlineTextBoxRect.height);
- }
- case WebAXTextDirectionRL: {
- int right = inlineTextBoxRect.x + inlineTextBoxRect.width;
-
- if (localIndex) {
- int left = right - characterOffsets[localIndex];
- int width = characterOffsets[localIndex] - characterOffsets[localIndex - 1];
- return WebRect(left, inlineTextBoxRect.y, width, inlineTextBoxRect.height);
- }
- int left = right - characterOffsets[0];
- return WebRect(left, inlineTextBoxRect.y, characterOffsets[0], inlineTextBoxRect.height);
- }
- case WebAXTextDirectionTB: {
- if (localIndex) {
- int top = inlineTextBoxRect.y + characterOffsets[localIndex - 1];
- int height = characterOffsets[localIndex] - characterOffsets[localIndex - 1];
- return WebRect(inlineTextBoxRect.x, top, inlineTextBoxRect.width, height);
- }
- return WebRect(inlineTextBoxRect.x, inlineTextBoxRect.y, inlineTextBoxRect.width, characterOffsets[0]);
- }
- case WebAXTextDirectionBT: {
- int bottom = inlineTextBoxRect.y + inlineTextBoxRect.height;
-
- if (localIndex) {
- int top = bottom - characterOffsets[localIndex];
- int height = characterOffsets[localIndex] - characterOffsets[localIndex - 1];
- return WebRect(inlineTextBoxRect.x, top, inlineTextBoxRect.width, height);
- }
- int top = bottom - characterOffsets[0];
- return WebRect(inlineTextBoxRect.x, top, inlineTextBoxRect.width, characterOffsets[0]);
- }
- }
- }
-
- BLINK_ASSERT(false);
- return WebRect();
-}
-
-void getBoundariesForOneWord(const WebAXObject& object, int characterIndex, int& wordStart, int& wordEnd)
-{
- int end = 0;
- for (unsigned i = 0; i < object.childCount(); i++) {
- WebAXObject inlineTextBox = object.childAt(i);
- BLINK_ASSERT(inlineTextBox.role() == WebAXRoleInlineTextBox);
- int start = end;
- end += inlineTextBox.stringValue().length();
- if (end <= characterIndex)
- continue;
- int localIndex = characterIndex - start;
-
- WebVector<int> starts;
- WebVector<int> ends;
- inlineTextBox.wordBoundaries(starts, ends);
- size_t wordCount = starts.size();
- BLINK_ASSERT(ends.size() == wordCount);
-
- // If there are no words, use the InlineTextBox boundaries.
- if (!wordCount) {
- wordStart = start;
- wordEnd = end;
- return;
- }
-
- // Look for a character within any word other than the last.
- for (size_t j = 0; j < wordCount - 1; j++) {
- if (localIndex <= ends[j]) {
- wordStart = start + starts[j];
- wordEnd = start + ends[j];
- return;
- }
- }
-
- // Return the last word by default.
- wordStart = start + starts[wordCount - 1];
- wordEnd = start + ends[wordCount - 1];
- return;
- }
-}
-
-// Collects attributes into a string, delimited by dashes. Used by all methods
-// that output lists of attributes: attributesOfLinkedUIElementsCallback,
-// AttributesOfChildrenCallback, etc.
-class AttributesCollector {
-public:
- void collectAttributes(const WebAXObject& object)
- {
- m_attributes.append("\n------------\n");
- m_attributes.append(getAttributes(object));
- }
-
- string attributes() const { return m_attributes; }
-
-private:
- string m_attributes;
-};
-
-}
-
-WebAXObjectProxy::WebAXObjectProxy(const WebAXObject& object, Factory* factory)
- : m_accessibilityObject(object)
- , m_factory(factory)
-{
-
- BLINK_ASSERT(factory);
-
- //
- // Properties
- //
-
- bindProperty("role", &WebAXObjectProxy::roleGetterCallback);
- bindProperty("title", &WebAXObjectProxy::titleGetterCallback);
- bindProperty("description", &WebAXObjectProxy::descriptionGetterCallback);
- bindProperty("helpText", &WebAXObjectProxy::helpTextGetterCallback);
- bindProperty("stringValue", &WebAXObjectProxy::stringValueGetterCallback);
- bindProperty("x", &WebAXObjectProxy::xGetterCallback);
- bindProperty("y", &WebAXObjectProxy::yGetterCallback);
- bindProperty("width", &WebAXObjectProxy::widthGetterCallback);
- bindProperty("height", &WebAXObjectProxy::heightGetterCallback);
- bindProperty("intValue", &WebAXObjectProxy::intValueGetterCallback);
- bindProperty("minValue", &WebAXObjectProxy::minValueGetterCallback);
- bindProperty("maxValue", &WebAXObjectProxy::maxValueGetterCallback);
- bindProperty("valueDescription", &WebAXObjectProxy::valueDescriptionGetterCallback);
- bindProperty("childrenCount", &WebAXObjectProxy::childrenCountGetterCallback);
- bindProperty("insertionPointLineNumber", &WebAXObjectProxy::insertionPointLineNumberGetterCallback);
- bindProperty("selectedTextRange", &WebAXObjectProxy::selectedTextRangeGetterCallback);
- bindProperty("isEnabled", &WebAXObjectProxy::isEnabledGetterCallback);
- bindProperty("isRequired", &WebAXObjectProxy::isRequiredGetterCallback);
- bindProperty("isFocused", &WebAXObjectProxy::isFocusedGetterCallback);
- bindProperty("isFocusable", &WebAXObjectProxy::isFocusableGetterCallback);
- bindProperty("isSelected", &WebAXObjectProxy::isSelectedGetterCallback);
- bindProperty("isSelectable", &WebAXObjectProxy::isSelectableGetterCallback);
- bindProperty("isMultiSelectable", &WebAXObjectProxy::isMultiSelectableGetterCallback);
- bindProperty("isSelectedOptionActive", &WebAXObjectProxy::isSelectedOptionActiveGetterCallback);
- bindProperty("isExpanded", &WebAXObjectProxy::isExpandedGetterCallback);
- bindProperty("isChecked", &WebAXObjectProxy::isCheckedGetterCallback);
- bindProperty("isVisible", &WebAXObjectProxy::isVisibleGetterCallback);
- bindProperty("isOffScreen", &WebAXObjectProxy::isOffScreenGetterCallback);
- bindProperty("isCollapsed", &WebAXObjectProxy::isCollapsedGetterCallback);
- bindProperty("hasPopup", &WebAXObjectProxy::hasPopupGetterCallback);
- bindProperty("isValid", &WebAXObjectProxy::isValidGetterCallback);
- bindProperty("isReadOnly", &WebAXObjectProxy::isReadOnlyGetterCallback);
- bindProperty("orientation", &WebAXObjectProxy::orientationGetterCallback);
- bindProperty("clickPointX", &WebAXObjectProxy::clickPointXGetterCallback);
- bindProperty("clickPointY", &WebAXObjectProxy::clickPointYGetterCallback);
- bindProperty("rowCount", &WebAXObjectProxy::rowCountGetterCallback);
- bindProperty("columnCount", &WebAXObjectProxy::columnCountGetterCallback);
- bindProperty("isClickable", &WebAXObjectProxy::isClickableGetterCallback);
-
- //
- // Methods
- //
-
- bindMethod("allAttributes", &WebAXObjectProxy::allAttributesCallback);
- bindMethod("attributesOfChildren", &WebAXObjectProxy::attributesOfChildrenCallback);
- bindMethod("lineForIndex", &WebAXObjectProxy::lineForIndexCallback);
- bindMethod("boundsForRange", &WebAXObjectProxy::boundsForRangeCallback);
- bindMethod("childAtIndex", &WebAXObjectProxy::childAtIndexCallback);
- bindMethod("elementAtPoint", &WebAXObjectProxy::elementAtPointCallback);
- bindMethod("tableHeader", &WebAXObjectProxy::tableHeaderCallback);
- bindMethod("rowIndexRange", &WebAXObjectProxy::rowIndexRangeCallback);
- bindMethod("columnIndexRange", &WebAXObjectProxy::columnIndexRangeCallback);
- bindMethod("cellForColumnAndRow", &WebAXObjectProxy::cellForColumnAndRowCallback);
- bindMethod("titleUIElement", &WebAXObjectProxy::titleUIElementCallback);
- bindMethod("setSelectedTextRange", &WebAXObjectProxy::setSelectedTextRangeCallback);
- bindMethod("isAttributeSettable", &WebAXObjectProxy::isAttributeSettableCallback);
- bindMethod("isPressActionSupported", &WebAXObjectProxy::isPressActionSupportedCallback);
- bindMethod("isIncrementActionSupported", &WebAXObjectProxy::isIncrementActionSupportedCallback);
- bindMethod("isDecrementActionSupported", &WebAXObjectProxy::isDecrementActionSupportedCallback);
- bindMethod("parentElement", &WebAXObjectProxy::parentElementCallback);
- bindMethod("increment", &WebAXObjectProxy::incrementCallback);
- bindMethod("decrement", &WebAXObjectProxy::decrementCallback);
- bindMethod("showMenu", &WebAXObjectProxy::showMenuCallback);
- bindMethod("press", &WebAXObjectProxy::pressCallback);
- bindMethod("isEqual", &WebAXObjectProxy::isEqualCallback);
- bindMethod("addNotificationListener", &WebAXObjectProxy::addNotificationListenerCallback);
- bindMethod("removeNotificationListener", &WebAXObjectProxy::removeNotificationListenerCallback);
- bindMethod("takeFocus", &WebAXObjectProxy::takeFocusCallback);
- bindMethod("scrollToMakeVisible", &WebAXObjectProxy::scrollToMakeVisibleCallback);
- bindMethod("scrollToMakeVisibleWithSubFocus", &WebAXObjectProxy::scrollToMakeVisibleWithSubFocusCallback);
- bindMethod("scrollToGlobalPoint", &WebAXObjectProxy::scrollToGlobalPointCallback);
- bindMethod("wordStart", &WebAXObjectProxy::wordStartCallback);
- bindMethod("wordEnd", &WebAXObjectProxy::wordEndCallback);
-
- bindFallbackMethod(&WebAXObjectProxy::fallbackCallback);
-}
-
-WebAXObjectProxy::~WebAXObjectProxy()
-{
-}
-
-WebAXObjectProxy* WebAXObjectProxy::getChildAtIndex(unsigned index)
-{
- return m_factory->getOrCreate(accessibilityObject().childAt(index));
-}
-
-bool WebAXObjectProxy::isRoot() const
-{
- return false;
-}
-
-bool WebAXObjectProxy::isEqual(const blink::WebAXObject& other)
-{
- return accessibilityObject().equals(other);
-}
-
-void WebAXObjectProxy::notificationReceived(const char* notificationName)
-{
- size_t callbackCount = m_notificationCallbacks.size();
- for (size_t i = 0; i < callbackCount; i++) {
- CppVariant notificationNameArgument;
- notificationNameArgument.set(notificationName);
- CppVariant invokeResult;
- m_notificationCallbacks[i].invokeDefault(&notificationNameArgument, 1, invokeResult);
- }
-}
-
-//
-// Properties
-//
-
-void WebAXObjectProxy::roleGetterCallback(CppVariant* result)
-{
- result->set(getRole(accessibilityObject()));
-}
-
-void WebAXObjectProxy::titleGetterCallback(CppVariant* result)
-{
- result->set(getTitle(accessibilityObject()));
-}
-
-void WebAXObjectProxy::descriptionGetterCallback(CppVariant* result)
-{
- result->set(getDescription(accessibilityObject()));
-}
-
-void WebAXObjectProxy::helpTextGetterCallback(CppVariant* result)
-{
- result->set(getHelpText(accessibilityObject()));
-}
-
-void WebAXObjectProxy::stringValueGetterCallback(CppVariant* result)
-{
- result->set(getStringValue(accessibilityObject()));
-}
-
-void WebAXObjectProxy::xGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().boundingBoxRect().x);
-}
-
-void WebAXObjectProxy::yGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().boundingBoxRect().y);
-}
-
-void WebAXObjectProxy::widthGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().boundingBoxRect().width);
-}
-
-void WebAXObjectProxy::heightGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().boundingBoxRect().height);
-}
-
-void WebAXObjectProxy::intValueGetterCallback(CppVariant* result)
-{
- if (accessibilityObject().supportsRangeValue())
- result->set(accessibilityObject().valueForRange());
- else if (accessibilityObject().role() == WebAXRoleHeading)
- result->set(accessibilityObject().headingLevel());
- else
- result->set(atoi(accessibilityObject().stringValue().utf8().data()));
-}
-
-void WebAXObjectProxy::minValueGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().minValueForRange());
-}
-
-void WebAXObjectProxy::maxValueGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().maxValueForRange());
-}
-
-void WebAXObjectProxy::valueDescriptionGetterCallback(CppVariant* result)
-{
- result->set(getValueDescription(accessibilityObject()));
-}
-
-void WebAXObjectProxy::childrenCountGetterCallback(CppVariant* result)
-{
- int count = 1; // Root object always has only one child, the WebView.
- if (!isRoot())
- count = accessibilityObject().childCount();
- result->set(count);
-}
-
-void WebAXObjectProxy::insertionPointLineNumberGetterCallback(CppVariant* result)
-{
- if (!accessibilityObject().isFocused()) {
- result->set(-1);
- return;
- }
-
- int lineNumber = accessibilityObject().selectionEndLineNumber();
- result->set(lineNumber);
-}
-
-void WebAXObjectProxy::selectedTextRangeGetterCallback(CppVariant* result)
-{
- unsigned selectionStart = accessibilityObject().selectionStart();
- unsigned selectionEnd = accessibilityObject().selectionEnd();
- char buffer[100];
- snprintf(buffer, sizeof(buffer), "{%d, %d}", selectionStart, selectionEnd - selectionStart);
-
- result->set(std::string(buffer));
-}
-
-void WebAXObjectProxy::isEnabledGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isEnabled());
-}
-
-void WebAXObjectProxy::isRequiredGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isRequired());
-}
-
-void WebAXObjectProxy::isFocusedGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isFocused());
-}
-
-void WebAXObjectProxy::isFocusableGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().canSetFocusAttribute());
-}
-
-void WebAXObjectProxy::isSelectedGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isSelected());
-}
-
-void WebAXObjectProxy::isSelectableGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().canSetSelectedAttribute());
-}
-
-void WebAXObjectProxy::isMultiSelectableGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isMultiSelectable());
-}
-
-void WebAXObjectProxy::isSelectedOptionActiveGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isSelectedOptionActive());
-}
-
-void WebAXObjectProxy::isExpandedGetterCallback(CppVariant* result)
-{
- result->set(!accessibilityObject().isCollapsed());
-}
-
-void WebAXObjectProxy::isCheckedGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isChecked());
-}
-
-void WebAXObjectProxy::isVisibleGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isVisible());
-}
-
-void WebAXObjectProxy::isOffScreenGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isOffScreen());
-}
-
-void WebAXObjectProxy::isCollapsedGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isCollapsed());
-}
-
-void WebAXObjectProxy::hasPopupGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().ariaHasPopup());
-}
-
-void WebAXObjectProxy::isValidGetterCallback(CppVariant* result)
-{
- result->set(!accessibilityObject().isDetached());
-}
-
-void WebAXObjectProxy::isReadOnlyGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isReadOnly());
-}
-
-void WebAXObjectProxy::orientationGetterCallback(CppVariant* result)
-{
- result->set(getOrientation(accessibilityObject()));
-}
-
-void WebAXObjectProxy::clickPointXGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().clickPoint().x);
-}
-
-void WebAXObjectProxy::clickPointYGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().clickPoint().y);
-}
-
-void WebAXObjectProxy::rowCountGetterCallback(CppVariant* result)
-{
- result->set(static_cast<int32_t>(accessibilityObject().rowCount()));
-}
-
-void WebAXObjectProxy::columnCountGetterCallback(CppVariant* result)
-{
- result->set(static_cast<int32_t>(accessibilityObject().columnCount()));
-}
-
-void WebAXObjectProxy::isClickableGetterCallback(CppVariant* result)
-{
- result->set(accessibilityObject().isClickable());
-}
-
-//
-// Methods
-//
-
-void WebAXObjectProxy::allAttributesCallback(const CppArgumentList&, CppVariant* result)
-{
- result->set(getAttributes(accessibilityObject()));
-}
-
-void WebAXObjectProxy::attributesOfChildrenCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- AttributesCollector collector;
- unsigned size = accessibilityObject().childCount();
- for (unsigned i = 0; i < size; ++i)
- collector.collectAttributes(accessibilityObject().childAt(i));
- result->set(collector.attributes());
-}
-
-void WebAXObjectProxy::lineForIndexCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- if (!arguments.size() || !arguments[0].isNumber()) {
- result->setNull();
- return;
- }
-
- int index = arguments[0].toInt32();
-
- WebVector<int> lineBreaks;
- accessibilityObject().lineBreaks(lineBreaks);
- int line = 0;
- int vectorSize = static_cast<int>(lineBreaks.size());
- while (line < vectorSize && lineBreaks[line] <= index)
- line++;
- result->set(line);
-}
-
-void WebAXObjectProxy::boundsForRangeCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
- return;
-
- if (accessibilityObject().role() != WebAXRoleStaticText)
- return;
-
- int start = arguments[0].toInt32();
- int end = arguments[1].toInt32();
- int len = end - start;
-
- // Get the bounds for each character and union them into one large rectangle.
- // This is just for testing so it doesn't need to be efficient.
- WebRect bounds = boundsForCharacter(accessibilityObject(), start);
- for (int i = 1; i < len; i++) {
- WebRect next = boundsForCharacter(accessibilityObject(), start + i);
- int right = std::max(bounds.x + bounds.width, next.x + next.width);
- int bottom = std::max(bounds.y + bounds.height, next.y + next.height);
- bounds.x = std::min(bounds.x, next.x);
- bounds.y = std::min(bounds.y, next.y);
- bounds.width = right - bounds.x;
- bounds.height = bottom - bounds.y;
- }
-
- char buffer[100];
- snprintf(buffer, sizeof(buffer), "{x: %d, y: %d, width: %d, height: %d}", bounds.x, bounds.y, bounds.width, bounds.height);
- result->set(string(buffer));
-}
-
-void WebAXObjectProxy::childAtIndexCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- if (!arguments.size() || !arguments[0].isNumber()) {
- result->setNull();
- return;
- }
-
- WebAXObjectProxy* child = getChildAtIndex(arguments[0].toInt32());
- if (!child) {
- result->setNull();
- return;
- }
-
- result->set(*(child->getAsCppVariant()));
-}
-
-void WebAXObjectProxy::elementAtPointCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
- return;
-
- int x = arguments[0].toInt32();
- int y = arguments[1].toInt32();
- WebPoint point(x, y);
- WebAXObject obj = accessibilityObject().hitTest(point);
- if (obj.isNull())
- return;
-
- result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant()));
-}
-
-void WebAXObjectProxy::tableHeaderCallback(const CppArgumentList&, CppVariant* result)
-{
- WebAXObject obj = accessibilityObject().headerContainerObject();
- if (obj.isNull()) {
- result->setNull();
- return;
- }
-
- result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant()));
-}
-
-void WebAXObjectProxy::rowIndexRangeCallback(const CppArgumentList&, CppVariant* result)
-{
- unsigned rowIndex = accessibilityObject().cellRowIndex();
- unsigned rowSpan = accessibilityObject().cellRowSpan();
- char buffer[100];
- snprintf(buffer, sizeof(buffer), "{%d, %d}", rowIndex, rowSpan);
- string value = buffer;
- result->set(std::string(buffer));
-}
-
-void WebAXObjectProxy::columnIndexRangeCallback(const CppArgumentList&, CppVariant* result)
-{
- unsigned columnIndex = accessibilityObject().cellColumnIndex();
- unsigned columnSpan = accessibilityObject().cellColumnSpan();
- char buffer[100];
- snprintf(buffer, sizeof(buffer), "{%d, %d}", columnIndex, columnSpan);
- result->set(std::string(buffer));
-}
-
-void WebAXObjectProxy::cellForColumnAndRowCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
- return;
-
- int column = arguments[0].toInt32();
- int row = arguments[1].toInt32();
- WebAXObject obj = accessibilityObject().cellForColumnAndRow(column, row);
- if (obj.isNull()) {
- result->setNull();
- return;
- }
-
- result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant()));
-}
-
-void WebAXObjectProxy::titleUIElementCallback(const CppArgumentList&, CppVariant* result)
-{
- WebAXObject obj = accessibilityObject().titleUIElement();
- if (obj.isNull()) {
- result->setNull();
- return;
- }
-
- result->set(*(m_factory->getOrCreate(obj)->getAsCppVariant()));
-}
-
-void WebAXObjectProxy::setSelectedTextRangeCallback(const CppArgumentList&arguments, CppVariant* result)
-{
- result->setNull();
- if (arguments.size() != 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
- return;
-
- int selectionStart = arguments[0].toInt32();
- int selectionEnd = selectionStart + arguments[1].toInt32();
- accessibilityObject().setSelectedTextRange(selectionStart, selectionEnd);
-}
-
-void WebAXObjectProxy::isAttributeSettableCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- if (arguments.size() < 1 && !arguments[0].isString()) {
- result->setNull();
- return;
- }
-
- string attribute = arguments[0].toString();
- bool settable = false;
- if (attribute == "AXValue")
- settable = accessibilityObject().canSetValueAttribute();
- result->set(settable);
-}
-
-void WebAXObjectProxy::isPressActionSupportedCallback(const CppArgumentList&, CppVariant* result)
-{
- result->set(accessibilityObject().canPress());
-}
-
-void WebAXObjectProxy::isIncrementActionSupportedCallback(const CppArgumentList&, CppVariant* result)
-{
- result->set(accessibilityObject().canIncrement());
-}
-
-void WebAXObjectProxy::isDecrementActionSupportedCallback(const CppArgumentList&, CppVariant* result)
-{
- result->set(accessibilityObject().canDecrement());
-}
-
-void WebAXObjectProxy::parentElementCallback(const CppArgumentList&, CppVariant* result)
-{
- WebAXObject parentObject = accessibilityObject().parentObject();
- while (parentObject.accessibilityIsIgnored())
- parentObject = parentObject.parentObject();
- WebAXObjectProxy* parent = m_factory->getOrCreate(parentObject);
- if (!parent) {
- result->setNull();
- return;
- }
-
- result->set(*(parent->getAsCppVariant()));
-}
-
-void WebAXObjectProxy::incrementCallback(const CppArgumentList&, CppVariant* result)
-{
- accessibilityObject().increment();
- result->setNull();
-}
-
-void WebAXObjectProxy::decrementCallback(const CppArgumentList&, CppVariant* result)
-{
- accessibilityObject().decrement();
- result->setNull();
-}
-
-void WebAXObjectProxy::showMenuCallback(const CppArgumentList&, CppVariant* result)
-{
- result->setNull();
-}
-
-void WebAXObjectProxy::pressCallback(const CppArgumentList&, CppVariant* result)
-{
- accessibilityObject().press();
- result->setNull();
-}
-
-void WebAXObjectProxy::isEqualCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- if (arguments.size() < 1 || !arguments[0].isObject()) {
- result->setNull();
- return;
- }
-
- result->set(arguments[0].isEqual(*getAsCppVariant()));
-}
-
-void WebAXObjectProxy::addNotificationListenerCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- if (arguments.size() < 1 || !arguments[0].isObject()) {
- result->setNull();
- return;
- }
-
- m_notificationCallbacks.push_back(arguments[0]);
- result->setNull();
-}
-
-void WebAXObjectProxy::removeNotificationListenerCallback(const CppArgumentList&, CppVariant* result)
-{
- // FIXME: Implement this.
- result->setNull();
-}
-
-void WebAXObjectProxy::takeFocusCallback(const CppArgumentList&, CppVariant* result)
-{
- accessibilityObject().setFocused(true);
- result->setNull();
-}
-
-void WebAXObjectProxy::scrollToMakeVisibleCallback(const CppArgumentList&, CppVariant* result)
-{
- accessibilityObject().scrollToMakeVisible();
- result->setNull();
-}
-
-void WebAXObjectProxy::scrollToMakeVisibleWithSubFocusCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- if (arguments.size() != 4
- || !arguments[0].isNumber()
- || !arguments[1].isNumber()
- || !arguments[2].isNumber()
- || !arguments[3].isNumber())
- return;
-
- int x = arguments[0].toInt32();
- int y = arguments[1].toInt32();
- int width = arguments[2].toInt32();
- int height = arguments[3].toInt32();
- accessibilityObject().scrollToMakeVisibleWithSubFocus(WebRect(x, y, width, height));
- result->setNull();
-}
-
-void WebAXObjectProxy::scrollToGlobalPointCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- if (arguments.size() != 2
- || !arguments[0].isNumber()
- || !arguments[1].isNumber())
- return;
-
- int x = arguments[0].toInt32();
- int y = arguments[1].toInt32();
-
- accessibilityObject().scrollToGlobalPoint(WebPoint(x, y));
- result->setNull();
-}
-
-void WebAXObjectProxy::wordStartCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- if (arguments.size() != 1 || !arguments[0].isNumber())
- return;
-
- if (accessibilityObject().role() != WebAXRoleStaticText)
- return;
-
- int characterIndex = arguments[0].toInt32();
- int wordStart, wordEnd;
- getBoundariesForOneWord(accessibilityObject(), characterIndex, wordStart, wordEnd);
- result->set(wordStart);
-}
-
-void WebAXObjectProxy::wordEndCallback(const CppArgumentList& arguments, CppVariant* result)
-{
- result->setNull();
-
- if (arguments.size() != 1 || !arguments[0].isNumber())
- return;
-
- if (accessibilityObject().role() != WebAXRoleStaticText)
- return;
-
- int characterIndex = arguments[0].toInt32();
- int wordStart, wordEnd;
- getBoundariesForOneWord(accessibilityObject(), characterIndex, wordStart, wordEnd);
- result->set(wordEnd);
-}
-
-void WebAXObjectProxy::fallbackCallback(const CppArgumentList &, CppVariant* result)
-{
- result->setNull();
-}
-
-RootWebAXObjectProxy::RootWebAXObjectProxy(const WebAXObject &object, Factory *factory)
- : WebAXObjectProxy(object, factory) { }
-
-WebAXObjectProxy* RootWebAXObjectProxy::getChildAtIndex(unsigned index)
-{
- if (index)
- return 0;
-
- return factory()->getOrCreate(accessibilityObject());
-}
-
-bool RootWebAXObjectProxy::isRoot() const
-{
- return true;
-}
-
-WebAXObjectProxyList::WebAXObjectProxyList()
-{
-}
-
-WebAXObjectProxyList::~WebAXObjectProxyList()
-{
- clear();
-}
-
-void WebAXObjectProxyList::clear()
-{
- for (ElementList::iterator i = m_elements.begin(); i != m_elements.end(); ++i)
- delete (*i);
- m_elements.clear();
-}
-
-WebAXObjectProxy* WebAXObjectProxyList::getOrCreate(const WebAXObject& object)
-{
- if (object.isNull())
- return 0;
-
- size_t elementCount = m_elements.size();
- for (size_t i = 0; i < elementCount; i++) {
- if (m_elements[i]->isEqual(object))
- return m_elements[i];
- }
-
- WebAXObjectProxy* element = new WebAXObjectProxy(object, this);
- m_elements.push_back(element);
- return element;
-}
-
-WebAXObjectProxy* WebAXObjectProxyList::createRoot(const WebAXObject& object)
-{
- WebAXObjectProxy* element = new RootWebAXObjectProxy(object, this);
- m_elements.push_back(element);
- return element;
-}
-
-}
diff --git a/content/shell/renderer/test_runner/WebAXObjectProxy.h b/content/shell/renderer/test_runner/WebAXObjectProxy.h
deleted file mode 100644
index 59162f2..0000000
--- a/content/shell/renderer/test_runner/WebAXObjectProxy.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_WEBAXOBJECTPROXY_H_
-#define CONTENT_SHELL_RENDERER_TEST_RUNNER_WEBAXOBJECTPROXY_H_
-
-#include <vector>
-
-#include "content/shell/renderer/test_runner/CppBoundClass.h"
-#include "third_party/WebKit/public/web/WebAXObject.h"
-
-namespace WebTestRunner {
-
-class WebAXObjectProxy : public CppBoundClass {
-public:
- class Factory {
- public:
- virtual ~Factory() { }
- virtual WebAXObjectProxy* getOrCreate(const blink::WebAXObject&) = 0;
- };
-
- WebAXObjectProxy(const blink::WebAXObject&, Factory*);
- virtual ~WebAXObjectProxy();
-
- virtual WebAXObjectProxy* getChildAtIndex(unsigned);
- virtual bool isRoot() const;
- virtual bool isEqual(const blink::WebAXObject&);
-
- virtual void notificationReceived(const char *notificationName);
-
-protected:
- const blink::WebAXObject& accessibilityObject() const { return m_accessibilityObject; }
-
- Factory* factory() const { return m_factory; }
-
-private:
- // Bound properties.
- void roleGetterCallback(CppVariant*);
- void titleGetterCallback(CppVariant*);
- void descriptionGetterCallback(CppVariant*);
- void helpTextGetterCallback(CppVariant*);
- void stringValueGetterCallback(CppVariant*);
- void xGetterCallback(CppVariant*);
- void yGetterCallback(CppVariant*);
- void widthGetterCallback(CppVariant*);
- void heightGetterCallback(CppVariant*);
- void intValueGetterCallback(CppVariant*);
- void minValueGetterCallback(CppVariant*);
- void maxValueGetterCallback(CppVariant*);
- void valueDescriptionGetterCallback(CppVariant*);
- void childrenCountGetterCallback(CppVariant*);
- void insertionPointLineNumberGetterCallback(CppVariant*);
- void selectedTextRangeGetterCallback(CppVariant*);
- void isEnabledGetterCallback(CppVariant*);
- void isRequiredGetterCallback(CppVariant*);
- void isFocusedGetterCallback(CppVariant*);
- void isFocusableGetterCallback(CppVariant*);
- void isSelectedGetterCallback(CppVariant*);
- void isSelectableGetterCallback(CppVariant*);
- void isMultiSelectableGetterCallback(CppVariant*);
- void isSelectedOptionActiveGetterCallback(CppVariant*);
- void isExpandedGetterCallback(CppVariant*);
- void isCheckedGetterCallback(CppVariant*);
- void isVisibleGetterCallback(CppVariant*);
- void isOffScreenGetterCallback(CppVariant*);
- void isCollapsedGetterCallback(CppVariant*);
- void hasPopupGetterCallback(CppVariant*);
- void isValidGetterCallback(CppVariant*);
- void isReadOnlyGetterCallback(CppVariant*);
- void orientationGetterCallback(CppVariant*);
- void clickPointXGetterCallback(CppVariant*);
- void clickPointYGetterCallback(CppVariant*);
- void rowCountGetterCallback(CppVariant*);
- void columnCountGetterCallback(CppVariant*);
- void isClickableGetterCallback(CppVariant*);
-
- // Bound methods.
- void allAttributesCallback(const CppArgumentList&, CppVariant*);
- void attributesOfChildrenCallback(const CppArgumentList&, CppVariant*);
- void lineForIndexCallback(const CppArgumentList&, CppVariant*);
- void boundsForRangeCallback(const CppArgumentList&, CppVariant*);
- void childAtIndexCallback(const CppArgumentList&, CppVariant*);
- void elementAtPointCallback(const CppArgumentList&, CppVariant*);
- void tableHeaderCallback(const CppArgumentList&, CppVariant*);
- void rowIndexRangeCallback(const CppArgumentList&, CppVariant*);
- void columnIndexRangeCallback(const CppArgumentList&, CppVariant*);
- void cellForColumnAndRowCallback(const CppArgumentList&, CppVariant*);
- void titleUIElementCallback(const CppArgumentList&, CppVariant*);
- void setSelectedTextRangeCallback(const CppArgumentList&, CppVariant*);
- void isAttributeSettableCallback(const CppArgumentList&, CppVariant*);
- void isPressActionSupportedCallback(const CppArgumentList&, CppVariant*);
- void isIncrementActionSupportedCallback(const CppArgumentList&, CppVariant*);
- void isDecrementActionSupportedCallback(const CppArgumentList&, CppVariant*);
- void parentElementCallback(const CppArgumentList&, CppVariant*);
- void incrementCallback(const CppArgumentList&, CppVariant*);
- void decrementCallback(const CppArgumentList&, CppVariant*);
- void showMenuCallback(const CppArgumentList&, CppVariant*);
- void pressCallback(const CppArgumentList&, CppVariant*);
- void isEqualCallback(const CppArgumentList&, CppVariant*);
- void addNotificationListenerCallback(const CppArgumentList&, CppVariant*);
- void removeNotificationListenerCallback(const CppArgumentList&, CppVariant*);
- void takeFocusCallback(const CppArgumentList&, CppVariant*);
- void scrollToMakeVisibleCallback(const CppArgumentList&, CppVariant*);
- void scrollToMakeVisibleWithSubFocusCallback(const CppArgumentList&, CppVariant*);
- void scrollToGlobalPointCallback(const CppArgumentList&, CppVariant*);
- void wordStartCallback(const CppArgumentList&, CppVariant*);
- void wordEndCallback(const CppArgumentList&, CppVariant*);
-
- void fallbackCallback(const CppArgumentList&, CppVariant*);
-
- blink::WebAXObject m_accessibilityObject;
- Factory* m_factory;
- std::vector<CppVariant> m_notificationCallbacks;
-};
-
-
-class RootWebAXObjectProxy : public WebAXObjectProxy {
-public:
- RootWebAXObjectProxy(const blink::WebAXObject&, Factory*);
-
- virtual WebAXObjectProxy* getChildAtIndex(unsigned) OVERRIDE;
- virtual bool isRoot() const OVERRIDE;
-};
-
-
-// Provides simple lifetime management of the WebAXObjectProxy instances:
-// all WebAXObjectProxys ever created from the controller are stored in
-// a list and cleared explicitly.
-class WebAXObjectProxyList : public WebAXObjectProxy::Factory {
-public:
- WebAXObjectProxyList();
- virtual ~WebAXObjectProxyList();
-
- void clear();
- virtual WebAXObjectProxy* getOrCreate(const blink::WebAXObject&) OVERRIDE;
- WebAXObjectProxy* createRoot(const blink::WebAXObject&);
-
-private:
- typedef std::vector<WebAXObjectProxy*> ElementList;
- ElementList m_elements;
-};
-
-}
-
-#endif // CONTENT_SHELL_RENDERER_TEST_RUNNER_WEBAXOBJECTPROXY_H_
diff --git a/content/shell/renderer/test_runner/WebTestProxy.cpp b/content/shell/renderer/test_runner/WebTestProxy.cpp
index 49e913c..2948c77 100644
--- a/content/shell/renderer/test_runner/WebTestProxy.cpp
+++ b/content/shell/renderer/test_runner/WebTestProxy.cpp
@@ -6,7 +6,6 @@
#include <cctype>
-#include "content/shell/renderer/test_runner/AccessibilityController.h"
#include "content/shell/renderer/test_runner/EventSender.h"
#include "content/shell/renderer/test_runner/MockColorChooser.h"
#include "content/shell/renderer/test_runner/MockWebSpeechInputController.h"
@@ -20,6 +19,7 @@
#include "content/shell/renderer/test_runner/WebTestInterfaces.h"
#include "content/shell/renderer/test_runner/WebTestRunner.h"
#include "content/shell/renderer/test_runner/WebUserMediaClientMock.h"
+#include "content/shell/renderer/test_runner/accessibility_controller.h"
// FIXME: Including platform_canvas.h here is a layering violation.
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebCString.h"
@@ -759,7 +759,7 @@ void WebTestProxyBase::didAutoResize(const WebSize&)
void WebTestProxyBase::postAccessibilityEvent(const blink::WebAXObject& obj, blink::WebAXEvent event)
{
if (event == blink::WebAXEventFocus)
- m_testInterfaces->accessibilityController()->setFocusedElement(obj);
+ m_testInterfaces->accessibilityController()->SetFocusedElement(obj);
const char* eventName = 0;
switch (event) {
@@ -849,9 +849,9 @@ void WebTestProxyBase::postAccessibilityEvent(const blink::WebAXObject& obj, bli
break;
}
- m_testInterfaces->accessibilityController()->notificationReceived(obj, eventName);
+ m_testInterfaces->accessibilityController()->NotificationReceived(obj, eventName);
- if (m_testInterfaces->accessibilityController()->shouldLogAccessibilityEvents()) {
+ if (m_testInterfaces->accessibilityController()->ShouldLogAccessibilityEvents()) {
string message("AccessibilityNotification - ");
message += eventName;
diff --git a/content/shell/renderer/test_runner/accessibility_controller.cc b/content/shell/renderer/test_runner/accessibility_controller.cc
new file mode 100644
index 0000000..79c6526
--- /dev/null
+++ b/content/shell/renderer/test_runner/accessibility_controller.cc
@@ -0,0 +1,272 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/shell/renderer/test_runner/accessibility_controller.h"
+
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
+#include "gin/wrappable.h"
+#include "third_party/WebKit/public/web/WebElement.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebKit.h"
+#include "third_party/WebKit/public/web/WebView.h"
+
+namespace content {
+
+class AccessibilityControllerBindings
+ : public gin::Wrappable<AccessibilityControllerBindings> {
+ public:
+ static gin::WrapperInfo kWrapperInfo;
+
+ static void Install(base::WeakPtr<AccessibilityController> controller,
+ blink::WebFrame* frame);
+
+ private:
+ explicit AccessibilityControllerBindings(
+ base::WeakPtr<AccessibilityController> controller);
+ virtual ~AccessibilityControllerBindings();
+
+ // gin::Wrappable:
+ virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) OVERRIDE;
+
+ void LogAccessibilityEvents();
+ void SetNotificationListener(v8::Handle<v8::Function> callback);
+ void UnsetNotificationListener();
+ v8::Handle<v8::Object> FocusedElement();
+ v8::Handle<v8::Object> RootElement();
+ v8::Handle<v8::Object> AccessibleElementById(const std::string& id);
+
+ base::WeakPtr<AccessibilityController> controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccessibilityControllerBindings);
+};
+
+gin::WrapperInfo AccessibilityControllerBindings::kWrapperInfo = {
+ gin::kEmbedderNativeGin};
+
+// static
+void AccessibilityControllerBindings::Install(
+ base::WeakPtr<AccessibilityController> controller,
+ blink::WebFrame* frame) {
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
+ if (context.IsEmpty())
+ return;
+
+ v8::Context::Scope context_scope(context);
+
+ gin::Handle<AccessibilityControllerBindings> bindings =
+ gin::CreateHandle(isolate,
+ new AccessibilityControllerBindings(controller));
+ v8::Handle<v8::Object> global = context->Global();
+ global->Set(gin::StringToV8(isolate, "accessibilityController"),
+ bindings.ToV8());
+}
+
+AccessibilityControllerBindings::AccessibilityControllerBindings(
+ base::WeakPtr<AccessibilityController> controller)
+ : controller_(controller) {
+}
+
+AccessibilityControllerBindings::~AccessibilityControllerBindings() {
+}
+
+gin::ObjectTemplateBuilder
+AccessibilityControllerBindings::GetObjectTemplateBuilder(
+ v8::Isolate* isolate) {
+ return gin::Wrappable<AccessibilityControllerBindings>::
+ GetObjectTemplateBuilder(isolate)
+ .SetMethod("logAccessibilityEvents",
+ &AccessibilityControllerBindings::LogAccessibilityEvents)
+ .SetMethod("setNotificationListener",
+ &AccessibilityControllerBindings::SetNotificationListener)
+ .SetMethod("unsetNotificationListener",
+ &AccessibilityControllerBindings::UnsetNotificationListener)
+ .SetProperty("focusedElement",
+ &AccessibilityControllerBindings::FocusedElement)
+ .SetProperty("rootElement",
+ &AccessibilityControllerBindings::RootElement)
+ .SetMethod("accessibleElementById",
+ &AccessibilityControllerBindings::AccessibleElementById)
+ // TODO(hajimehoshi): These are for backward compatibility. Remove them.
+ .SetMethod("addNotificationListener",
+ &AccessibilityControllerBindings::SetNotificationListener)
+ .SetMethod("removeNotificationListener",
+ &AccessibilityControllerBindings::UnsetNotificationListener);
+}
+
+void AccessibilityControllerBindings::LogAccessibilityEvents() {
+ if (controller_)
+ controller_->LogAccessibilityEvents();
+}
+
+void AccessibilityControllerBindings::SetNotificationListener(
+ v8::Handle<v8::Function> callback) {
+ if (controller_)
+ controller_->SetNotificationListener(callback);
+}
+
+void AccessibilityControllerBindings::UnsetNotificationListener() {
+ if (controller_)
+ controller_->UnsetNotificationListener();
+}
+
+v8::Handle<v8::Object> AccessibilityControllerBindings::FocusedElement() {
+ return controller_ ? controller_->FocusedElement() : v8::Handle<v8::Object>();
+}
+
+v8::Handle<v8::Object> AccessibilityControllerBindings::RootElement() {
+ return controller_ ? controller_->RootElement() : v8::Handle<v8::Object>();
+}
+
+v8::Handle<v8::Object> AccessibilityControllerBindings::AccessibleElementById(
+ const std::string& id) {
+ return controller_ ? controller_->AccessibleElementById(id)
+ : v8::Handle<v8::Object>();
+}
+
+AccessibilityController::AccessibilityController()
+ : log_accessibility_events_(false),
+ weak_factory_(this) {
+}
+
+AccessibilityController::~AccessibilityController() {}
+
+void AccessibilityController::Reset() {
+ root_element_ = blink::WebAXObject();
+ focused_element_ = blink::WebAXObject();
+ elements_.Clear();
+ notification_callback_.Reset();
+ log_accessibility_events_ = false;
+}
+
+void AccessibilityController::Install(blink::WebFrame* frame) {
+ blink::WebAXObject::enableAccessibility();
+ blink::WebAXObject::enableInlineTextBoxAccessibility();
+ AccessibilityControllerBindings::Install(weak_factory_.GetWeakPtr(), frame);
+}
+
+void AccessibilityController::SetFocusedElement(
+ const blink::WebAXObject& focused_element) {
+ focused_element_ = focused_element;
+}
+
+bool AccessibilityController::ShouldLogAccessibilityEvents() {
+ return log_accessibility_events_;
+}
+
+void AccessibilityController::NotificationReceived(
+ const blink::WebAXObject& target, const std::string& notification_name) {
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+ v8::HandleScope handle_scope(isolate);
+
+ blink::WebFrame* frame = web_view_->mainFrame();
+ if (!frame)
+ return;
+
+ v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
+ if (context.IsEmpty())
+ return;
+
+ v8::Context::Scope context_scope(context);
+
+ // Call notification listeners on the element.
+ v8::Handle<v8::Object> element_handle = elements_.GetOrCreate(target);
+ WebAXObjectProxy* element;
+ bool result = gin::ConvertFromV8(isolate, element_handle, &element);
+ DCHECK(result);
+ element->NotificationReceived(frame, notification_name);
+
+ if (notification_callback_.IsEmpty())
+ return;
+
+ // Call global notification listeners.
+ v8::Handle<v8::Value> argv[] = {
+ element_handle,
+ v8::String::NewFromUtf8(isolate, notification_name.data(),
+ v8::String::kNormalString,
+ notification_name.size()),
+ };
+ frame->callFunctionEvenIfScriptDisabled(
+ v8::Local<v8::Function>::New(isolate, notification_callback_),
+ context->Global(),
+ arraysize(argv),
+ argv);
+}
+
+void AccessibilityController::SetDelegate(
+ WebTestRunner::WebTestDelegate* delegate) {
+ delegate_ = delegate;
+}
+
+void AccessibilityController::SetWebView(blink::WebView* web_view) {
+ web_view_ = web_view;
+}
+
+void AccessibilityController::LogAccessibilityEvents() {
+ log_accessibility_events_ = true;
+}
+
+void AccessibilityController::SetNotificationListener(
+ v8::Handle<v8::Function> callback) {
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+ notification_callback_.Reset(isolate, callback);
+}
+
+void AccessibilityController::UnsetNotificationListener() {
+ notification_callback_.Reset();
+}
+
+v8::Handle<v8::Object> AccessibilityController::FocusedElement() {
+ if (focused_element_.isNull())
+ focused_element_ = web_view_->accessibilityObject();
+ return elements_.GetOrCreate(focused_element_);
+}
+
+v8::Handle<v8::Object> AccessibilityController::RootElement() {
+ if (root_element_.isNull())
+ root_element_ = web_view_->accessibilityObject();
+ return elements_.CreateRoot(root_element_);
+}
+
+v8::Handle<v8::Object>
+AccessibilityController::AccessibleElementById(const std::string& id) {
+ if (root_element_.isNull())
+ root_element_ = web_view_->accessibilityObject();
+
+ if (!root_element_.updateBackingStoreAndCheckValidity())
+ return v8::Handle<v8::Object>();
+
+ return FindAccessibleElementByIdRecursive(
+ root_element_, blink::WebString::fromUTF8(id.c_str()));
+}
+
+v8::Handle<v8::Object>
+AccessibilityController::FindAccessibleElementByIdRecursive(
+ const blink::WebAXObject& obj, const blink::WebString& id) {
+ if (obj.isNull() || obj.isDetached())
+ return v8::Handle<v8::Object>();
+
+ blink::WebNode node = obj.node();
+ if (!node.isNull() && node.isElementNode()) {
+ blink::WebElement element = node.to<blink::WebElement>();
+ element.getAttribute("id");
+ if (element.getAttribute("id") == id)
+ return elements_.GetOrCreate(obj);
+ }
+
+ unsigned childCount = obj.childCount();
+ for (unsigned i = 0; i < childCount; i++) {
+ v8::Handle<v8::Object> result =
+ FindAccessibleElementByIdRecursive(obj.childAt(i), id);
+ if (*result)
+ return result;
+ }
+
+ return v8::Handle<v8::Object>();
+}
+
+} // namespace content
diff --git a/content/shell/renderer/test_runner/accessibility_controller.h b/content/shell/renderer/test_runner/accessibility_controller.h
new file mode 100644
index 0000000..30e0131
--- /dev/null
+++ b/content/shell/renderer/test_runner/accessibility_controller.h
@@ -0,0 +1,77 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_ACCESSIBILITY_CONTROLLER_H_
+#define CONTENT_SHELL_RENDERER_TEST_RUNNER_ACCESSIBILITY_CONTROLLER_H_
+
+#include <vector>
+
+#include "base/memory/weak_ptr.h"
+#include "content/shell/renderer/test_runner/web_ax_object_proxy.h"
+#include "third_party/WebKit/public/web/WebAXObject.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+class WebFrame;
+class WebString;
+class WebView;
+}
+
+namespace WebTestRunner {
+class WebTestDelegate;
+}
+
+namespace content {
+
+class AccessibilityController :
+ public base::SupportsWeakPtr<AccessibilityController> {
+ public:
+ AccessibilityController();
+ ~AccessibilityController();
+
+ void Reset();
+ void Install(blink::WebFrame* frame);
+ void SetFocusedElement(const blink::WebAXObject&);
+ bool ShouldLogAccessibilityEvents();
+ void NotificationReceived(const blink::WebAXObject& target,
+ const std::string& notification_name);
+
+ void SetDelegate(WebTestRunner::WebTestDelegate* delegate);
+ void SetWebView(blink::WebView* web_view);
+
+ private:
+ friend class AccessibilityControllerBindings;
+
+ // Bound methods and properties
+ void LogAccessibilityEvents();
+ void SetNotificationListener(v8::Handle<v8::Function> callback);
+ void UnsetNotificationListener();
+ v8::Handle<v8::Object> FocusedElement();
+ v8::Handle<v8::Object> RootElement();
+ v8::Handle<v8::Object> AccessibleElementById(const std::string& id);
+
+ v8::Handle<v8::Object> FindAccessibleElementByIdRecursive(
+ const blink::WebAXObject&, const blink::WebString& id);
+
+ // If true, will log all accessibility notifications.
+ bool log_accessibility_events_;
+
+ blink::WebAXObject focused_element_;
+ blink::WebAXObject root_element_;
+
+ WebAXObjectProxyList elements_;
+
+ v8::Persistent<v8::Function> notification_callback_;
+
+ WebTestRunner::WebTestDelegate* delegate_;
+ blink::WebView* web_view_;
+
+ base::WeakPtrFactory<AccessibilityController> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccessibilityController);
+};
+
+} // namespace content
+
+#endif // CONTENT_SHELL_RENDERER_TEST_RUNNER_ACCESSIBILITY_CONTROLLER_H_
diff --git a/content/shell/renderer/test_runner/unsafe_persistent.h b/content/shell/renderer/test_runner/unsafe_persistent.h
new file mode 100644
index 0000000..b47a33e
--- /dev/null
+++ b/content/shell/renderer/test_runner/unsafe_persistent.h
@@ -0,0 +1,50 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_UNSAFE_PERSISTENT_H_
+#define CONTENT_SHELL_RENDERER_TEST_RUNNER_UNSAFE_PERSISTENT_H_
+
+#include "v8/include/v8.h"
+
+namespace content {
+
+// An unsafe way to pass Persistent handles around. Do not use unless you know
+// what you're doing. UnsafePersistent is only safe to use when we know that the
+// memory pointed by it is not going away: 1) When GC cannot happen while the
+// UnsafePersistent is alive or 2) when there is a strong Persistent keeping the
+// memory alive while the UnsafePersistent is alive.
+template<typename T> class UnsafePersistent {
+ public:
+ UnsafePersistent() : value_(0) { }
+
+ explicit UnsafePersistent(v8::Persistent<T>* handle) {
+ value_ = handle->ClearAndLeak();
+ }
+
+ UnsafePersistent(v8::Isolate* isolate, const v8::Handle<T>& handle) {
+ v8::Persistent<T> persistent(isolate, handle);
+ value_ = persistent.ClearAndLeak();
+ }
+
+ // Usage of this function requires
+ // V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR to be defined
+ void Dispose() {
+ v8::Persistent<T> handle(value_);
+ handle.Reset();
+ value_ = 0;
+ }
+
+ // Usage of this function requires
+ // V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR to be defined
+ v8::Local<T> NewLocal(v8::Isolate* isolate) {
+ return v8::Local<T>::New(isolate, v8::Local<T>(value_));
+ }
+
+ private:
+ T* value_;
+};
+
+} // namespace content
+
+#endif // CONTENT_SHELL_RENDERER_TEST_RUNNER_UNSAFE_PERSISTENT_H_
diff --git a/content/shell/renderer/test_runner/web_ax_object_proxy.cc b/content/shell/renderer/test_runner/web_ax_object_proxy.cc
new file mode 100644
index 0000000..7d6f186
--- /dev/null
+++ b/content/shell/renderer/test_runner/web_ax_object_proxy.cc
@@ -0,0 +1,1024 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(hajimehoshi): Remove this when UnsafePersistent is removed.
+#define V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR
+
+#include "content/shell/renderer/test_runner/web_ax_object_proxy.h"
+
+#include "base/strings/stringprintf.h"
+#include "gin/handle.h"
+#include "third_party/WebKit/public/platform/WebPoint.h"
+#include "third_party/WebKit/public/platform/WebRect.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebKit.h"
+
+namespace content {
+
+namespace {
+
+// Map role value to string, matching Safari/Mac platform implementation to
+// avoid rebaselining layout tests.
+std::string RoleToString(blink::WebAXRole role)
+{
+ std::string result = "AXRole: AX";
+ switch (role) {
+ case blink::WebAXRoleAlertDialog:
+ return result.append("AlertDialog");
+ case blink::WebAXRoleAlert:
+ return result.append("Alert");
+ case blink::WebAXRoleAnnotation:
+ return result.append("Annotation");
+ case blink::WebAXRoleApplication:
+ return result.append("Application");
+ case blink::WebAXRoleArticle:
+ return result.append("Article");
+ case blink::WebAXRoleBanner:
+ return result.append("Banner");
+ case blink::WebAXRoleBrowser:
+ return result.append("Browser");
+ case blink::WebAXRoleBusyIndicator:
+ return result.append("BusyIndicator");
+ case blink::WebAXRoleButton:
+ return result.append("Button");
+ case blink::WebAXRoleCanvas:
+ return result.append("Canvas");
+ case blink::WebAXRoleCell:
+ return result.append("Cell");
+ case blink::WebAXRoleCheckBox:
+ return result.append("CheckBox");
+ case blink::WebAXRoleColorWell:
+ return result.append("ColorWell");
+ case blink::WebAXRoleColumnHeader:
+ return result.append("ColumnHeader");
+ case blink::WebAXRoleColumn:
+ return result.append("Column");
+ case blink::WebAXRoleComboBox:
+ return result.append("ComboBox");
+ case blink::WebAXRoleComplementary:
+ return result.append("Complementary");
+ case blink::WebAXRoleContentInfo:
+ return result.append("ContentInfo");
+ case blink::WebAXRoleDefinition:
+ return result.append("Definition");
+ case blink::WebAXRoleDescriptionListDetail:
+ return result.append("DescriptionListDetail");
+ case blink::WebAXRoleDescriptionListTerm:
+ return result.append("DescriptionListTerm");
+ case blink::WebAXRoleDialog:
+ return result.append("Dialog");
+ case blink::WebAXRoleDirectory:
+ return result.append("Directory");
+ case blink::WebAXRoleDisclosureTriangle:
+ return result.append("DisclosureTriangle");
+ case blink::WebAXRoleDiv:
+ return result.append("Div");
+ case blink::WebAXRoleDocument:
+ return result.append("Document");
+ case blink::WebAXRoleDrawer:
+ return result.append("Drawer");
+ case blink::WebAXRoleEditableText:
+ return result.append("EditableText");
+ case blink::WebAXRoleFooter:
+ return result.append("Footer");
+ case blink::WebAXRoleForm:
+ return result.append("Form");
+ case blink::WebAXRoleGrid:
+ return result.append("Grid");
+ case blink::WebAXRoleGroup:
+ return result.append("Group");
+ case blink::WebAXRoleGrowArea:
+ return result.append("GrowArea");
+ case blink::WebAXRoleHeading:
+ return result.append("Heading");
+ case blink::WebAXRoleHelpTag:
+ return result.append("HelpTag");
+ case blink::WebAXRoleHorizontalRule:
+ return result.append("HorizontalRule");
+ case blink::WebAXRoleIgnored:
+ return result.append("Ignored");
+ case blink::WebAXRoleImageMapLink:
+ return result.append("ImageMapLink");
+ case blink::WebAXRoleImageMap:
+ return result.append("ImageMap");
+ case blink::WebAXRoleImage:
+ return result.append("Image");
+ case blink::WebAXRoleIncrementor:
+ return result.append("Incrementor");
+ case blink::WebAXRoleInlineTextBox:
+ return result.append("InlineTextBox");
+ case blink::WebAXRoleLabel:
+ return result.append("Label");
+ case blink::WebAXRoleLegend:
+ return result.append("Legend");
+ case blink::WebAXRoleLink:
+ return result.append("Link");
+ case blink::WebAXRoleListBoxOption:
+ return result.append("ListBoxOption");
+ case blink::WebAXRoleListBox:
+ return result.append("ListBox");
+ case blink::WebAXRoleListItem:
+ return result.append("ListItem");
+ case blink::WebAXRoleListMarker:
+ return result.append("ListMarker");
+ case blink::WebAXRoleList:
+ return result.append("List");
+ case blink::WebAXRoleLog:
+ return result.append("Log");
+ case blink::WebAXRoleMain:
+ return result.append("Main");
+ case blink::WebAXRoleMarquee:
+ return result.append("Marquee");
+ case blink::WebAXRoleMathElement:
+ return result.append("MathElement");
+ case blink::WebAXRoleMath:
+ return result.append("Math");
+ case blink::WebAXRoleMatte:
+ return result.append("Matte");
+ case blink::WebAXRoleMenuBar:
+ return result.append("MenuBar");
+ case blink::WebAXRoleMenuButton:
+ return result.append("MenuButton");
+ case blink::WebAXRoleMenuItem:
+ return result.append("MenuItem");
+ case blink::WebAXRoleMenuListOption:
+ return result.append("MenuListOption");
+ case blink::WebAXRoleMenuListPopup:
+ return result.append("MenuListPopup");
+ case blink::WebAXRoleMenu:
+ return result.append("Menu");
+ case blink::WebAXRoleNavigation:
+ return result.append("Navigation");
+ case blink::WebAXRoleNote:
+ return result.append("Note");
+ case blink::WebAXRoleOutline:
+ return result.append("Outline");
+ case blink::WebAXRoleParagraph:
+ return result.append("Paragraph");
+ case blink::WebAXRolePopUpButton:
+ return result.append("PopUpButton");
+ case blink::WebAXRolePresentational:
+ return result.append("Presentational");
+ case blink::WebAXRoleProgressIndicator:
+ return result.append("ProgressIndicator");
+ case blink::WebAXRoleRadioButton:
+ return result.append("RadioButton");
+ case blink::WebAXRoleRadioGroup:
+ return result.append("RadioGroup");
+ case blink::WebAXRoleRegion:
+ return result.append("Region");
+ case blink::WebAXRoleRootWebArea:
+ return result.append("RootWebArea");
+ case blink::WebAXRoleRowHeader:
+ return result.append("RowHeader");
+ case blink::WebAXRoleRow:
+ return result.append("Row");
+ case blink::WebAXRoleRulerMarker:
+ return result.append("RulerMarker");
+ case blink::WebAXRoleRuler:
+ return result.append("Ruler");
+ case blink::WebAXRoleSVGRoot:
+ return result.append("SVGRoot");
+ case blink::WebAXRoleScrollArea:
+ return result.append("ScrollArea");
+ case blink::WebAXRoleScrollBar:
+ return result.append("ScrollBar");
+ case blink::WebAXRoleSeamlessWebArea:
+ return result.append("SeamlessWebArea");
+ case blink::WebAXRoleSearch:
+ return result.append("Search");
+ case blink::WebAXRoleSheet:
+ return result.append("Sheet");
+ case blink::WebAXRoleSlider:
+ return result.append("Slider");
+ case blink::WebAXRoleSliderThumb:
+ return result.append("SliderThumb");
+ case blink::WebAXRoleSpinButtonPart:
+ return result.append("SpinButtonPart");
+ case blink::WebAXRoleSpinButton:
+ return result.append("SpinButton");
+ case blink::WebAXRoleSplitGroup:
+ return result.append("SplitGroup");
+ case blink::WebAXRoleSplitter:
+ return result.append("Splitter");
+ case blink::WebAXRoleStaticText:
+ return result.append("StaticText");
+ case blink::WebAXRoleStatus:
+ return result.append("Status");
+ case blink::WebAXRoleSystemWide:
+ return result.append("SystemWide");
+ case blink::WebAXRoleTabGroup:
+ return result.append("TabGroup");
+ case blink::WebAXRoleTabList:
+ return result.append("TabList");
+ case blink::WebAXRoleTabPanel:
+ return result.append("TabPanel");
+ case blink::WebAXRoleTab:
+ return result.append("Tab");
+ case blink::WebAXRoleTableHeaderContainer:
+ return result.append("TableHeaderContainer");
+ case blink::WebAXRoleTable:
+ return result.append("Table");
+ case blink::WebAXRoleTextArea:
+ return result.append("TextArea");
+ case blink::WebAXRoleTextField:
+ return result.append("TextField");
+ case blink::WebAXRoleTimer:
+ return result.append("Timer");
+ case blink::WebAXRoleToggleButton:
+ return result.append("ToggleButton");
+ case blink::WebAXRoleToolbar:
+ return result.append("Toolbar");
+ case blink::WebAXRoleTreeGrid:
+ return result.append("TreeGrid");
+ case blink::WebAXRoleTreeItem:
+ return result.append("TreeItem");
+ case blink::WebAXRoleTree:
+ return result.append("Tree");
+ case blink::WebAXRoleUnknown:
+ return result.append("Unknown");
+ case blink::WebAXRoleUserInterfaceTooltip:
+ return result.append("UserInterfaceTooltip");
+ case blink::WebAXRoleValueIndicator:
+ return result.append("ValueIndicator");
+ case blink::WebAXRoleWebArea:
+ return result.append("WebArea");
+ case blink::WebAXRoleWindow:
+ return result.append("Window");
+ default:
+ return result.append("Unknown");
+ }
+}
+
+std::string GetDescription(const blink::WebAXObject& object) {
+ std::string description = object.accessibilityDescription().utf8();
+ return description.insert(0, "AXDescription: ");
+}
+
+std::string GetHelpText(const blink::WebAXObject& object) {
+ std::string help_text = object.helpText().utf8();
+ return help_text.insert(0, "AXHelp: ");
+}
+
+std::string GetStringValue(const blink::WebAXObject& object) {
+ std::string value;
+ if (object.role() == blink::WebAXRoleColorWell) {
+ int r, g, b;
+ object.colorValue(r, g, b);
+ value = base::StringPrintf("rgb %7.5f %7.5f %7.5f 1",
+ r / 255., g / 255., b / 255.);
+ } else {
+ value = object.stringValue().utf8();
+ }
+ return value.insert(0, "AXValue: ");
+}
+
+std::string GetRole(const blink::WebAXObject& object) {
+ std::string role_string = RoleToString(object.role());
+
+ // Special-case canvas with fallback content because Chromium wants to treat
+ // this as essentially a separate role that it can map differently depending
+ // on the platform.
+ if (object.role() == blink::WebAXRoleCanvas &&
+ object.canvasHasFallbackContent()) {
+ role_string += "WithFallbackContent";
+ }
+
+ return role_string;
+}
+
+std::string GetTitle(const blink::WebAXObject& object) {
+ std::string title = object.title().utf8();
+ return title.insert(0, "AXTitle: ");
+}
+
+std::string GetOrientation(const blink::WebAXObject& object) {
+ if (object.isVertical())
+ return "AXOrientation: AXVerticalOrientation";
+
+ return "AXOrientation: AXHorizontalOrientation";
+}
+
+std::string GetValueDescription(const blink::WebAXObject& object) {
+ std::string value_description = object.valueDescription().utf8();
+ return value_description.insert(0, "AXValueDescription: ");
+}
+
+std::string GetAttributes(const blink::WebAXObject& object) {
+ // FIXME: Concatenate all attributes of the AXObject.
+ std::string attributes(GetTitle(object));
+ attributes.append("\n");
+ attributes.append(GetRole(object));
+ attributes.append("\n");
+ attributes.append(GetDescription(object));
+ return attributes;
+}
+
+blink::WebRect BoundsForCharacter(const blink::WebAXObject& object,
+ int characterIndex) {
+ DCHECK_EQ(object.role(), blink::WebAXRoleStaticText);
+ int end = 0;
+ for (unsigned i = 0; i < object.childCount(); i++) {
+ blink::WebAXObject inline_text_box = object.childAt(i);
+ DCHECK_EQ(inline_text_box.role(), blink::WebAXRoleInlineTextBox);
+ int start = end;
+ end += inline_text_box.stringValue().length();
+ if (end <= characterIndex)
+ continue;
+ blink::WebRect inline_text_box_rect = inline_text_box.boundingBoxRect();
+ int localIndex = characterIndex - start;
+ blink::WebVector<int> character_offsets;
+ inline_text_box.characterOffsets(character_offsets);
+ DCHECK(character_offsets.size() > 0 &&
+ character_offsets.size() == inline_text_box.stringValue().length());
+ switch (inline_text_box.textDirection()) {
+ case blink::WebAXTextDirectionLR: {
+ if (localIndex) {
+ int left = inline_text_box_rect.x + character_offsets[localIndex - 1];
+ int width = character_offsets[localIndex] -
+ character_offsets[localIndex - 1];
+ return blink::WebRect(left, inline_text_box_rect.y,
+ width, inline_text_box_rect.height);
+ }
+ return blink::WebRect(
+ inline_text_box_rect.x, inline_text_box_rect.y,
+ character_offsets[0], inline_text_box_rect.height);
+ }
+ case blink::WebAXTextDirectionRL: {
+ int right = inline_text_box_rect.x + inline_text_box_rect.width;
+
+ if (localIndex) {
+ int left = right - character_offsets[localIndex];
+ int width = character_offsets[localIndex] -
+ character_offsets[localIndex - 1];
+ return blink::WebRect(left, inline_text_box_rect.y,
+ width, inline_text_box_rect.height);
+ }
+ int left = right - character_offsets[0];
+ return blink::WebRect(
+ left, inline_text_box_rect.y,
+ character_offsets[0], inline_text_box_rect.height);
+ }
+ case blink::WebAXTextDirectionTB: {
+ if (localIndex) {
+ int top = inline_text_box_rect.y + character_offsets[localIndex - 1];
+ int height = character_offsets[localIndex] -
+ character_offsets[localIndex - 1];
+ return blink::WebRect(inline_text_box_rect.x, top,
+ inline_text_box_rect.width, height);
+ }
+ return blink::WebRect(inline_text_box_rect.x, inline_text_box_rect.y,
+ inline_text_box_rect.width, character_offsets[0]);
+ }
+ case blink::WebAXTextDirectionBT: {
+ int bottom = inline_text_box_rect.y + inline_text_box_rect.height;
+
+ if (localIndex) {
+ int top = bottom - character_offsets[localIndex];
+ int height = character_offsets[localIndex] -
+ character_offsets[localIndex - 1];
+ return blink::WebRect(inline_text_box_rect.x, top,
+ inline_text_box_rect.width, height);
+ }
+ int top = bottom - character_offsets[0];
+ return blink::WebRect(inline_text_box_rect.x, top,
+ inline_text_box_rect.width, character_offsets[0]);
+ }
+ }
+ }
+
+ DCHECK(false);
+ return blink::WebRect();
+}
+
+void GetBoundariesForOneWord(const blink::WebAXObject& object,
+ int character_index,
+ int& word_start,
+ int& word_end) {
+ int end = 0;
+ for (unsigned i = 0; i < object.childCount(); i++) {
+ blink::WebAXObject inline_text_box = object.childAt(i);
+ DCHECK_EQ(inline_text_box.role(), blink::WebAXRoleInlineTextBox);
+ int start = end;
+ end += inline_text_box.stringValue().length();
+ if (end <= character_index)
+ continue;
+ int localIndex = character_index - start;
+
+ blink::WebVector<int> starts;
+ blink::WebVector<int> ends;
+ inline_text_box.wordBoundaries(starts, ends);
+ size_t word_count = starts.size();
+ DCHECK_EQ(ends.size(), word_count);
+
+ // If there are no words, use the InlineTextBox boundaries.
+ if (!word_count) {
+ word_start = start;
+ word_end = end;
+ return;
+ }
+
+ // Look for a character within any word other than the last.
+ for (size_t j = 0; j < word_count - 1; j++) {
+ if (localIndex <= ends[j]) {
+ word_start = start + starts[j];
+ word_end = start + ends[j];
+ return;
+ }
+ }
+
+ // Return the last word by default.
+ word_start = start + starts[word_count - 1];
+ word_end = start + ends[word_count - 1];
+ return;
+ }
+}
+
+// Collects attributes into a string, delimited by dashes. Used by all methods
+// that output lists of attributes: attributesOfLinkedUIElementsCallback,
+// AttributesOfChildrenCallback, etc.
+class AttributesCollector {
+ public:
+ AttributesCollector() {}
+ ~AttributesCollector() {}
+
+ void CollectAttributes(const blink::WebAXObject& object) {
+ attributes_.append("\n------------\n");
+ attributes_.append(GetAttributes(object));
+ }
+
+ std::string attributes() const { return attributes_; }
+
+ private:
+ std::string attributes_;
+
+ DISALLOW_COPY_AND_ASSIGN(AttributesCollector);
+};
+
+} // namespace
+
+gin::WrapperInfo WebAXObjectProxy::kWrapperInfo = {
+ gin::kEmbedderNativeGin};
+
+WebAXObjectProxy::WebAXObjectProxy(const blink::WebAXObject& object,
+ WebAXObjectProxy::Factory* factory)
+ : accessibility_object_(object),
+ factory_(factory) {
+}
+
+WebAXObjectProxy::~WebAXObjectProxy() {}
+
+gin::ObjectTemplateBuilder
+WebAXObjectProxy::GetObjectTemplateBuilder(v8::Isolate* isolate) {
+ return gin::Wrappable<WebAXObjectProxy>::GetObjectTemplateBuilder(isolate)
+ .SetProperty("role", &WebAXObjectProxy::Role)
+ .SetProperty("title", &WebAXObjectProxy::Title)
+ .SetProperty("description", &WebAXObjectProxy::Description)
+ .SetProperty("helpText", &WebAXObjectProxy::HelpText)
+ .SetProperty("stringValue", &WebAXObjectProxy::StringValue)
+ .SetProperty("x", &WebAXObjectProxy::X)
+ .SetProperty("y", &WebAXObjectProxy::Y)
+ .SetProperty("width", &WebAXObjectProxy::Width)
+ .SetProperty("height", &WebAXObjectProxy::Height)
+ .SetProperty("intValue", &WebAXObjectProxy::IntValue)
+ .SetProperty("minValue", &WebAXObjectProxy::MinValue)
+ .SetProperty("maxValue", &WebAXObjectProxy::MaxValue)
+ .SetProperty("valueDescription", &WebAXObjectProxy::ValueDescription)
+ .SetProperty("childrenCount", &WebAXObjectProxy::ChildrenCount)
+ .SetProperty("insertionPointLineNumber",
+ &WebAXObjectProxy::InsertionPointLineNumber)
+ .SetProperty("selectedTextRange", &WebAXObjectProxy::SelectedTextRange)
+ .SetProperty("isEnabled", &WebAXObjectProxy::IsEnabled)
+ .SetProperty("isRequired", &WebAXObjectProxy::IsRequired)
+ .SetProperty("isFocused", &WebAXObjectProxy::IsFocused)
+ .SetProperty("isFocusable", &WebAXObjectProxy::IsFocusable)
+ .SetProperty("isSelected", &WebAXObjectProxy::IsSelected)
+ .SetProperty("isSelectable", &WebAXObjectProxy::IsSelectable)
+ .SetProperty("isMultiSelectable", &WebAXObjectProxy::IsMultiSelectable)
+ .SetProperty("isSelectedOptionActive",
+ &WebAXObjectProxy::IsSelectedOptionActive)
+ .SetProperty("isExpanded", &WebAXObjectProxy::IsExpanded)
+ .SetProperty("isChecked", &WebAXObjectProxy::IsChecked)
+ .SetProperty("isVisible", &WebAXObjectProxy::IsVisible)
+ .SetProperty("isOffScreen", &WebAXObjectProxy::IsOffScreen)
+ .SetProperty("isCollapsed", &WebAXObjectProxy::IsCollapsed)
+ .SetProperty("hasPopup", &WebAXObjectProxy::HasPopup)
+ .SetProperty("isValid", &WebAXObjectProxy::IsValid)
+ .SetProperty("isReadOnly", &WebAXObjectProxy::IsReadOnly)
+ .SetProperty("orientation", &WebAXObjectProxy::Orientation)
+ .SetProperty("clickPointX", &WebAXObjectProxy::ClickPointX)
+ .SetProperty("clickPointY", &WebAXObjectProxy::ClickPointY)
+ .SetProperty("rowCount", &WebAXObjectProxy::RowCount)
+ .SetProperty("columnCount", &WebAXObjectProxy::ColumnCount)
+ .SetProperty("isClickable", &WebAXObjectProxy::IsClickable)
+ .SetMethod("allAttributes", &WebAXObjectProxy::AllAttributes)
+ .SetMethod("attributesOfChildren",
+ &WebAXObjectProxy::AttributesOfChildren)
+ .SetMethod("lineForIndex", &WebAXObjectProxy::LineForIndex)
+ .SetMethod("boundsForRange", &WebAXObjectProxy::BoundsForRange)
+ .SetMethod("childAtIndex", &WebAXObjectProxy::ChildAtIndex)
+ .SetMethod("elementAtPoint", &WebAXObjectProxy::ElementAtPoint)
+ .SetMethod("tableHeader", &WebAXObjectProxy::TableHeader)
+ .SetMethod("rowIndexRange", &WebAXObjectProxy::RowIndexRange)
+ .SetMethod("columnIndexRange", &WebAXObjectProxy::ColumnIndexRange)
+ .SetMethod("cellForColumnAndRow", &WebAXObjectProxy::CellForColumnAndRow)
+ .SetMethod("titleUIElement", &WebAXObjectProxy::TitleUIElement)
+ .SetMethod("setSelectedTextRange",
+ &WebAXObjectProxy::SetSelectedTextRange)
+ .SetMethod("isAttributeSettable", &WebAXObjectProxy::IsAttributeSettable)
+ .SetMethod("isPressActionSupported",
+ &WebAXObjectProxy::IsPressActionSupported)
+ .SetMethod("isIncrementActionSupported",
+ &WebAXObjectProxy::IsIncrementActionSupported)
+ .SetMethod("isDecrementActionSupported",
+ &WebAXObjectProxy::IsDecrementActionSupported)
+ .SetMethod("parentElement", &WebAXObjectProxy::ParentElement)
+ .SetMethod("increment", &WebAXObjectProxy::Increment)
+ .SetMethod("decrement", &WebAXObjectProxy::Decrement)
+ .SetMethod("showMenu", &WebAXObjectProxy::ShowMenu)
+ .SetMethod("press", &WebAXObjectProxy::Press)
+ .SetMethod("isEqual", &WebAXObjectProxy::IsEqual)
+ .SetMethod("setNotificationListener",
+ &WebAXObjectProxy::SetNotificationListener)
+ .SetMethod("unsetNotificationListener",
+ &WebAXObjectProxy::UnsetNotificationListener)
+ .SetMethod("takeFocus", &WebAXObjectProxy::TakeFocus)
+ .SetMethod("scrollToMakeVisible", &WebAXObjectProxy::ScrollToMakeVisible)
+ .SetMethod("scrollToMakeVisibleWithSubFocus",
+ &WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus)
+ .SetMethod("scrollToGlobalPoint", &WebAXObjectProxy::ScrollToGlobalPoint)
+ .SetMethod("wordStart", &WebAXObjectProxy::WordStart)
+ .SetMethod("wordEnd", &WebAXObjectProxy::WordEnd)
+ // TODO(hajimehoshi): This is for backward compatibility. Remove them.
+ .SetMethod("addNotificationListener",
+ &WebAXObjectProxy::SetNotificationListener)
+ .SetMethod("removeNotificationListener",
+ &WebAXObjectProxy::UnsetNotificationListener);
+}
+
+v8::Handle<v8::Object> WebAXObjectProxy::GetChildAtIndex(unsigned index) {
+ return factory_->GetOrCreate(accessibility_object().childAt(index));
+}
+
+bool WebAXObjectProxy::IsRoot() const {
+ return false;
+}
+
+bool WebAXObjectProxy::IsEqualToObject(const blink::WebAXObject& other) {
+ return accessibility_object().equals(other);
+}
+
+void WebAXObjectProxy::NotificationReceived(
+ blink::WebFrame* frame,
+ const std::string& notification_name) {
+ if (notification_callback_.IsEmpty())
+ return;
+
+ v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
+ if (context.IsEmpty())
+ return;
+
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+
+ v8::Handle<v8::Value> argv[] = {
+ v8::String::NewFromUtf8(isolate, notification_name.data(),
+ v8::String::kNormalString,
+ notification_name.size()),
+ };
+ frame->callFunctionEvenIfScriptDisabled(
+ v8::Local<v8::Function>::New(isolate, notification_callback_),
+ context->Global(),
+ arraysize(argv),
+ argv);
+}
+
+std::string WebAXObjectProxy::Role() {
+ return GetRole(accessibility_object());
+}
+
+std::string WebAXObjectProxy::Title() {
+ return GetTitle(accessibility_object());
+}
+
+std::string WebAXObjectProxy::Description() {
+ return GetDescription(accessibility_object());
+}
+
+std::string WebAXObjectProxy::HelpText() {
+ return GetHelpText(accessibility_object());
+}
+
+std::string WebAXObjectProxy::StringValue() {
+ return GetStringValue(accessibility_object());
+}
+
+int WebAXObjectProxy::X() {
+ return accessibility_object().boundingBoxRect().x;
+}
+
+int WebAXObjectProxy::Y() {
+ return accessibility_object().boundingBoxRect().y;
+}
+
+int WebAXObjectProxy::Width() {
+ return accessibility_object().boundingBoxRect().width;
+}
+
+int WebAXObjectProxy::Height() {
+ return accessibility_object().boundingBoxRect().height;
+}
+
+int WebAXObjectProxy::IntValue() {
+ if (accessibility_object().supportsRangeValue())
+ return accessibility_object().valueForRange();
+ else if (accessibility_object().role() == blink::WebAXRoleHeading)
+ return accessibility_object().headingLevel();
+ else
+ return atoi(accessibility_object().stringValue().utf8().data());
+}
+
+int WebAXObjectProxy::MinValue() {
+ return accessibility_object().minValueForRange();
+}
+
+int WebAXObjectProxy::MaxValue() {
+ return accessibility_object().maxValueForRange();
+}
+
+std::string WebAXObjectProxy::ValueDescription() {
+ return GetValueDescription(accessibility_object());
+}
+
+int WebAXObjectProxy::ChildrenCount() {
+ int count = 1; // Root object always has only one child, the WebView.
+ if (!IsRoot())
+ count = accessibility_object().childCount();
+ return count;
+}
+
+int WebAXObjectProxy::InsertionPointLineNumber() {
+ if (!accessibility_object().isFocused())
+ return -1;
+ return accessibility_object().selectionEndLineNumber();
+}
+
+std::string WebAXObjectProxy::SelectedTextRange() {
+ unsigned selection_start = accessibility_object().selectionStart();
+ unsigned selection_end = accessibility_object().selectionEnd();
+ return base::StringPrintf("{%d, %d}",
+ selection_start, selection_end - selection_start);
+}
+
+bool WebAXObjectProxy::IsEnabled() {
+ return accessibility_object().isEnabled();
+}
+
+bool WebAXObjectProxy::IsRequired() {
+ return accessibility_object().isRequired();
+}
+
+bool WebAXObjectProxy::IsFocused() {
+ return accessibility_object().isFocused();
+}
+
+bool WebAXObjectProxy::IsFocusable() {
+ return accessibility_object().canSetFocusAttribute();
+}
+
+bool WebAXObjectProxy::IsSelected() {
+ return accessibility_object().isSelected();
+}
+
+bool WebAXObjectProxy::IsSelectable() {
+ return accessibility_object().canSetSelectedAttribute();
+}
+
+bool WebAXObjectProxy::IsMultiSelectable() {
+ return accessibility_object().isMultiSelectable();
+}
+
+bool WebAXObjectProxy::IsSelectedOptionActive() {
+ return accessibility_object().isSelectedOptionActive();
+}
+
+bool WebAXObjectProxy::IsExpanded() {
+ return !accessibility_object().isCollapsed();
+}
+
+bool WebAXObjectProxy::IsChecked() {
+ return accessibility_object().isChecked();
+}
+
+bool WebAXObjectProxy::IsVisible() {
+ return accessibility_object().isVisible();
+}
+
+bool WebAXObjectProxy::IsOffScreen() {
+ return accessibility_object().isOffScreen();
+}
+
+bool WebAXObjectProxy::IsCollapsed() {
+ return accessibility_object().isCollapsed();
+}
+
+bool WebAXObjectProxy::HasPopup() {
+ return accessibility_object().ariaHasPopup();
+}
+
+bool WebAXObjectProxy::IsValid() {
+ return !accessibility_object().isDetached();
+}
+
+bool WebAXObjectProxy::IsReadOnly() {
+ return accessibility_object().isReadOnly();
+}
+
+std::string WebAXObjectProxy::Orientation() {
+ return GetOrientation(accessibility_object());
+}
+
+int WebAXObjectProxy::ClickPointX() {
+ return accessibility_object().clickPoint().x;
+}
+
+int WebAXObjectProxy::ClickPointY() {
+ return accessibility_object().clickPoint().y;
+}
+
+int32_t WebAXObjectProxy::RowCount() {
+ return static_cast<int32_t>(accessibility_object().rowCount());
+}
+
+int32_t WebAXObjectProxy::ColumnCount() {
+ return static_cast<int32_t>(accessibility_object().columnCount());
+}
+
+bool WebAXObjectProxy::IsClickable() {
+ return accessibility_object().isClickable();
+}
+
+std::string WebAXObjectProxy::AllAttributes() {
+ return GetAttributes(accessibility_object());
+}
+
+std::string WebAXObjectProxy::AttributesOfChildren() {
+ AttributesCollector collector;
+ unsigned size = accessibility_object().childCount();
+ for (unsigned i = 0; i < size; ++i)
+ collector.CollectAttributes(accessibility_object().childAt(i));
+ return collector.attributes();
+}
+
+int WebAXObjectProxy::LineForIndex(int index) {
+ blink::WebVector<int> line_breaks;
+ accessibility_object().lineBreaks(line_breaks);
+ int line = 0;
+ int vector_size = static_cast<int>(line_breaks.size());
+ while (line < vector_size && line_breaks[line] <= index)
+ line++;
+ return line;
+}
+
+std::string WebAXObjectProxy::BoundsForRange(int start, int end) {
+ if (accessibility_object().role() != blink::WebAXRoleStaticText)
+ return std::string();
+
+ int len = end - start;
+
+ // Get the bounds for each character and union them into one large rectangle.
+ // This is just for testing so it doesn't need to be efficient.
+ blink::WebRect bounds = BoundsForCharacter(accessibility_object(), start);
+ for (int i = 1; i < len; i++) {
+ blink::WebRect next = BoundsForCharacter(accessibility_object(), start + i);
+ int right = std::max(bounds.x + bounds.width, next.x + next.width);
+ int bottom = std::max(bounds.y + bounds.height, next.y + next.height);
+ bounds.x = std::min(bounds.x, next.x);
+ bounds.y = std::min(bounds.y, next.y);
+ bounds.width = right - bounds.x;
+ bounds.height = bottom - bounds.y;
+ }
+
+ return base::StringPrintf("{x: %d, y: %d, width: %d, height: %d}",
+ bounds.x, bounds.y, bounds.width, bounds.height);
+}
+
+v8::Handle<v8::Object> WebAXObjectProxy::ChildAtIndex(int index) {
+ return GetChildAtIndex(index);
+}
+
+v8::Handle<v8::Object> WebAXObjectProxy::ElementAtPoint(int x, int y) {
+ blink::WebPoint point(x, y);
+ blink::WebAXObject obj = accessibility_object().hitTest(point);
+ if (obj.isNull())
+ return v8::Handle<v8::Object>();
+
+ return factory_->GetOrCreate(obj);
+}
+
+v8::Handle<v8::Object> WebAXObjectProxy::TableHeader() {
+ blink::WebAXObject obj = accessibility_object().headerContainerObject();
+ if (obj.isNull())
+ return v8::Handle<v8::Object>();
+
+ return factory_->GetOrCreate(obj);
+}
+
+std::string WebAXObjectProxy::RowIndexRange() {
+ unsigned row_index = accessibility_object().cellRowIndex();
+ unsigned row_span = accessibility_object().cellRowSpan();
+ return base::StringPrintf("{%d, %d}", row_index, row_span);
+}
+
+std::string WebAXObjectProxy::ColumnIndexRange() {
+ unsigned column_index = accessibility_object().cellColumnIndex();
+ unsigned column_span = accessibility_object().cellColumnSpan();
+ return base::StringPrintf("{%d, %d}", column_index, column_span);
+}
+
+v8::Handle<v8::Object> WebAXObjectProxy::CellForColumnAndRow(
+ int column, int row) {
+ blink::WebAXObject obj =
+ accessibility_object().cellForColumnAndRow(column, row);
+ if (obj.isNull())
+ return v8::Handle<v8::Object>();
+
+ return factory_->GetOrCreate(obj);
+}
+
+v8::Handle<v8::Object> WebAXObjectProxy::TitleUIElement() {
+ blink::WebAXObject obj = accessibility_object().titleUIElement();
+ if (obj.isNull())
+ return v8::Handle<v8::Object>();
+
+ return factory_->GetOrCreate(obj);
+}
+
+void WebAXObjectProxy::SetSelectedTextRange(int selection_start,
+ int length) {
+ accessibility_object().setSelectedTextRange(selection_start,
+ selection_start + length);
+}
+
+bool WebAXObjectProxy::IsAttributeSettable(const std::string& attribute) {
+ bool settable = false;
+ if (attribute == "AXValue")
+ settable = accessibility_object().canSetValueAttribute();
+ return settable;
+}
+
+bool WebAXObjectProxy::IsPressActionSupported() {
+ return accessibility_object().canPress();
+}
+
+bool WebAXObjectProxy::IsIncrementActionSupported() {
+ return accessibility_object().canIncrement();
+}
+
+bool WebAXObjectProxy::IsDecrementActionSupported() {
+ return accessibility_object().canDecrement();
+}
+
+v8::Handle<v8::Object> WebAXObjectProxy::ParentElement() {
+ blink::WebAXObject parent_object = accessibility_object().parentObject();
+ while (parent_object.accessibilityIsIgnored())
+ parent_object = parent_object.parentObject();
+ return factory_->GetOrCreate(parent_object);
+}
+
+void WebAXObjectProxy::Increment() {
+ accessibility_object().increment();
+}
+
+void WebAXObjectProxy::Decrement() {
+ accessibility_object().decrement();
+}
+
+void WebAXObjectProxy::ShowMenu() {
+}
+
+void WebAXObjectProxy::Press() {
+ accessibility_object().press();
+}
+
+bool WebAXObjectProxy::IsEqual(v8::Handle<v8::Object> proxy) {
+ WebAXObjectProxy* unwrapped_proxy = NULL;
+ if (!gin::ConvertFromV8(blink::mainThreadIsolate(), proxy, &unwrapped_proxy))
+ return false;
+ return unwrapped_proxy->IsEqualToObject(accessibility_object_);
+}
+
+void WebAXObjectProxy::SetNotificationListener(
+ v8::Handle<v8::Function> callback) {
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+ notification_callback_.Reset(isolate, callback);
+}
+
+void WebAXObjectProxy::UnsetNotificationListener() {
+ notification_callback_.Reset();
+}
+
+void WebAXObjectProxy::TakeFocus() {
+ accessibility_object().setFocused(true);
+}
+
+void WebAXObjectProxy::ScrollToMakeVisible() {
+ accessibility_object().scrollToMakeVisible();
+}
+
+void WebAXObjectProxy::ScrollToMakeVisibleWithSubFocus(int x, int y,
+ int width, int height) {
+ accessibility_object().scrollToMakeVisibleWithSubFocus(
+ blink::WebRect(x, y, width, height));
+}
+
+void WebAXObjectProxy::ScrollToGlobalPoint(int x, int y) {
+ accessibility_object().scrollToGlobalPoint(blink::WebPoint(x, y));
+}
+
+int WebAXObjectProxy::WordStart(int character_index) {
+ if (accessibility_object().role() != blink::WebAXRoleStaticText)
+ return -1;
+
+ int word_start, word_end;
+ GetBoundariesForOneWord(accessibility_object(), character_index,
+ word_start, word_end);
+ return word_start;
+}
+
+int WebAXObjectProxy::WordEnd(int character_index) {
+ if (accessibility_object().role() != blink::WebAXRoleStaticText)
+ return -1;
+
+ int word_start, word_end;
+ GetBoundariesForOneWord(accessibility_object(), character_index,
+ word_start, word_end);
+ return word_end;
+}
+
+RootWebAXObjectProxy::RootWebAXObjectProxy(
+ const blink::WebAXObject &object, Factory *factory)
+ : WebAXObjectProxy(object, factory) {
+}
+
+v8::Handle<v8::Object> RootWebAXObjectProxy::GetChildAtIndex(unsigned index) {
+ if (index)
+ return v8::Handle<v8::Object>();
+
+ return factory()->GetOrCreate(accessibility_object());
+}
+
+bool RootWebAXObjectProxy::IsRoot() const {
+ return true;
+}
+
+WebAXObjectProxyList::WebAXObjectProxyList() {
+}
+
+WebAXObjectProxyList::~WebAXObjectProxyList() {
+ Clear();
+}
+
+void WebAXObjectProxyList::Clear() {
+ for (ElementList::iterator i = elements_.begin(); i != elements_.end(); ++i)
+ i->Dispose();
+ elements_.clear();
+}
+
+v8::Handle<v8::Object> WebAXObjectProxyList::GetOrCreate(
+ const blink::WebAXObject& object) {
+ if (object.isNull())
+ return v8::Handle<v8::Object>();
+
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+
+ size_t elementCount = elements_.size();
+ for (size_t i = 0; i < elementCount; i++) {
+ WebAXObjectProxy* unwrapped_object = NULL;
+ bool result = gin::ConvertFromV8(isolate, elements_[i].NewLocal(isolate),
+ &unwrapped_object);
+ DCHECK(result);
+ DCHECK(unwrapped_object);
+ if (unwrapped_object->IsEqualToObject(object))
+ return elements_[i].NewLocal(isolate);
+ }
+
+ v8::Handle<v8::Object> handle = gin::CreateHandle(
+ isolate, new WebAXObjectProxy(object, this)).ToV8()->ToObject();
+ UnsafePersistent<v8::Object> unsafe_handle(isolate, handle);
+ elements_.push_back(unsafe_handle);
+ return unsafe_handle.NewLocal(isolate);
+}
+
+v8::Handle<v8::Object> WebAXObjectProxyList::CreateRoot(
+ const blink::WebAXObject& object) {
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+ v8::Handle<v8::Object> handle = gin::CreateHandle(
+ isolate, new RootWebAXObjectProxy(object, this)).ToV8()->ToObject();
+ UnsafePersistent<v8::Object> unsafe_handle(isolate, handle);
+ elements_.push_back(unsafe_handle);
+ return unsafe_handle.NewLocal(isolate);
+}
+
+} // namespace content
diff --git a/content/shell/renderer/test_runner/web_ax_object_proxy.h b/content/shell/renderer/test_runner/web_ax_object_proxy.h
new file mode 100644
index 0000000..b10b5e8
--- /dev/null
+++ b/content/shell/renderer/test_runner/web_ax_object_proxy.h
@@ -0,0 +1,168 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_WEB_AX_OBJECT_PROXY_H_
+#define CONTENT_SHELL_RENDERER_TEST_RUNNER_WEB_AX_OBJECT_PROXY_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "content/shell/renderer/test_runner/unsafe_persistent.h"
+#include "gin/object_template_builder.h"
+#include "gin/wrappable.h"
+#include "third_party/WebKit/public/web/WebAXObject.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+class WebFrame;
+}
+
+namespace content {
+
+class WebAXObjectProxy : public gin::Wrappable<WebAXObjectProxy> {
+ public:
+ class Factory {
+ public:
+ virtual ~Factory() { }
+ virtual v8::Handle<v8::Object> GetOrCreate(
+ const blink::WebAXObject& object) = 0;
+ };
+
+ static gin::WrapperInfo kWrapperInfo;
+
+ WebAXObjectProxy(const blink::WebAXObject& object, Factory* factory);
+ virtual ~WebAXObjectProxy();
+
+ // gin::Wrappable:
+ virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) OVERRIDE;
+
+ virtual v8::Handle<v8::Object> GetChildAtIndex(unsigned index);
+ virtual bool IsRoot() const;
+ bool IsEqualToObject(const blink::WebAXObject& object);
+
+ void NotificationReceived(blink::WebFrame* frame,
+ const std::string& notification_name);
+
+ protected:
+ const blink::WebAXObject& accessibility_object() const {
+ return accessibility_object_;
+ }
+
+ Factory* factory() const { return factory_; }
+
+ private:
+ friend class WebAXObjectProxyBindings;
+
+ // Bound properties.
+ std::string Role();
+ std::string Title();
+ std::string Description();
+ std::string HelpText();
+ std::string StringValue();
+ int X();
+ int Y();
+ int Width();
+ int Height();
+ int IntValue();
+ int MinValue();
+ int MaxValue();
+ std::string ValueDescription();
+ int ChildrenCount();
+ int InsertionPointLineNumber();
+ std::string SelectedTextRange();
+ bool IsEnabled();
+ bool IsRequired();
+ bool IsFocused();
+ bool IsFocusable();
+ bool IsSelected();
+ bool IsSelectable();
+ bool IsMultiSelectable();
+ bool IsSelectedOptionActive();
+ bool IsExpanded();
+ bool IsChecked();
+ bool IsVisible();
+ bool IsOffScreen();
+ bool IsCollapsed();
+ bool HasPopup();
+ bool IsValid();
+ bool IsReadOnly();
+ std::string Orientation();
+ int ClickPointX();
+ int ClickPointY();
+ int32_t RowCount();
+ int32_t ColumnCount();
+ bool IsClickable();
+
+ // Bound methods.
+ std::string AllAttributes();
+ std::string AttributesOfChildren();
+ int LineForIndex(int index);
+ std::string BoundsForRange(int start, int end);
+ v8::Handle<v8::Object> ChildAtIndex(int index);
+ v8::Handle<v8::Object> ElementAtPoint(int x, int y);
+ v8::Handle<v8::Object> TableHeader();
+ std::string RowIndexRange();
+ std::string ColumnIndexRange();
+ v8::Handle<v8::Object> CellForColumnAndRow(int column, int row);
+ v8::Handle<v8::Object> TitleUIElement();
+ void SetSelectedTextRange(int selection_start, int length);
+ bool IsAttributeSettable(const std::string& attribute);
+ bool IsPressActionSupported();
+ bool IsIncrementActionSupported();
+ bool IsDecrementActionSupported();
+ v8::Handle<v8::Object> ParentElement();
+ void Increment();
+ void Decrement();
+ void ShowMenu();
+ void Press();
+ bool IsEqual(v8::Handle<v8::Object> proxy);
+ void SetNotificationListener(v8::Handle<v8::Function> callback);
+ void UnsetNotificationListener();
+ void TakeFocus();
+ void ScrollToMakeVisible();
+ void ScrollToMakeVisibleWithSubFocus(int x, int y, int width, int height);
+ void ScrollToGlobalPoint(int x, int y);
+ int WordStart(int character_index);
+ int WordEnd(int character_index);
+
+ blink::WebAXObject accessibility_object_;
+ Factory* factory_;
+
+ v8::Persistent<v8::Function> notification_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebAXObjectProxy);
+};
+
+class RootWebAXObjectProxy : public WebAXObjectProxy {
+ public:
+ RootWebAXObjectProxy(const blink::WebAXObject&, Factory*);
+
+ virtual v8::Handle<v8::Object> GetChildAtIndex(unsigned index) OVERRIDE;
+ virtual bool IsRoot() const OVERRIDE;
+};
+
+
+// Provides simple lifetime management of the WebAXObjectProxy instances: all
+// WebAXObjectProxys ever created from the controller are stored in a list and
+// cleared explicitly.
+class WebAXObjectProxyList : public WebAXObjectProxy::Factory {
+ public:
+ WebAXObjectProxyList();
+ virtual ~WebAXObjectProxyList();
+
+ void Clear();
+ virtual v8::Handle<v8::Object> GetOrCreate(
+ const blink::WebAXObject&) OVERRIDE;
+ v8::Handle<v8::Object> CreateRoot(const blink::WebAXObject&);
+
+ private:
+ typedef std::vector<UnsafePersistent<v8::Object> > ElementList;
+ ElementList elements_;
+};
+
+} // namespace content
+
+#endif // CONTENT_SHELL_RENDERER_TEST_RUNNER_WEB_AX_OBJECT_PROXY_H_