Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Unified Diff: webkit/glue/webaccessibility.cc

Issue 348063: Introduce WebAccessibilityControllerImpl.... (Closed) Base URL: svn://chrome-svn.corp.google.com/chrome/trunk/src/
Patch Set: Licked clean. Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webkit/glue/webaccessibility.cc
===================================================================
--- webkit/glue/webaccessibility.cc (revision 30762)
+++ webkit/glue/webaccessibility.cc (working copy)
@@ -2,288 +2,339 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "config.h"
+#include "webkit/glue/webaccessibility.h"
-#include "AXObjectCache.h"
-#include "Document.h"
-#include "Frame.h"
-#include "RefPtr.h"
-#undef LOG
-
-#include "webkit/glue/webaccessibilitymanager_impl.h"
-
+#include "webkit/api/public/WebAccessibilityCache.h"
#include "webkit/api/public/WebAccessibilityObject.h"
-#include "webkit/api/src/WebFrameImpl.h"
-#include "webkit/api/src/WebViewImpl.h"
-#include "webkit/glue/glue_accessibility_object.h"
-#include "webkit/glue/glue_util.h"
+#include "webkit/api/public/WebAccessibilityRole.h"
+#include "webkit/api/public/WebPoint.h"
+#include "webkit/api/public/WebRect.h"
+#include "webkit/api/public/WebString.h"
+using WebKit::WebAccessibilityCache;
+using WebKit::WebAccessibilityRole;
using WebKit::WebAccessibilityObject;
-using WebKit::WebFrameImpl;
-using WebKit::WebView;
+using WebKit::WebPoint;
+using WebKit::WebRect;
+using WebKit::WebString;
namespace webkit_glue {
-// struct WebAccessibilityManagerImpl::GlueAccessibilityObjectRoot
-struct WebAccessibilityManagerImpl::GlueAccessibilityObjectRoot {
- GlueAccessibilityObjectRoot() {}
+// Provides a conversion between the WebKit::WebAccessibilityRole and a role
+// supported on the Browser side. Listed alphabetically by the
+// WebAccessibilityRole (except for default role).
+WebAccessibility::Role ConvertRole(WebKit::WebAccessibilityRole role) {
+ switch (role) {
+ case WebKit::WebAccessibilityRoleLandmarkApplication:
+ return WebAccessibility::ROLE_APPLICATION;
+ case WebKit::WebAccessibilityRoleCell:
+ return WebAccessibility::ROLE_CELL;
+ case WebKit::WebAccessibilityRoleCheckBox:
+ return WebAccessibility::ROLE_CHECKBUTTON;
+ case WebKit::WebAccessibilityRoleColumn:
+ return WebAccessibility::ROLE_COLUMN;
+ case WebKit::WebAccessibilityRoleColumnHeader:
+ return WebAccessibility::ROLE_COLUMNHEADER;
+ case WebKit::WebAccessibilityRoleDocumentArticle:
+ case WebKit::WebAccessibilityRoleWebArea:
+ return WebAccessibility::ROLE_DOCUMENT;
+ case WebKit::WebAccessibilityRoleImageMap:
+ case WebKit::WebAccessibilityRoleImage:
+ return WebAccessibility::ROLE_GRAPHIC;
+ case WebKit::WebAccessibilityRoleDocumentRegion:
+ case WebKit::WebAccessibilityRoleRadioGroup:
+ case WebKit::WebAccessibilityRoleGroup:
+ return WebAccessibility::ROLE_GROUPING;
+ case WebKit::WebAccessibilityRoleLink:
+ case WebKit::WebAccessibilityRoleWebCoreLink:
+ return WebAccessibility::ROLE_LINK;
+ case WebKit::WebAccessibilityRoleList:
+ return WebAccessibility::ROLE_LIST;
+ case WebKit::WebAccessibilityRoleListBox:
+ return WebAccessibility::ROLE_LISTBOX;
+ case WebKit::WebAccessibilityRoleListBoxOption:
+ return WebAccessibility::ROLE_LISTITEM;
+ case WebKit::WebAccessibilityRoleMenuBar:
+ return WebAccessibility::ROLE_MENUBAR;
+ case WebKit::WebAccessibilityRoleMenuButton:
+ case WebKit::WebAccessibilityRoleMenuItem:
+ return WebAccessibility::ROLE_MENUITEM;
+ case WebKit::WebAccessibilityRoleMenu:
+ return WebAccessibility::ROLE_MENUPOPUP;
+ case WebKit::WebAccessibilityRoleOutline:
+ return WebAccessibility::ROLE_OUTLINE;
+ case WebKit::WebAccessibilityRoleTabGroup:
+ return WebAccessibility::ROLE_PAGETABLIST;
+ case WebKit::WebAccessibilityRoleProgressIndicator:
+ return WebAccessibility::ROLE_PROGRESSBAR;
+ case WebKit::WebAccessibilityRoleButton:
+ return WebAccessibility::ROLE_PUSHBUTTON;
+ case WebKit::WebAccessibilityRoleRadioButton:
+ return WebAccessibility::ROLE_RADIOBUTTON;
+ case WebKit::WebAccessibilityRoleRow:
+ return WebAccessibility::ROLE_ROW;
+ case WebKit::WebAccessibilityRoleRowHeader:
+ return WebAccessibility::ROLE_ROWHEADER;
+ case WebKit::WebAccessibilityRoleSplitter:
+ return WebAccessibility::ROLE_SEPARATOR;
+ case WebKit::WebAccessibilityRoleSlider:
+ return WebAccessibility::ROLE_SLIDER;
+ case WebKit::WebAccessibilityRoleStaticText:
+ return WebAccessibility::ROLE_STATICTEXT;
+ case WebKit::WebAccessibilityRoleApplicationStatus:
+ return WebAccessibility::ROLE_STATUSBAR;
+ case WebKit::WebAccessibilityRoleTable:
+ return WebAccessibility::ROLE_TABLE;
+ case WebKit::WebAccessibilityRoleListMarker:
+ case WebKit::WebAccessibilityRoleTextField:
+ case WebKit::WebAccessibilityRoleTextArea:
+ return WebAccessibility::ROLE_TEXT;
+ case WebKit::WebAccessibilityRoleToolbar:
+ return WebAccessibility::ROLE_TOOLBAR;
+ case WebKit::WebAccessibilityRoleUserInterfaceTooltip:
+ return WebAccessibility::ROLE_TOOLTIP;
+ case WebKit::WebAccessibilityRoleDocument:
+ case WebKit::WebAccessibilityRoleUnknown:
+ default:
+ // This is the default role.
+ return WebAccessibility::ROLE_CLIENT;
+ }
+}
- // Root of the WebKit AccessibilityObject tree.
- RefPtr<GlueAccessibilityObject> acc_obj_root_;
-};
+long ConvertState(const WebAccessibilityObject& o) {
+ long state = 0;
+ if (o.isChecked())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_CHECKED);
-/*static*/
-WebAccessibilityManager* WebAccessibilityManager::Create() {
- return new WebAccessibilityManagerImpl();
-}
+ if (o.canSetFocusAttribute())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_FOCUSABLE);
-// class WebAccessibilityManagerImpl
-WebAccessibilityManagerImpl::WebAccessibilityManagerImpl()
- : root_(new GlueAccessibilityObjectRoot),
- acc_obj_id_(1000) {
-}
+ if (o.isFocused())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_FOCUSED);
-WebAccessibilityManagerImpl::~WebAccessibilityManagerImpl() {
- int_to_glue_acc_obj_map_.clear();
- acc_obj_to_int_map_.clear();
+ if (o.isHovered())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_HOTTRACKED);
+
+ if (o.isIndeterminate())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_INDETERMINATE);
+
+ if (o.isAnchor())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_LINKED);
+
+ if (o.isMultiSelect())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_MULTISELECTABLE);
+
+ if (o.isOffScreen())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_OFFSCREEN);
+
+ if (o.isPressed())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_PRESSED);
+
+ if (o.isPasswordField())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_PROTECTED);
+
+ if (o.isReadOnly())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_READONLY);
+
+ if (o.isVisited())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_TRAVERSED);
+
+ if (!o.isEnabled())
+ state |= static_cast<long>(1 << WebAccessibility::STATE_UNAVAILABLE);
+
+ return state;
}
-bool WebAccessibilityManagerImpl::GetAccObjInfo(WebView* view,
+
+bool WebAccessibility::GetAccObjInfo(WebAccessibilityCache* cache,
const WebAccessibility::InParams& in_params,
WebAccessibility::OutParams* out_params) {
- if (!root_->acc_obj_root_ && !InitAccObjRoot(view)) {
- // Failure in retrieving or initializing the root.
- return false;
- }
- // Function input parameters.
- int object_id = in_params.object_id;
- int child_id = in_params.child_id;
+ // Find object requested by |object_id|.
+ WebAccessibilityObject active_acc_obj;
// Since ids assigned by Chrome starts at 1000, whereas platform-specific ids
// used to reference a child will be in a wholly different range, we know
// that any id that high should be treated as a non-direct descendant.
- if (in_params.child_id >= 1000) {
+ bool local_child = false;
+ if (cache->isValidId(in_params.child_id)) {
// Object is not a direct child, re-map the input parameters accordingly.
// The object to be retrieved is referred to by the |in_params.child_id|, as
- // a result of e.g. a focus event. The local |child_id| is set to 0, to
- // indicate that any function call should refer to the object itself.
- object_id = in_params.child_id;
- child_id = 0;
+ // a result of e.g. a focus event.
+ active_acc_obj = cache->getObjectById(in_params.child_id);
+ } else {
+ local_child = true;
+
+ active_acc_obj = cache->getObjectById(in_params.object_id);
+ if (active_acc_obj.isNull())
+ return false;
+
+ // child_id == 0 means self. Otherwise, it's a local child - 1.
+ if (in_params.child_id > 0) {
+ unsigned index = in_params.child_id - 1;
+ if (index >= active_acc_obj.childCount())
+ return false;
+
+ active_acc_obj = active_acc_obj.childAt(index);
+ }
}
- // Find GlueAccessibilityObject requested by |object_id|.
- IntToGlueAccObjMap::iterator it =
- int_to_glue_acc_obj_map_.find(object_id);
- if (it == int_to_glue_acc_obj_map_.end() || !it->second) {
- // Map did not contain a valid instance of the data requested.
+ if (active_acc_obj.isNull())
return false;
- }
- RefPtr<GlueAccessibilityObject> active_acc_obj = it->second;
// Temp paramters for holding output information.
- RefPtr<GlueAccessibilityObject> out_acc_obj = NULL;
- WebCore::String out_string;
+ WebAccessibilityObject out_acc_obj;
+ string16 out_string;
switch (in_params.function_id) {
- case WebAccessibility::FUNCTION_DODEFAULTACTION :
- if (!active_acc_obj->DoDefaultAction(child_id))
+ case WebAccessibility::FUNCTION_DODEFAULTACTION: {
+ if (!active_acc_obj.performDefaultAction())
return false;
break;
- case WebAccessibility::FUNCTION_HITTEST :
- out_acc_obj = active_acc_obj->HitTest(in_params.input_long1,
- in_params.input_long2);
- if (!out_acc_obj.get())
+ }
+ case WebAccessibility::FUNCTION_HITTEST: {
+ WebPoint point(in_params.input_long1, in_params.input_long2);
+ out_acc_obj = active_acc_obj.hitTest(point);
+ if (out_acc_obj.isNull())
return false;
break;
- case WebAccessibility::FUNCTION_LOCATION :
- if (!active_acc_obj->Location(&out_params->output_long1,
- &out_params->output_long2,
- &out_params->output_long3,
- &out_params->output_long4,
- child_id)) {
- return false;
- }
+ }
+ case WebAccessibility::FUNCTION_LOCATION: {
+ WebRect rect = active_acc_obj.boundingBoxRect();
+ out_params->output_long1 = rect.x;
+ out_params->output_long2 = rect.y;
+ out_params->output_long3 = rect.width;
+ out_params->output_long4 = rect.height;
break;
- case WebAccessibility::FUNCTION_NAVIGATE :
- out_acc_obj = active_acc_obj->Navigate(
- static_cast<WebAccessibility::Direction>(in_params.input_long1),
- child_id);
- if (!out_acc_obj.get())
- return false;
- break;
- case WebAccessibility::FUNCTION_GETCHILD :
- if (child_id == 0) {
- // If child requested is self, stay with the same accessibility object.
- out_params->object_id = in_params.object_id;
- out_acc_obj = active_acc_obj.get();
- } else {
- out_acc_obj = active_acc_obj->GetChild(child_id);
+ }
+ case WebAccessibility::FUNCTION_NAVIGATE: {
+ WebAccessibility::Direction dir =
+ static_cast<WebAccessibility::Direction>(in_params.input_long1);
+ switch (dir) {
+ case WebAccessibility::DIRECTION_DOWN:
+ case WebAccessibility::DIRECTION_UP:
+ case WebAccessibility::DIRECTION_LEFT:
+ case WebAccessibility::DIRECTION_RIGHT:
+ // These directions are not implemented, matching Mozilla and IE.
+ return false;
+ case WebAccessibility::DIRECTION_LASTCHILD:
+ case WebAccessibility::DIRECTION_FIRSTCHILD:
+ // MSDN states that navigating to first/last child can only be from
+ // self.
+ if (!local_child)
+ return false;
+
+ if (dir == WebAccessibility::DIRECTION_FIRSTCHILD) {
+ out_acc_obj = active_acc_obj.firstChild();
+ } else {
+ out_acc_obj = active_acc_obj.lastChild();
+ }
+ break;
+ case WebAccessibility::DIRECTION_NEXT:
+ case WebAccessibility::DIRECTION_PREVIOUS: {
+ if (dir == WebAccessibility::DIRECTION_NEXT) {
+ out_acc_obj = active_acc_obj.nextSibling();
+ } else {
+ out_acc_obj = active_acc_obj.previousSibling();
+ }
+ break;
+ }
+ default:
+ return false;
}
-
- if (!out_acc_obj.get())
+ if (out_acc_obj.isNull())
return false;
break;
- case WebAccessibility::FUNCTION_CHILDCOUNT :
- if (!active_acc_obj->ChildCount(&out_params->output_long1))
- return false;
+ }
+ case WebAccessibility::FUNCTION_GETCHILD: {
+ out_params->object_id = in_params.object_id;
+ out_acc_obj = active_acc_obj;
break;
- case WebAccessibility::FUNCTION_DEFAULTACTION :
- if (!active_acc_obj->DefaultAction(child_id, &out_string))
- return false;
+ }
+ case WebAccessibility::FUNCTION_CHILDCOUNT: {
+ out_params->output_long1 = active_acc_obj.childCount();
break;
- case WebAccessibility::FUNCTION_DESCRIPTION :
- if (!active_acc_obj->Description(child_id, &out_string))
+ }
+ case WebAccessibility::FUNCTION_DEFAULTACTION: {
+ out_string = active_acc_obj.actionVerb();
+ if (out_string.empty())
return false;
break;
- case WebAccessibility::FUNCTION_GETFOCUSEDCHILD :
- out_acc_obj = active_acc_obj->GetFocusedChild();
- if (!out_acc_obj.get())
+ }
+ case WebAccessibility::FUNCTION_DESCRIPTION: {
+ out_string = active_acc_obj.accessibilityDescription();
+ if (out_string.empty())
return false;
+ // From the Mozilla MSAA implementation:
+ // "Signal to screen readers that this description is speakable and is not
+ // a formatted positional information description. Don't localize the
+ // 'Description: ' part of this string, it will be parsed out by assistive
+ // technologies."
+ out_string = L"Description: " + out_string;
break;
- case WebAccessibility::FUNCTION_HELPTEXT :
- if (!active_acc_obj->HelpText(child_id, &out_string))
+ }
+ case WebAccessibility::FUNCTION_GETFOCUSEDCHILD: {
+ out_acc_obj = active_acc_obj.focusedChild();
+ if (out_acc_obj.isNull())
return false;
break;
- case WebAccessibility::FUNCTION_KEYBOARDSHORTCUT :
- if (!active_acc_obj->KeyboardShortcut(child_id, &out_string))
+ }
+ case WebAccessibility::FUNCTION_HELPTEXT: {
+ out_string = active_acc_obj.helpText();
+ if (out_string.empty())
return false;
break;
- case WebAccessibility::FUNCTION_NAME :
- if (!active_acc_obj->Name(child_id, &out_string))
+ }
+ case WebAccessibility::FUNCTION_KEYBOARDSHORTCUT: {
+ out_string = active_acc_obj.keyboardShortcut();
+ if (out_string.empty())
return false;
break;
- case WebAccessibility::FUNCTION_GETPARENT :
- out_acc_obj = active_acc_obj->GetParent();
- if (!out_acc_obj.get())
+ }
+ case WebAccessibility::FUNCTION_NAME: {
+ out_string = active_acc_obj.title();
+ if (out_string.empty())
return false;
break;
- case WebAccessibility::FUNCTION_ROLE :
- if (!active_acc_obj->Role(child_id, &out_params->output_long1))
+ }
+ case WebAccessibility::FUNCTION_GETPARENT: {
+ out_acc_obj = active_acc_obj.parentObject();
+ if (out_acc_obj.isNull())
return false;
break;
- case WebAccessibility::FUNCTION_STATE :
- if (!active_acc_obj->State(child_id, &out_params->output_long1))
- return false;
+ }
+ case WebAccessibility::FUNCTION_ROLE: {
+ out_params->output_long1 = ConvertRole(active_acc_obj.roleValue());
break;
- case WebAccessibility::FUNCTION_VALUE :
- if (!active_acc_obj->Value(child_id, &out_string))
+ }
+ case WebAccessibility::FUNCTION_STATE: {
+ out_params->output_long1 = ConvertState(active_acc_obj);
+ break;
+ }
+ case WebAccessibility::FUNCTION_VALUE: {
+ out_string = active_acc_obj.stringValue();
+ if (out_string.empty())
return false;
break;
+ }
default:
// Non-supported function id.
return false;
}
// Output and hashmap assignments, as appropriate.
- if (!out_string.isEmpty())
- out_params->output_string = StringToString16(out_string);
+ if (!out_string.empty())
+ out_params->output_string = out_string;
- if (out_acc_obj) {
- AccObjToIntMap::iterator it =
- acc_obj_to_int_map_.find(out_acc_obj->accessibilityObject());
-
- if (it != acc_obj_to_int_map_.end()) {
- // Data already present in map, return previously assigned id.
- out_params->object_id = it->second;
- out_params->output_long1 = -1;
- } else {
- // Insert new GlueAccessibilityObject in hashmaps.
- int_to_glue_acc_obj_map_[acc_obj_id_] = out_acc_obj.get();
- acc_obj_to_int_map_[out_acc_obj->accessibilityObject()] = acc_obj_id_;
- out_params->object_id = acc_obj_id_++;
- out_params->output_long1 = -1;
- }
- }
- // TODO(klink): Handle simple objects returned.
- return true;
-}
-
-bool WebAccessibilityManagerImpl::InitAccObjRoot(WebView* view) {
- // Enable accessibility and retrieve Document.
- WebCore::AXObjectCache::enableAccessibility();
- WebFrameImpl* main_frame_impl =
- static_cast<WebFrameImpl*>(view->mainFrame());
- if (!main_frame_impl || !main_frame_impl->frame())
- return false;
-
- WebCore::Document* doc = main_frame_impl->frame()->document();
-
- if (!doc || !doc->renderer())
- return false;
-
- if (!root_->acc_obj_root_) {
- // Either we've never had a wrapper for this frame's top-level Document,
- // the Document renderer was destroyed and its wrapper was detached, or
- // the previous Document is in the page cache, and the current document
- // needs to be wrapped.
- root_->acc_obj_root_ = GlueAccessibilityObject::CreateInstance(doc->
- axObjectCache()->getOrCreate(doc->renderer()));
- }
- // Insert root in hashmaps.
- int_to_glue_acc_obj_map_[acc_obj_id_] = root_->acc_obj_root_.get();
- acc_obj_to_int_map_[root_->acc_obj_root_->accessibilityObject()] =
- acc_obj_id_++;
-
- return true;
-}
-
-bool WebAccessibilityManagerImpl::ClearAccObjMap(int acc_obj_id,
- bool clear_all) {
- if (clear_all) {
- // Clear maps and invalidate root.
- int_to_glue_acc_obj_map_.clear();
- acc_obj_to_int_map_.clear();
- root_->acc_obj_root_ = 0;
+ if (out_acc_obj.isNull())
return true;
- }
- IntToGlueAccObjMap::iterator it = int_to_glue_acc_obj_map_.find(acc_obj_id);
+ int id = cache->addOrGetId(out_acc_obj);
+ out_params->object_id = id;
+ out_params->output_long1 = -1;
- if (it == int_to_glue_acc_obj_map_.end()) {
- // Element not found.
- return false;
- }
-
- if (it->second) {
- // Erase element from reverse hashmap.
- AccObjToIntMap::iterator it2 =
- acc_obj_to_int_map_.find(it->second->accessibilityObject());
-
- if (it2 != acc_obj_to_int_map_.end())
- acc_obj_to_int_map_.erase(it2);
- }
- int_to_glue_acc_obj_map_.erase(it);
-
- if (acc_obj_id == 1000) {
- // Invalidate root.
- root_->acc_obj_root_ = 0;
- }
+ // TODO(klink): Handle simple objects returned.
return true;
}
-int WebAccessibilityManagerImpl::FocusAccObj(
- const WebAccessibilityObject& object) {
- if (object.isNull()) {
- // Return with failure.
- return -1;
- }
-
- RefPtr<WebCore::AccessibilityObject> acc_obj =
- WebAccessibilityObjectToAccessibilityObject(object);
-
- AccObjToIntMap::iterator it = acc_obj_to_int_map_.find(acc_obj.get());
-
- if (it != acc_obj_to_int_map_.end())
- return it->second;
-
- // Insert new accessibility object in hashmaps and return its newly
- // assigned accessibility object id.
- int_to_glue_acc_obj_map_[acc_obj_id_] =
- GlueAccessibilityObject::CreateInstance(acc_obj.get());
- acc_obj_to_int_map_[acc_obj.get()] = acc_obj_id_;
-
- return acc_obj_id_++;
-}
-
} // namespace webkit_glue

Powered by Google App Engine
This is Rietveld 408576698