1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/shell/renderer/test_runner/accessibility_controller.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "gin/handle.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "gin/object_template_builder.h"
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "gin/wrappable.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/WebKit/public/web/WebElement.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/WebKit/public/web/WebKit.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "third_party/WebKit/public/web/WebView.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace content {
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class AccessibilityControllerBindings
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : public gin::Wrappable<AccessibilityControllerBindings> {
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static gin::WrapperInfo kWrapperInfo;
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static void Install(base::WeakPtr<AccessibilityController> controller,
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                      blink::WebFrame* frame);
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  explicit AccessibilityControllerBindings(
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::WeakPtr<AccessibilityController> controller);
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual ~AccessibilityControllerBindings();
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // gin::Wrappable:
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      v8::Isolate* isolate) OVERRIDE;
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void LogAccessibilityEvents();
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void SetNotificationListener(v8::Handle<v8::Function> callback);
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void UnsetNotificationListener();
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::Object> FocusedElement();
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::Object> RootElement();
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::Object> AccessibleElementById(const std::string& id);
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::WeakPtr<AccessibilityController> controller_;
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AccessibilityControllerBindings);
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)gin::WrapperInfo AccessibilityControllerBindings::kWrapperInfo = {
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    gin::kEmbedderNativeGin};
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityControllerBindings::Install(
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::WeakPtr<AccessibilityController> controller,
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    blink::WebFrame* frame) {
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Isolate* isolate = blink::mainThreadIsolate();
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::HandleScope handle_scope(isolate);
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (context.IsEmpty())
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Context::Scope context_scope(context);
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gin::Handle<AccessibilityControllerBindings> bindings =
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      gin::CreateHandle(isolate,
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                        new AccessibilityControllerBindings(controller));
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (bindings.IsEmpty())
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::Object> global = context->Global();
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  global->Set(gin::StringToV8(isolate, "accessibilityController"),
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              bindings.ToV8());
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AccessibilityControllerBindings::AccessibilityControllerBindings(
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::WeakPtr<AccessibilityController> controller)
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  : controller_(controller) {
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AccessibilityControllerBindings::~AccessibilityControllerBindings() {
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)gin::ObjectTemplateBuilder
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AccessibilityControllerBindings::GetObjectTemplateBuilder(
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    v8::Isolate* isolate) {
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return gin::Wrappable<AccessibilityControllerBindings>::
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GetObjectTemplateBuilder(isolate)
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .SetMethod("logAccessibilityEvents",
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 &AccessibilityControllerBindings::LogAccessibilityEvents)
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .SetMethod("setNotificationListener",
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 &AccessibilityControllerBindings::SetNotificationListener)
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .SetMethod("unsetNotificationListener",
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 &AccessibilityControllerBindings::UnsetNotificationListener)
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .SetProperty("focusedElement",
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   &AccessibilityControllerBindings::FocusedElement)
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .SetProperty("rootElement",
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   &AccessibilityControllerBindings::RootElement)
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .SetMethod("accessibleElementById",
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 &AccessibilityControllerBindings::AccessibleElementById)
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      // TODO(hajimehoshi): These are for backward compatibility. Remove them.
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .SetMethod("addNotificationListener",
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 &AccessibilityControllerBindings::SetNotificationListener)
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .SetMethod("removeNotificationListener",
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 &AccessibilityControllerBindings::UnsetNotificationListener);
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityControllerBindings::LogAccessibilityEvents() {
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (controller_)
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    controller_->LogAccessibilityEvents();
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityControllerBindings::SetNotificationListener(
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    v8::Handle<v8::Function> callback) {
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (controller_)
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    controller_->SetNotificationListener(callback);
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityControllerBindings::UnsetNotificationListener() {
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (controller_)
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    controller_->UnsetNotificationListener();
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)v8::Handle<v8::Object> AccessibilityControllerBindings::FocusedElement() {
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return controller_ ? controller_->FocusedElement() : v8::Handle<v8::Object>();
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)v8::Handle<v8::Object> AccessibilityControllerBindings::RootElement() {
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return controller_ ? controller_->RootElement() : v8::Handle<v8::Object>();
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)v8::Handle<v8::Object> AccessibilityControllerBindings::AccessibleElementById(
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& id) {
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return controller_ ? controller_->AccessibleElementById(id)
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     : v8::Handle<v8::Object>();
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AccessibilityController::AccessibilityController()
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : log_accessibility_events_(false),
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      weak_factory_(this) {
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AccessibilityController::~AccessibilityController() {}
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityController::Reset() {
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  root_element_ = blink::WebAXObject();
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  focused_element_ = blink::WebAXObject();
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  elements_.Clear();
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  notification_callback_.Reset();
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  log_accessibility_events_ = false;
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityController::Install(blink::WebFrame* frame) {
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  blink::WebAXObject::enableAccessibility();
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  blink::WebAXObject::enableInlineTextBoxAccessibility();
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AccessibilityControllerBindings::Install(weak_factory_.GetWeakPtr(), frame);
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityController::SetFocusedElement(
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const blink::WebAXObject& focused_element) {
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  focused_element_ = focused_element;
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool AccessibilityController::ShouldLogAccessibilityEvents() {
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return log_accessibility_events_;
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityController::NotificationReceived(
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const blink::WebAXObject& target, const std::string& notification_name) {
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Isolate* isolate = blink::mainThreadIsolate();
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::HandleScope handle_scope(isolate);
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  blink::WebFrame* frame = web_view_->mainFrame();
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!frame)
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (context.IsEmpty())
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Context::Scope context_scope(context);
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Call notification listeners on the element.
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::Object> element_handle = elements_.GetOrCreate(target);
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (element_handle.IsEmpty())
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  WebAXObjectProxy* element;
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool result = gin::ConvertFromV8(isolate, element_handle, &element);
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(result);
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  element->NotificationReceived(frame, notification_name);
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (notification_callback_.IsEmpty())
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Call global notification listeners.
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Handle<v8::Value> argv[] = {
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    element_handle,
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    v8::String::NewFromUtf8(isolate, notification_name.data(),
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            v8::String::kNormalString,
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            notification_name.size()),
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  };
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  frame->callFunctionEvenIfScriptDisabled(
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      v8::Local<v8::Function>::New(isolate, notification_callback_),
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      context->Global(),
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      arraysize(argv),
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      argv);
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
205010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void AccessibilityController::SetDelegate(WebTestDelegate* delegate) {
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  delegate_ = delegate;
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityController::SetWebView(blink::WebView* web_view) {
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  web_view_ = web_view;
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityController::LogAccessibilityEvents() {
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  log_accessibility_events_ = true;
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityController::SetNotificationListener(
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    v8::Handle<v8::Function> callback) {
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Isolate* isolate = blink::mainThreadIsolate();
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  notification_callback_.Reset(isolate, callback);
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void AccessibilityController::UnsetNotificationListener() {
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  notification_callback_.Reset();
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)v8::Handle<v8::Object> AccessibilityController::FocusedElement() {
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (focused_element_.isNull())
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    focused_element_ = web_view_->accessibilityObject();
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return elements_.GetOrCreate(focused_element_);
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)v8::Handle<v8::Object> AccessibilityController::RootElement() {
234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (root_element_.isNull())
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    root_element_ = web_view_->accessibilityObject();
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return elements_.CreateRoot(root_element_);
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)v8::Handle<v8::Object>
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AccessibilityController::AccessibleElementById(const std::string& id) {
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (root_element_.isNull())
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    root_element_ = web_view_->accessibilityObject();
243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!root_element_.updateBackingStoreAndCheckValidity())
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return v8::Handle<v8::Object>();
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return FindAccessibleElementByIdRecursive(
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      root_element_, blink::WebString::fromUTF8(id.c_str()));
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)v8::Handle<v8::Object>
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)AccessibilityController::FindAccessibleElementByIdRecursive(
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const blink::WebAXObject& obj, const blink::WebString& id) {
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (obj.isNull() || obj.isDetached())
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return v8::Handle<v8::Object>();
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  blink::WebNode node = obj.node();
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!node.isNull() && node.isElementNode()) {
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    blink::WebElement element = node.to<blink::WebElement>();
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    element.getAttribute("id");
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (element.getAttribute("id") == id)
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return elements_.GetOrCreate(obj);
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  unsigned childCount = obj.childCount();
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (unsigned i = 0; i < childCount; i++) {
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    v8::Handle<v8::Object> result =
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        FindAccessibleElementByIdRecursive(obj.childAt(i), id);
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (*result)
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return result;
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return v8::Handle<v8::Object>();
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace content
277