1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_COMPLETE_H_
6#define CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_COMPLETE_H_
7
8#include <set>
9#include <vector>
10
11#include "base/containers/hash_tables.h"
12#include "base/memory/weak_ptr.h"
13#include "content/common/accessibility_node_data.h"
14#include "content/public/renderer/render_view_observer.h"
15#include "content/renderer/accessibility/renderer_accessibility.h"
16#include "third_party/WebKit/public/web/WebAXEnums.h"
17#include "third_party/WebKit/public/web/WebAXObject.h"
18
19namespace blink {
20class WebDocument;
21class WebNode;
22};
23
24namespace content {
25class RenderViewImpl;
26
27// This is the subclass of RendererAccessibility that implements
28// complete accessibility support for assistive technology (as opposed to
29// partial support - see RendererAccessibilityFocusOnly).
30//
31// This version turns on WebKit's accessibility code and sends
32// a serialized representation of that tree whenever it changes. It also
33// handles requests from the browser to perform accessibility actions on
34// nodes in the tree (e.g., change focus, or click on a button).
35class CONTENT_EXPORT RendererAccessibilityComplete
36    : public RendererAccessibility {
37 public:
38  explicit RendererAccessibilityComplete(RenderViewImpl* render_view);
39  virtual ~RendererAccessibilityComplete();
40
41  // RenderView::Observer implementation.
42  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
43  virtual void FocusedNodeChanged(const blink::WebNode& node) OVERRIDE;
44  virtual void DidFinishLoad(blink::WebFrame* frame) OVERRIDE;
45
46  // RendererAccessibility.
47  virtual void HandleWebAccessibilityEvent(
48      const blink::WebAXObject& obj, blink::WebAXEvent event) OVERRIDE;
49
50  // In order to keep track of what nodes the browser knows about, we keep a
51  // representation of the browser tree - just IDs and parent/child
52  // relationships.
53  struct CONTENT_EXPORT BrowserTreeNode {
54    BrowserTreeNode();
55    virtual ~BrowserTreeNode();
56    int32 id;
57    gfx::Rect location;
58    BrowserTreeNode* parent;
59    std::vector<BrowserTreeNode*> children;
60  };
61
62  virtual BrowserTreeNode* CreateBrowserTreeNode();
63
64 protected:
65  // Send queued events from the renderer to the browser.
66  void SendPendingAccessibilityEvents();
67
68  // Check the entire accessibility tree to see if any nodes have
69  // changed location, by comparing their locations to the cached
70  // versions. If any have moved, append a event to |events|
71  // that updates the coordinates of these objects.
72  void AppendLocationChangeEvents(
73      std::vector<AccessibilityHostMsg_EventParams>* events);
74
75 private:
76  // Serialize the given accessibility object |obj| and append it to
77  // |dst|, and then recursively also serialize any *new* children of
78  // |obj|, based on what object ids we know the browser already has.
79  // The set of ids serialized is added to |ids_serialized|, and any
80  // ids previously in that set are not serialized again.
81  void SerializeChangedNodes(const blink::WebAXObject& obj,
82                             std::vector<AccessibilityNodeData>* dst,
83                             std::set<int>* ids_serialized);
84
85  // Clear the given node and recursively delete all of its descendants
86  // from the browser tree. (Does not delete |browser_node|).
87  void ClearBrowserTreeNode(BrowserTreeNode* browser_node);
88
89  // Handlers for messages from the browser to the renderer.
90  void OnDoDefaultAction(int acc_obj_id);
91  void OnEventsAck();
92  void OnChangeScrollPosition(int acc_obj_id, int scroll_x, int scroll_y);
93  void OnScrollToMakeVisible(int acc_obj_id, gfx::Rect subfocus);
94  void OnScrollToPoint(int acc_obj_id, gfx::Point point);
95  void OnSetFocus(int acc_obj_id);
96  void OnSetTextSelection(int acc_obj_id, int start_offset, int end_offset);
97  void OnFatalError();
98
99  // Checks if a WebKit accessibility object is an editable text node.
100  bool IsEditableText(const blink::WebAXObject& node);
101
102  // Recursively explore the tree of WebKit accessibility objects rooted
103  // at |src|, and for each editable text node encountered, add a
104  // corresponding WebAccessibility node as a child of |dst|.
105  void RecursiveAddEditableTextNodesToTree(
106      const blink::WebAXObject& src,
107      AccessibilityNodeData* dst);
108
109  // Build a tree of serializable AccessibilityNodeData nodes to send to the
110  // browser process, given a WebAXObject node from WebKit.
111  // Modifies |dst| in-place, it's assumed to be empty.
112  void BuildAccessibilityTree(const blink::WebAXObject& src,
113                              bool include_children,
114                              AccessibilityNodeData* dst);
115
116  // So we can queue up tasks to be executed later.
117  base::WeakPtrFactory<RendererAccessibilityComplete> weak_factory_;
118
119  // Events from WebKit are collected until they are ready to be
120  // sent to the browser.
121  std::vector<AccessibilityHostMsg_EventParams> pending_events_;
122
123  // Our representation of the browser tree.
124  BrowserTreeNode* browser_root_;
125
126  // A map from IDs to nodes in the browser tree.
127  base::hash_map<int32, BrowserTreeNode*> browser_id_map_;
128
129  // The most recently observed scroll offset of the root document element.
130  // TODO(dmazzoni): remove once https://bugs.webkit.org/show_bug.cgi?id=73460
131  // is fixed.
132  gfx::Size last_scroll_offset_;
133
134  // The current accessibility mode.
135  AccessibilityMode mode_;
136
137  // Set if we are waiting for an accessibility event ack.
138  bool ack_pending_;
139
140  // True if verbose logging of accessibility events is on.
141  bool logging_;
142
143  DISALLOW_COPY_AND_ASSIGN(RendererAccessibilityComplete);
144};
145
146#endif  // CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_COMPLETE_H_
147
148}  // namespace content
149