Commit 4d527503 authored by Jose Dapena Paz's avatar Jose Dapena Paz Committed by Commit Bot

Export AtkHyperlinkImpl and AtkHyperlink for link role.

On ATK accessibility model, embedded hyperlinks accessibility nodes should
be exposed as ATK objects implementing AtkHyperlinkImpl interface. This
interface should provide the get_hyperlink method that returns an
AtkHyperlink object with the hyperlink URL and status.

This implementation is equivalent to the one found in Firefox and in
WebKitGTK: it will return always one anchor, that will point to the
link embedding object.

It does not implement the get_start_index and get_end_index yet.

Bug: 783447
Change-Id: I72163b1cce18c7cc3c8f732d5eaa45987b86a420
Reviewed-on: https://chromium-review.googlesource.com/762316Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Commit-Queue: Avi Drissman <avi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#516318}
parent 574061c0
...@@ -1962,6 +1962,8 @@ source_set("browser") { ...@@ -1962,6 +1962,8 @@ source_set("browser") {
if (use_atk) { if (use_atk) {
sources += [ sources += [
"accessibility/accessibility_tree_formatter_auralinux.cc", "accessibility/accessibility_tree_formatter_auralinux.cc",
"accessibility/browser_accessibility_atk_hyperlink.cc",
"accessibility/browser_accessibility_atk_hyperlink.h",
"accessibility/browser_accessibility_auralinux.cc", "accessibility/browser_accessibility_auralinux.cc",
"accessibility/browser_accessibility_auralinux.h", "accessibility/browser_accessibility_auralinux.h",
"accessibility/browser_accessibility_manager_auralinux.cc", "accessibility/browser_accessibility_manager_auralinux.cc",
......
// Copyright (c) 2017 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/browser/accessibility/browser_accessibility_atk_hyperlink.h"
#include "content/browser/accessibility/browser_accessibility_auralinux.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
namespace content {
static gpointer browser_accessibility_atk_hyperlink_parent_class = nullptr;
static BrowserAccessibilityAuraLinux* ToBrowserAccessibilityAuraLinux(
BrowserAccessibilityAtkHyperlink* atk_hyperlink) {
if (!atk_hyperlink)
return nullptr;
return atk_hyperlink->m_object;
}
static void browser_accessibility_atk_hyperlink_finalize(
GObject* atk_hyperlink) {
G_OBJECT_CLASS(browser_accessibility_atk_hyperlink_parent_class)
->finalize(atk_hyperlink);
}
static gchar* browser_accessibility_atk_hyperlink_get_uri(
AtkHyperlink* atk_hyperlink,
gint index) {
BrowserAccessibilityAuraLinux* obj = ToBrowserAccessibilityAuraLinux(
BROWSER_ACCESSIBILITY_ATK_HYPERLINK(atk_hyperlink));
if (!obj)
return nullptr;
if (index != 0)
return nullptr;
return g_strdup(obj->GetStringAttribute(ui::AX_ATTR_URL).c_str());
}
static AtkObject* browser_accessibility_atk_hyperlink_get_object(
AtkHyperlink* atk_hyperlink,
gint index) {
BrowserAccessibilityAuraLinux* obj = ToBrowserAccessibilityAuraLinux(
BROWSER_ACCESSIBILITY_ATK_HYPERLINK(atk_hyperlink));
if (!obj)
return nullptr;
if (index != 0)
return nullptr;
return obj->GetAtkObject();
}
static gint browser_accessibility_atk_hyperlink_get_n_anchors(
AtkHyperlink* atk_hyperlink) {
BrowserAccessibilityAuraLinux* obj = ToBrowserAccessibilityAuraLinux(
BROWSER_ACCESSIBILITY_ATK_HYPERLINK(atk_hyperlink));
return obj ? 1 : 0;
}
static gboolean browser_accessibility_atk_hyperlink_is_valid(
AtkHyperlink* atk_hyperlink) {
BrowserAccessibilityAuraLinux* obj = ToBrowserAccessibilityAuraLinux(
BROWSER_ACCESSIBILITY_ATK_HYPERLINK(atk_hyperlink));
return obj ? TRUE : FALSE;
}
static gboolean browser_accessibility_atk_hyperlink_is_selected_link(
AtkHyperlink* atk_hyperlink) {
BrowserAccessibilityAuraLinux* obj = ToBrowserAccessibilityAuraLinux(
BROWSER_ACCESSIBILITY_ATK_HYPERLINK(atk_hyperlink));
if (!obj)
return false;
return obj->manager()->GetFocus() == obj;
}
static void browser_accessibility_atk_hyperlink_class_init(
AtkHyperlinkClass* klass) {
GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
browser_accessibility_atk_hyperlink_parent_class =
g_type_class_peek_parent(klass);
gobject_class->finalize = browser_accessibility_atk_hyperlink_finalize;
klass->get_uri = browser_accessibility_atk_hyperlink_get_uri;
klass->get_object = browser_accessibility_atk_hyperlink_get_object;
klass->is_valid = browser_accessibility_atk_hyperlink_is_valid;
klass->get_n_anchors = browser_accessibility_atk_hyperlink_get_n_anchors;
klass->is_selected_link =
browser_accessibility_atk_hyperlink_is_selected_link;
// TODO(jose.dapena) implement get_start_index and get_end_index methods
// that should provide the range of the link in the embedding text.
}
//
// AtkAction interface.
//
static BrowserAccessibilityAuraLinux* ToBrowserAccessibilityAuraLinux(
AtkAction* atk_action) {
if (!IS_BROWSER_ACCESSIBILITY_ATK_HYPERLINK(atk_action))
return nullptr;
return ToBrowserAccessibilityAuraLinux(
BROWSER_ACCESSIBILITY_ATK_HYPERLINK(atk_action));
}
static gboolean browser_accessibility_atk_hyperlink_do_action(AtkAction* action,
gint index) {
g_return_val_if_fail(ATK_IS_ACTION(action), FALSE);
g_return_val_if_fail(!index, FALSE);
BrowserAccessibilityAuraLinux* obj = ToBrowserAccessibilityAuraLinux(action);
if (!obj)
return FALSE;
obj->manager()->DoDefaultAction(*obj);
return TRUE;
}
static gint browser_accessibility_atk_hyperlink_get_n_actions(
AtkAction* action) {
g_return_val_if_fail(ATK_IS_ACTION(action), FALSE);
BrowserAccessibilityAuraLinux* obj = ToBrowserAccessibilityAuraLinux(action);
if (!obj)
return 0;
return 1;
}
static const gchar* browser_accessibility_atk_hyperlink_get_description(
AtkAction* action,
gint index) {
g_return_val_if_fail(ATK_IS_ACTION(action), FALSE);
g_return_val_if_fail(!index, FALSE);
BrowserAccessibilityAuraLinux* obj = ToBrowserAccessibilityAuraLinux(action);
if (!obj)
return nullptr;
// Not implemented
return nullptr;
}
static const gchar* browser_accessibility_atk_hyperlink_get_keybinding(
AtkAction* action,
gint index) {
g_return_val_if_fail(ATK_IS_ACTION(action), FALSE);
g_return_val_if_fail(!index, FALSE);
BrowserAccessibilityAuraLinux* obj = ToBrowserAccessibilityAuraLinux(action);
if (!obj)
return nullptr;
return obj->GetStringAttribute(ui::AX_ATTR_ACCESS_KEY).c_str();
}
static const gchar* browser_accessibility_atk_hyperlink_get_name(
AtkAction* atk_action,
gint index) {
g_return_val_if_fail(ATK_IS_ACTION(atk_action), FALSE);
g_return_val_if_fail(!index, FALSE);
BrowserAccessibilityAuraLinux* obj =
ToBrowserAccessibilityAuraLinux(atk_action);
if (!obj)
return nullptr;
int action;
if (!obj->GetIntAttribute(ui::AX_ATTR_DEFAULT_ACTION_VERB, &action))
return nullptr;
base::string16 action_verb = ui::ActionVerbToUnlocalizedString(
static_cast<ui::AXDefaultActionVerb>(action));
return base::UTF16ToUTF8(action_verb).c_str();
}
static const gchar* browser_accessibility_atk_hyperlink_get_localized_name(
AtkAction* atk_action,
gint index) {
g_return_val_if_fail(ATK_IS_ACTION(atk_action), FALSE);
g_return_val_if_fail(!index, FALSE);
BrowserAccessibilityAuraLinux* obj =
ToBrowserAccessibilityAuraLinux(atk_action);
if (!obj)
return nullptr;
int action;
if (!obj->GetIntAttribute(ui::AX_ATTR_DEFAULT_ACTION_VERB, &action))
return nullptr;
base::string16 action_verb = ui::ActionVerbToLocalizedString(
static_cast<ui::AXDefaultActionVerb>(action));
return base::UTF16ToUTF8(action_verb).c_str();
}
static void atk_action_interface_init(AtkActionIface* iface) {
iface->do_action = browser_accessibility_atk_hyperlink_do_action;
iface->get_n_actions = browser_accessibility_atk_hyperlink_get_n_actions;
iface->get_description = browser_accessibility_atk_hyperlink_get_description;
iface->get_keybinding = browser_accessibility_atk_hyperlink_get_keybinding;
iface->get_name = browser_accessibility_atk_hyperlink_get_name;
iface->get_localized_name =
browser_accessibility_atk_hyperlink_get_localized_name;
}
void browser_accessibility_atk_hyperlink_set_object(
BrowserAccessibilityAtkHyperlink* atk_hyperlink,
BrowserAccessibilityAuraLinux* obj) {
g_return_if_fail(BROWSER_ACCESSIBILITY_ATK_HYPERLINK(atk_hyperlink));
atk_hyperlink->m_object = obj;
}
GType browser_accessibility_atk_hyperlink_get_type() {
static volatile gsize type_volatile = 0;
#if !GLIB_CHECK_VERSION(2, 36, 0)
g_type_init();
#endif
if (g_once_init_enter(&type_volatile)) {
static const GTypeInfo tinfo = {
sizeof(BrowserAccessibilityAtkHyperlinkClass),
(GBaseInitFunc) nullptr,
(GBaseFinalizeFunc) nullptr,
(GClassInitFunc)browser_accessibility_atk_hyperlink_class_init,
(GClassFinalizeFunc) nullptr,
nullptr, /* class data */
sizeof(BrowserAccessibilityAtkHyperlink), /* instance size */
0, /* nb preallocs */
(GInstanceInitFunc) nullptr,
nullptr /* value table */
};
static const GInterfaceInfo actionInfo = {
(GInterfaceInitFunc)(GInterfaceInitFunc)atk_action_interface_init,
(GInterfaceFinalizeFunc)0, 0};
GType type = g_type_register_static(ATK_TYPE_HYPERLINK,
"BrowserAccessibilityAtkHyperlink",
&tinfo, GTypeFlags(0));
g_type_add_interface_static(type, ATK_TYPE_ACTION, &actionInfo);
g_once_init_leave(&type_volatile, type);
}
return type_volatile;
}
} // namespace content
// Copyright (c) 2017 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_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_ATK_HYPERLINK_H_
#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_ATK_HYPERLINK_H_
#include <atk/atk.h>
namespace content {
class BrowserAccessibilityAuraLinux;
G_BEGIN_DECLS
#define BROWSER_ACCESSIBILITY_ATK_HYPERLINK_TYPE \
(browser_accessibility_atk_hyperlink_get_type())
#define BROWSER_ACCESSIBILITY_ATK_HYPERLINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), BROWSER_ACCESSIBILITY_ATK_HYPERLINK_TYPE, \
BrowserAccessibilityAtkHyperlink))
#define BROWSER_ACCESSIBILITY_ATK_HYPERLINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), BROWSER_ACCESSIBILITY_ATK_HYPERLINK_TYPE, \
BrowserAccessibilityAtkHyperlinkClass))
#define IS_BROWSER_ACCESSIBILITY_ATK_HYPERLINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), BROWSER_ACCESSIBILITY_ATK_HYPERLINK_TYPE))
#define IS_BROWSER_ACCESSIBILITY_ATK_HYPERLINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), BROWSER_ACCESSIBILITY_ATK_HYPERLINK_TYPE))
#define BROWSER_ACCESSIBILITY_ATK_HYPERLINK_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), BROWSER_ACCESSIBILITY_ATK_HYPERLINK_TYPE, \
BrowserAccessibilityAtkHyperlinkClass))
typedef struct _BrowserAccessibilityAtkHyperlink
BrowserAccessibilityAtkHyperlink;
typedef struct _BrowserAccessibilityAtkHyperlinkClass
BrowserAccessibilityAtkHyperlinkClass;
struct _BrowserAccessibilityAtkHyperlink {
AtkHyperlink parent;
BrowserAccessibilityAuraLinux* m_object;
};
struct _BrowserAccessibilityAtkHyperlinkClass {
AtkHyperlinkClass parent_class;
};
GType browser_accessibility_atk_hyperlink_get_type(void) G_GNUC_CONST;
void browser_accessibility_atk_hyperlink_set_object(
BrowserAccessibilityAtkHyperlink* hyperlink,
BrowserAccessibilityAuraLinux* obj);
G_END_DECLS
} // namespace content
#endif // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_ATK_HYPERLINK_H_
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "content/browser/accessibility/browser_accessibility_atk_hyperlink.h"
#include "content/browser/accessibility/browser_accessibility_manager_auralinux.h" #include "content/browser/accessibility/browser_accessibility_manager_auralinux.h"
#include "content/common/accessibility_messages.h" #include "content/common/accessibility_messages.h"
#include "ui/accessibility/ax_text_utils.h" #include "ui/accessibility/ax_text_utils.h"
...@@ -289,6 +290,40 @@ static const GInterfaceInfo DocumentInfo = { ...@@ -289,6 +290,40 @@ static const GInterfaceInfo DocumentInfo = {
nullptr}; nullptr};
// //
// AtkHyperlinkImpl interface.
//
static BrowserAccessibilityAuraLinux* ToBrowserAccessibilityAuraLinux(
AtkHyperlinkImpl* atk_hyperlink_impl) {
if (!IS_BROWSER_ACCESSIBILITY(atk_hyperlink_impl))
return nullptr;
return ToBrowserAccessibilityAuraLinux(
BROWSER_ACCESSIBILITY(atk_hyperlink_impl));
}
static AtkHyperlink* browser_accessibility_get_hyperlink(
AtkHyperlinkImpl* atk_hyperlink_impl) {
g_return_val_if_fail(ATK_HYPERLINK_IMPL(atk_hyperlink_impl), 0);
BrowserAccessibilityAuraLinux* obj =
ToBrowserAccessibilityAuraLinux(atk_hyperlink_impl);
if (!obj)
return 0;
AtkHyperlink* atk_hyperlink = obj->GetAtkHyperlink();
g_object_ref(atk_hyperlink);
return atk_hyperlink;
}
void HyperlinkImplInterfaceInit(AtkHyperlinkImplIface* iface) {
iface->get_hyperlink = browser_accessibility_get_hyperlink;
}
static const GInterfaceInfo HyperlinkImplInfo = {
reinterpret_cast<GInterfaceInitFunc>(HyperlinkImplInterfaceInit), nullptr,
nullptr};
//
// AtkImage interface. // AtkImage interface.
// //
...@@ -704,6 +739,9 @@ static int GetInterfaceMaskFromObject(BrowserAccessibilityAuraLinux* obj) { ...@@ -704,6 +739,9 @@ static int GetInterfaceMaskFromObject(BrowserAccessibilityAuraLinux* obj) {
if (role == ui::AX_ROLE_IMAGE || role == ui::AX_ROLE_IMAGE_MAP) if (role == ui::AX_ROLE_IMAGE || role == ui::AX_ROLE_IMAGE_MAP)
interface_mask |= 1 << ATK_IMAGE_INTERFACE; interface_mask |= 1 << ATK_IMAGE_INTERFACE;
if (role == ui::AX_ROLE_LINK)
interface_mask |= 1 << ATK_HYPERLINK_INTERFACE;
return interface_mask; return interface_mask;
} }
...@@ -740,6 +778,9 @@ static GType GetAccessibilityTypeFromObject( ...@@ -740,6 +778,9 @@ static GType GetAccessibilityTypeFromObject(
g_type_add_interface_static(type, ATK_TYPE_IMAGE, &ImageInfo); g_type_add_interface_static(type, ATK_TYPE_IMAGE, &ImageInfo);
if (interface_mask & (1 << ATK_VALUE_INTERFACE)) if (interface_mask & (1 << ATK_VALUE_INTERFACE))
g_type_add_interface_static(type, ATK_TYPE_VALUE, &ValueInfo); g_type_add_interface_static(type, ATK_TYPE_VALUE, &ValueInfo);
if (interface_mask & (1 << ATK_HYPERLINK_INTERFACE))
g_type_add_interface_static(type, ATK_TYPE_HYPERLINK_IMPL,
&HyperlinkImplInfo);
return type; return type;
} }
...@@ -772,9 +813,14 @@ BrowserAccessibility* BrowserAccessibility::Create() { ...@@ -772,9 +813,14 @@ BrowserAccessibility* BrowserAccessibility::Create() {
} }
BrowserAccessibilityAuraLinux::BrowserAccessibilityAuraLinux() BrowserAccessibilityAuraLinux::BrowserAccessibilityAuraLinux()
: atk_object_(nullptr) {} : atk_object_(nullptr), atk_hyperlink_(nullptr) {}
BrowserAccessibilityAuraLinux::~BrowserAccessibilityAuraLinux() { BrowserAccessibilityAuraLinux::~BrowserAccessibilityAuraLinux() {
if (atk_hyperlink_) {
browser_accessibility_atk_hyperlink_set_object(
BROWSER_ACCESSIBILITY_ATK_HYPERLINK(atk_hyperlink_), nullptr);
g_object_unref(atk_hyperlink_);
}
browser_accessibility_detach(BROWSER_ACCESSIBILITY(atk_object_)); browser_accessibility_detach(BROWSER_ACCESSIBILITY(atk_object_));
if (atk_object_) if (atk_object_)
g_object_unref(atk_object_); g_object_unref(atk_object_);
...@@ -786,6 +832,19 @@ AtkObject* BrowserAccessibilityAuraLinux::GetAtkObject() const { ...@@ -786,6 +832,19 @@ AtkObject* BrowserAccessibilityAuraLinux::GetAtkObject() const {
return atk_object_; return atk_object_;
} }
AtkHyperlink* BrowserAccessibilityAuraLinux::GetAtkHyperlink() {
g_return_val_if_fail(ATK_HYPERLINK_IMPL(atk_object_), 0);
if (!atk_hyperlink_) {
atk_hyperlink_ = ATK_HYPERLINK(
g_object_new(BROWSER_ACCESSIBILITY_ATK_HYPERLINK_TYPE, 0));
browser_accessibility_atk_hyperlink_set_object(
BROWSER_ACCESSIBILITY_ATK_HYPERLINK(atk_hyperlink_), this);
}
return atk_hyperlink_;
}
void BrowserAccessibilityAuraLinux::OnDataChanged() { void BrowserAccessibilityAuraLinux::OnDataChanged() {
BrowserAccessibility::OnDataChanged(); BrowserAccessibility::OnDataChanged();
InitRoleAndState(); InitRoleAndState();
......
...@@ -67,6 +67,7 @@ class BrowserAccessibilityAuraLinux : public BrowserAccessibility { ...@@ -67,6 +67,7 @@ class BrowserAccessibilityAuraLinux : public BrowserAccessibility {
~BrowserAccessibilityAuraLinux() override; ~BrowserAccessibilityAuraLinux() override;
AtkObject* GetAtkObject() const; AtkObject* GetAtkObject() const;
AtkHyperlink* GetAtkHyperlink();
AtkRole atk_role() { return atk_role_; } AtkRole atk_role() { return atk_role_; }
...@@ -84,7 +85,8 @@ class BrowserAccessibilityAuraLinux : public BrowserAccessibility { ...@@ -84,7 +85,8 @@ class BrowserAccessibilityAuraLinux : public BrowserAccessibility {
AtkRole atk_role_; AtkRole atk_role_;
int interface_mask_; int interface_mask_;
private: AtkHyperlink* atk_hyperlink_;
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityAuraLinux); DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityAuraLinux);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment