Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/accessible/atk/nsMaiHyperlink.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "nsIURI.h"
8
#include "nsMaiHyperlink.h"
9
#include "mozilla/a11y/ProxyAccessible.h"
10
11
using namespace mozilla::a11y;
12
13
/* MaiAtkHyperlink */
14
15
#define MAI_TYPE_ATK_HYPERLINK      (mai_atk_hyperlink_get_type ())
16
0
#define MAI_ATK_HYPERLINK(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
17
0
                                     MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlink))
18
#define MAI_ATK_HYPERLINK_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass),\
19
                                 MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass))
20
0
#define MAI_IS_ATK_HYPERLINK(obj)      (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
21
0
                                        MAI_TYPE_ATK_HYPERLINK))
22
#define MAI_IS_ATK_HYPERLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
23
                                        MAI_TYPE_ATK_HYPERLINK))
24
#define MAI_ATK_HYPERLINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
25
                                 MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlinkClass))
26
27
/**
28
 * This MaiAtkHyperlink is a thin wrapper, in the MAI namespace,
29
 * for AtkHyperlink
30
 */
31
32
struct MaiAtkHyperlink
33
{
34
    AtkHyperlink parent;
35
36
    /*
37
     * The MaiHyperlink whose properties and features are exported via this
38
     * hyperlink instance.
39
     */
40
    MaiHyperlink *maiHyperlink;
41
};
42
43
struct MaiAtkHyperlinkClass
44
{
45
    AtkHyperlinkClass parent_class;
46
};
47
48
GType mai_atk_hyperlink_get_type(void);
49
50
G_BEGIN_DECLS
51
/* callbacks for AtkHyperlink */
52
static void classInitCB(AtkHyperlinkClass *aClass);
53
static void finalizeCB(GObject *aObj);
54
55
/* callbacks for AtkHyperlink virtual functions */
56
static gchar *getUriCB(AtkHyperlink *aLink, gint aLinkIndex);
57
static AtkObject *getObjectCB(AtkHyperlink *aLink, gint aLinkIndex);
58
static gint getEndIndexCB(AtkHyperlink *aLink);
59
static gint getStartIndexCB(AtkHyperlink *aLink);
60
static gboolean isValidCB(AtkHyperlink *aLink);
61
static gint getAnchorCountCB(AtkHyperlink *aLink);
62
G_END_DECLS
63
64
static gpointer parent_class = nullptr;
65
66
static MaiHyperlink*
67
GetMaiHyperlink(AtkHyperlink *aHyperlink)
68
0
{
69
0
    NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
70
0
    MaiHyperlink * maiHyperlink =
71
0
        MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink;
72
0
    NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr);
73
0
    NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr);
74
0
    return maiHyperlink;
75
0
}
76
77
GType
78
mai_atk_hyperlink_get_type(void)
79
0
{
80
0
    static GType type = 0;
81
0
82
0
    if (!type) {
83
0
        static const GTypeInfo tinfo = {
84
0
            sizeof(MaiAtkHyperlinkClass),
85
0
            (GBaseInitFunc)nullptr,
86
0
            (GBaseFinalizeFunc)nullptr,
87
0
            (GClassInitFunc)classInitCB,
88
0
            (GClassFinalizeFunc)nullptr,
89
0
            nullptr, /* class data */
90
0
            sizeof(MaiAtkHyperlink), /* instance size */
91
0
            0, /* nb preallocs */
92
0
            (GInstanceInitFunc)nullptr,
93
0
            nullptr /* value table */
94
0
        };
95
0
96
0
        type = g_type_register_static(ATK_TYPE_HYPERLINK,
97
0
                                      "MaiAtkHyperlink",
98
0
                                      &tinfo, GTypeFlags(0));
99
0
    }
100
0
    return type;
101
0
}
102
103
MaiHyperlink::MaiHyperlink(AccessibleOrProxy aHyperLink) :
104
    mHyperlink(aHyperLink),
105
    mMaiAtkHyperlink(nullptr)
106
0
{
107
0
    mMaiAtkHyperlink =
108
0
        reinterpret_cast<AtkHyperlink *>
109
0
                        (g_object_new(mai_atk_hyperlink_get_type(), nullptr));
110
0
    NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY");
111
0
    if (!mMaiAtkHyperlink)
112
0
      return;
113
0
114
0
    MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = this;
115
0
}
116
117
MaiHyperlink::~MaiHyperlink()
118
0
{
119
0
  if (mMaiAtkHyperlink) {
120
0
    MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = nullptr;
121
0
    g_object_unref(mMaiAtkHyperlink);
122
0
  }
123
0
}
124
125
126
/* static functions for ATK callbacks */
127
128
void
129
classInitCB(AtkHyperlinkClass *aClass)
130
0
{
131
0
    GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);
132
0
133
0
    parent_class = g_type_class_peek_parent(aClass);
134
0
135
0
    aClass->get_uri = getUriCB;
136
0
    aClass->get_object = getObjectCB;
137
0
    aClass->get_end_index = getEndIndexCB;
138
0
    aClass->get_start_index = getStartIndexCB;
139
0
    aClass->is_valid = isValidCB;
140
0
    aClass->get_n_anchors = getAnchorCountCB;
141
0
142
0
    gobject_class->finalize = finalizeCB;
143
0
}
144
145
void
146
finalizeCB(GObject *aObj)
147
0
{
148
0
    NS_ASSERTION(MAI_IS_ATK_HYPERLINK(aObj), "Invalid MaiAtkHyperlink");
149
0
    if (!MAI_IS_ATK_HYPERLINK(aObj))
150
0
        return;
151
0
152
0
    MaiAtkHyperlink *maiAtkHyperlink = MAI_ATK_HYPERLINK(aObj);
153
0
    maiAtkHyperlink->maiHyperlink = nullptr;
154
0
155
0
    /* call parent finalize function */
156
0
    if (G_OBJECT_CLASS (parent_class)->finalize)
157
0
        G_OBJECT_CLASS (parent_class)->finalize(aObj);
158
0
}
159
160
gchar *
161
getUriCB(AtkHyperlink *aLink, gint aLinkIndex)
162
0
{
163
0
  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
164
0
  if (!maiLink)
165
0
    return nullptr;
166
0
167
0
  nsAutoCString cautoStr;
168
0
  if (Accessible* hyperlink = maiLink->GetAccHyperlink()) {
169
0
    nsCOMPtr<nsIURI> uri = hyperlink->AnchorURIAt(aLinkIndex);
170
0
    if (!uri)
171
0
      return nullptr;
172
0
173
0
    nsresult rv = uri->GetSpec(cautoStr);
174
0
    NS_ENSURE_SUCCESS(rv, nullptr);
175
0
176
0
    return g_strdup(cautoStr.get());
177
0
  }
178
0
179
0
  bool valid;
180
0
  maiLink->Proxy()->AnchorURIAt(aLinkIndex, cautoStr, &valid);
181
0
  if (!valid)
182
0
    return nullptr;
183
0
184
0
  return g_strdup(cautoStr.get());
185
0
}
186
187
AtkObject *
188
getObjectCB(AtkHyperlink *aLink, gint aLinkIndex)
189
0
{
190
0
  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
191
0
  if (!maiLink) {
192
0
    return nullptr;
193
0
  }
194
0
195
0
  if (Accessible* hyperlink = maiLink->GetAccHyperlink()) {
196
0
    Accessible* anchor = hyperlink->AnchorAt(aLinkIndex);
197
0
    NS_ENSURE_TRUE(anchor, nullptr);
198
0
199
0
    return AccessibleWrap::GetAtkObject(anchor);
200
0
  }
201
0
202
0
  ProxyAccessible* anchor = maiLink->Proxy()->AnchorAt(aLinkIndex);
203
0
  return anchor ? GetWrapperFor(anchor) : nullptr;
204
0
}
205
206
gint
207
getEndIndexCB(AtkHyperlink *aLink)
208
0
{
209
0
  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
210
0
  if (!maiLink)
211
0
    return false;
212
0
213
0
  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
214
0
    return static_cast<gint>(hyperlink->EndOffset());
215
0
216
0
  bool valid = false;
217
0
  uint32_t endIdx = maiLink->Proxy()->EndOffset(&valid);
218
0
  return valid ? static_cast<gint>(endIdx) : -1;
219
0
}
220
221
gint
222
getStartIndexCB(AtkHyperlink *aLink)
223
0
{
224
0
  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
225
0
  if (!maiLink)
226
0
    return -1;
227
0
228
0
  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
229
0
    return static_cast<gint>(hyperlink->StartOffset());
230
0
231
0
  bool valid = false;
232
0
  uint32_t startIdx = maiLink->Proxy()->StartOffset(&valid);
233
0
  return valid ? static_cast<gint>(startIdx) : -1;
234
0
}
235
236
gboolean
237
isValidCB(AtkHyperlink *aLink)
238
0
{
239
0
  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
240
0
  if (!maiLink)
241
0
    return false;
242
0
243
0
  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
244
0
    return static_cast<gboolean>(hyperlink->IsLinkValid());
245
0
246
0
  return static_cast<gboolean>(maiLink->Proxy()->IsLinkValid());
247
0
}
248
249
gint
250
getAnchorCountCB(AtkHyperlink *aLink)
251
0
{
252
0
  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
253
0
  if (!maiLink)
254
0
    return -1;
255
0
256
0
  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
257
0
    return static_cast<gint>(hyperlink->AnchorCount());
258
0
259
0
  bool valid = false;
260
0
  uint32_t anchorCount = maiLink->Proxy()->AnchorCount(&valid);
261
0
  return valid ? static_cast<gint>(anchorCount) : -1;
262
0
}