tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsMaiHyperlink.cpp (6255B)


      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/RemoteAccessible.h"
     10 
     11 using namespace mozilla::a11y;
     12 
     13 /* MaiAtkHyperlink */
     14 
     15 #define MAI_TYPE_ATK_HYPERLINK (mai_atk_hyperlink_get_type())
     16 #define MAI_ATK_HYPERLINK(obj) \
     17  (G_TYPE_CHECK_INSTANCE_CAST((obj), MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlink))
     18 #define MAI_ATK_HYPERLINK_CLASS(klass)                      \
     19  (G_TYPE_CHECK_CLASS_CAST((klass), MAI_TYPE_ATK_HYPERLINK, \
     20                           MaiAtkHyperlinkClass))
     21 #define MAI_IS_ATK_HYPERLINK(obj) \
     22  (G_TYPE_CHECK_INSTANCE_TYPE((obj), MAI_TYPE_ATK_HYPERLINK))
     23 #define MAI_IS_ATK_HYPERLINK_CLASS(klass) \
     24  (G_TYPE_CHECK_CLASS_TYPE((klass), MAI_TYPE_ATK_HYPERLINK))
     25 #define MAI_ATK_HYPERLINK_GET_CLASS(obj)                    \
     26  (G_TYPE_INSTANCE_GET_CLASS((obj), MAI_TYPE_ATK_HYPERLINK, \
     27                             MaiAtkHyperlinkClass))
     28 
     29 /**
     30 * This MaiAtkHyperlink is a thin wrapper, in the MAI namespace,
     31 * for AtkHyperlink
     32 */
     33 
     34 struct MaiAtkHyperlink {
     35  AtkHyperlink parent;
     36 
     37  /*
     38   * The MaiHyperlink whose properties and features are exported via this
     39   * hyperlink instance.
     40   */
     41  MaiHyperlink* maiHyperlink;
     42 };
     43 
     44 struct MaiAtkHyperlinkClass {
     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* GetMaiHyperlink(AtkHyperlink* aHyperlink) {
     67  NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
     68  MaiHyperlink* maiHyperlink = MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink;
     69  NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr);
     70  NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr);
     71  return maiHyperlink;
     72 }
     73 
     74 GType mai_atk_hyperlink_get_type(void) {
     75  static GType type = 0;
     76 
     77  if (!type) {
     78    static const GTypeInfo tinfo = {
     79        sizeof(MaiAtkHyperlinkClass),
     80        (GBaseInitFunc) nullptr,
     81        (GBaseFinalizeFunc) nullptr,
     82        (GClassInitFunc)classInitCB,
     83        (GClassFinalizeFunc) nullptr,
     84        nullptr,                 /* class data */
     85        sizeof(MaiAtkHyperlink), /* instance size */
     86        0,                       /* nb preallocs */
     87        (GInstanceInitFunc) nullptr,
     88        nullptr /* value table */
     89    };
     90 
     91    type = g_type_register_static(ATK_TYPE_HYPERLINK, "MaiAtkHyperlink", &tinfo,
     92                                  GTypeFlags(0));
     93  }
     94  return type;
     95 }
     96 
     97 MaiHyperlink::MaiHyperlink(Accessible* aHyperLink)
     98    : mHyperlink(aHyperLink), mMaiAtkHyperlink(nullptr) {
     99  mMaiAtkHyperlink = reinterpret_cast<AtkHyperlink*>(
    100      g_object_new(mai_atk_hyperlink_get_type(), nullptr));
    101  NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY");
    102  if (!mMaiAtkHyperlink) return;
    103 
    104  MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = this;
    105 }
    106 
    107 MaiHyperlink::~MaiHyperlink() {
    108  if (mMaiAtkHyperlink) {
    109    MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = nullptr;
    110    g_object_unref(mMaiAtkHyperlink);
    111  }
    112 }
    113 
    114 /* static functions for ATK callbacks */
    115 
    116 void classInitCB(AtkHyperlinkClass* aClass) {
    117  GObjectClass* gobject_class = G_OBJECT_CLASS(aClass);
    118 
    119  parent_class = g_type_class_peek_parent(aClass);
    120 
    121  aClass->get_uri = getUriCB;
    122  aClass->get_object = getObjectCB;
    123  aClass->get_end_index = getEndIndexCB;
    124  aClass->get_start_index = getStartIndexCB;
    125  aClass->is_valid = isValidCB;
    126  aClass->get_n_anchors = getAnchorCountCB;
    127 
    128  gobject_class->finalize = finalizeCB;
    129 }
    130 
    131 void finalizeCB(GObject* aObj) {
    132  NS_ASSERTION(MAI_IS_ATK_HYPERLINK(aObj), "Invalid MaiAtkHyperlink");
    133  if (!MAI_IS_ATK_HYPERLINK(aObj)) return;
    134 
    135  MaiAtkHyperlink* maiAtkHyperlink = MAI_ATK_HYPERLINK(aObj);
    136  maiAtkHyperlink->maiHyperlink = nullptr;
    137 
    138  /* call parent finalize function */
    139  if (G_OBJECT_CLASS(parent_class)->finalize) {
    140    G_OBJECT_CLASS(parent_class)->finalize(aObj);
    141  }
    142 }
    143 
    144 gchar* getUriCB(AtkHyperlink* aLink, gint aLinkIndex) {
    145  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
    146  if (!maiLink) {
    147    return nullptr;
    148  }
    149 
    150  Accessible* acc = maiLink->Acc();
    151  if (!acc) {
    152    return nullptr;
    153  }
    154 
    155  nsAutoCString cautoStr;
    156  nsCOMPtr<nsIURI> uri = acc->AnchorURIAt(aLinkIndex);
    157  if (!uri) return nullptr;
    158 
    159  nsresult rv = uri->GetSpec(cautoStr);
    160  NS_ENSURE_SUCCESS(rv, nullptr);
    161 
    162  return g_strdup(cautoStr.get());
    163 }
    164 
    165 AtkObject* getObjectCB(AtkHyperlink* aLink, gint aLinkIndex) {
    166  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
    167  if (!maiLink) {
    168    return nullptr;
    169  }
    170 
    171  Accessible* acc = maiLink->Acc();
    172  if (!acc) {
    173    return nullptr;
    174  }
    175 
    176  Accessible* anchor = acc->AnchorAt(aLinkIndex);
    177  return anchor ? GetWrapperFor(anchor) : nullptr;
    178 }
    179 
    180 gint getEndIndexCB(AtkHyperlink* aLink) {
    181  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
    182  if (!maiLink) return false;
    183 
    184  return static_cast<gint>(maiLink->Acc()->EndOffset());
    185 }
    186 
    187 gint getStartIndexCB(AtkHyperlink* aLink) {
    188  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
    189  if (!maiLink) return -1;
    190 
    191  return static_cast<gint>(maiLink->Acc()->StartOffset());
    192 }
    193 
    194 gboolean isValidCB(AtkHyperlink* aLink) {
    195  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
    196  if (!maiLink) return false;
    197 
    198  Accessible* acc = maiLink->Acc();
    199  if (!acc) {
    200    return false;
    201  }
    202 
    203  return static_cast<gboolean>(acc->IsLinkValid());
    204 }
    205 
    206 gint getAnchorCountCB(AtkHyperlink* aLink) {
    207  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
    208  if (!maiLink) return -1;
    209 
    210  Accessible* acc = maiLink->Acc();
    211  if (!acc) {
    212    return -1;
    213  }
    214 
    215  return static_cast<gint>(acc->AnchorCount());
    216 }