LCOV - code coverage report
Current view: top level - accessible/atk - AccessibleWrap.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 776 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 56 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "AccessibleWrap.h"
       8             : 
       9             : #include "Accessible-inl.h"
      10             : #include "ApplicationAccessibleWrap.h"
      11             : #include "InterfaceInitFuncs.h"
      12             : #include "nsAccUtils.h"
      13             : #include "mozilla/a11y/PDocAccessible.h"
      14             : #include "OuterDocAccessible.h"
      15             : #include "ProxyAccessible.h"
      16             : #include "DocAccessibleParent.h"
      17             : #include "RootAccessible.h"
      18             : #include "TableAccessible.h"
      19             : #include "TableCellAccessible.h"
      20             : #include "nsMai.h"
      21             : #include "nsMaiHyperlink.h"
      22             : #include "nsString.h"
      23             : #include "nsStateMap.h"
      24             : #include "mozilla/a11y/Platform.h"
      25             : #include "Relation.h"
      26             : #include "RootAccessible.h"
      27             : #include "States.h"
      28             : #include "nsISimpleEnumerator.h"
      29             : 
      30             : #include "mozilla/ArrayUtils.h"
      31             : #include "mozilla/Sprintf.h"
      32             : #include "nsComponentManagerUtils.h"
      33             : #include "nsIPersistentProperties2.h"
      34             : 
      35             : using namespace mozilla;
      36             : using namespace mozilla::a11y;
      37             : 
      38             : MaiAtkObject::EAvailableAtkSignals MaiAtkObject::gAvailableAtkSignals =
      39             :   eUnknown;
      40             : 
      41             : //defined in ApplicationAccessibleWrap.cpp
      42             : extern "C" GType g_atk_hyperlink_impl_type;
      43             : 
      44             : /* MaiAtkObject */
      45             : 
      46             : enum {
      47             :   ACTIVATE,
      48             :   CREATE,
      49             :   DEACTIVATE,
      50             :   DESTROY,
      51             :   MAXIMIZE,
      52             :   MINIMIZE,
      53             :   RESIZE,
      54             :   RESTORE,
      55             :   LAST_SIGNAL
      56             : };
      57             : 
      58             : enum MaiInterfaceType {
      59             :     MAI_INTERFACE_COMPONENT, /* 0 */
      60             :     MAI_INTERFACE_ACTION,
      61             :     MAI_INTERFACE_VALUE,
      62             :     MAI_INTERFACE_EDITABLE_TEXT,
      63             :     MAI_INTERFACE_HYPERTEXT,
      64             :     MAI_INTERFACE_HYPERLINK_IMPL,
      65             :     MAI_INTERFACE_SELECTION,
      66             :     MAI_INTERFACE_TABLE,
      67             :     MAI_INTERFACE_TEXT,
      68             :     MAI_INTERFACE_DOCUMENT,
      69             :     MAI_INTERFACE_IMAGE, /* 10 */
      70             :     MAI_INTERFACE_TABLE_CELL
      71             : };
      72             : 
      73           0 : static GType GetAtkTypeForMai(MaiInterfaceType type)
      74             : {
      75           0 :   switch (type) {
      76             :     case MAI_INTERFACE_COMPONENT:
      77           0 :       return ATK_TYPE_COMPONENT;
      78             :     case MAI_INTERFACE_ACTION:
      79           0 :       return ATK_TYPE_ACTION;
      80             :     case MAI_INTERFACE_VALUE:
      81           0 :       return ATK_TYPE_VALUE;
      82             :     case MAI_INTERFACE_EDITABLE_TEXT:
      83           0 :       return ATK_TYPE_EDITABLE_TEXT;
      84             :     case MAI_INTERFACE_HYPERTEXT:
      85           0 :       return ATK_TYPE_HYPERTEXT;
      86             :     case MAI_INTERFACE_HYPERLINK_IMPL:
      87           0 :        return g_atk_hyperlink_impl_type;
      88             :     case MAI_INTERFACE_SELECTION:
      89           0 :       return ATK_TYPE_SELECTION;
      90             :     case MAI_INTERFACE_TABLE:
      91           0 :       return ATK_TYPE_TABLE;
      92             :     case MAI_INTERFACE_TEXT:
      93           0 :       return ATK_TYPE_TEXT;
      94             :     case MAI_INTERFACE_DOCUMENT:
      95           0 :       return ATK_TYPE_DOCUMENT;
      96             :     case MAI_INTERFACE_IMAGE:
      97           0 :       return ATK_TYPE_IMAGE;
      98             :     case MAI_INTERFACE_TABLE_CELL:
      99           0 :       MOZ_ASSERT(false);
     100             :   }
     101           0 :   return G_TYPE_INVALID;
     102             : }
     103             : 
     104             : #define NON_USER_EVENT ":system"
     105             : 
     106             : // The atk interfaces we can expose without checking what version of ATK we are
     107             : // dealing with.  At the moment AtkTableCell is the only interface we can't
     108             : // always expose.
     109             : static const GInterfaceInfo atk_if_infos[] = {
     110             :     {(GInterfaceInitFunc)componentInterfaceInitCB,
     111             :      (GInterfaceFinalizeFunc) nullptr, nullptr},
     112             :     {(GInterfaceInitFunc)actionInterfaceInitCB,
     113             :      (GInterfaceFinalizeFunc) nullptr, nullptr},
     114             :     {(GInterfaceInitFunc)valueInterfaceInitCB,
     115             :      (GInterfaceFinalizeFunc) nullptr, nullptr},
     116             :     {(GInterfaceInitFunc)editableTextInterfaceInitCB,
     117             :      (GInterfaceFinalizeFunc) nullptr, nullptr},
     118             :     {(GInterfaceInitFunc)hypertextInterfaceInitCB,
     119             :      (GInterfaceFinalizeFunc) nullptr, nullptr},
     120             :     {(GInterfaceInitFunc)hyperlinkImplInterfaceInitCB,
     121             :      (GInterfaceFinalizeFunc) nullptr, nullptr},
     122             :     {(GInterfaceInitFunc)selectionInterfaceInitCB,
     123             :      (GInterfaceFinalizeFunc) nullptr, nullptr},
     124             :     {(GInterfaceInitFunc)tableInterfaceInitCB,
     125             :      (GInterfaceFinalizeFunc) nullptr, nullptr},
     126             :     {(GInterfaceInitFunc)textInterfaceInitCB,
     127             :      (GInterfaceFinalizeFunc) nullptr, nullptr},
     128             :     {(GInterfaceInitFunc)documentInterfaceInitCB,
     129             :      (GInterfaceFinalizeFunc) nullptr, nullptr},
     130             :     {(GInterfaceInitFunc)imageInterfaceInitCB,
     131             :      (GInterfaceFinalizeFunc) nullptr, nullptr}
     132             : };
     133             : 
     134             : static GQuark quark_mai_hyperlink = 0;
     135             : 
     136             : AtkHyperlink*
     137           0 : MaiAtkObject::GetAtkHyperlink()
     138             : {
     139           0 :   NS_ASSERTION(quark_mai_hyperlink, "quark_mai_hyperlink not initialized");
     140             :   MaiHyperlink* maiHyperlink =
     141           0 :     (MaiHyperlink*)g_object_get_qdata(G_OBJECT(this), quark_mai_hyperlink);
     142           0 :   if (!maiHyperlink) {
     143           0 :     maiHyperlink = new MaiHyperlink(accWrap);
     144           0 :     g_object_set_qdata(G_OBJECT(this), quark_mai_hyperlink, maiHyperlink);
     145             :   }
     146             : 
     147           0 :   return maiHyperlink->GetAtkHyperlink();
     148             : }
     149             : 
     150             : void
     151           0 : MaiAtkObject::Shutdown()
     152             : {
     153           0 :   accWrap.SetBits(0);
     154             :   MaiHyperlink* maiHyperlink =
     155           0 :     (MaiHyperlink*)g_object_get_qdata(G_OBJECT(this), quark_mai_hyperlink);
     156           0 :   if (maiHyperlink) {
     157           0 :     delete maiHyperlink;
     158           0 :     g_object_set_qdata(G_OBJECT(this), quark_mai_hyperlink, nullptr);
     159             :   }
     160           0 : }
     161             : 
     162             : struct MaiAtkObjectClass
     163             : {
     164             :     AtkObjectClass parent_class;
     165             : };
     166             : 
     167             : static guint mai_atk_object_signals [LAST_SIGNAL] = { 0, };
     168             : 
     169             : static void MaybeFireNameChange(AtkObject* aAtkObj, const nsString& aNewName);
     170             : 
     171             : G_BEGIN_DECLS
     172             : /* callbacks for MaiAtkObject */
     173             : static void classInitCB(AtkObjectClass *aClass);
     174             : static void initializeCB(AtkObject *aAtkObj, gpointer aData);
     175             : static void finalizeCB(GObject *aObj);
     176             : 
     177             : /* callbacks for AtkObject virtual functions */
     178             : static const gchar*        getNameCB (AtkObject *aAtkObj);
     179             : /* getDescriptionCB is also used by image interface */
     180             :        const gchar*        getDescriptionCB (AtkObject *aAtkObj);
     181             : static AtkRole             getRoleCB(AtkObject *aAtkObj);
     182             : static AtkAttributeSet*    getAttributesCB(AtkObject *aAtkObj);
     183             : static const gchar* GetLocaleCB(AtkObject*);
     184             : static AtkObject*          getParentCB(AtkObject *aAtkObj);
     185             : static gint                getChildCountCB(AtkObject *aAtkObj);
     186             : static AtkObject*          refChildCB(AtkObject *aAtkObj, gint aChildIndex);
     187             : static gint                getIndexInParentCB(AtkObject *aAtkObj);
     188             : static AtkStateSet*        refStateSetCB(AtkObject *aAtkObj);
     189             : static AtkRelationSet*     refRelationSetCB(AtkObject *aAtkObj);
     190             : 
     191             : /* the missing atkobject virtual functions */
     192             : /*
     193             :   static AtkLayer            getLayerCB(AtkObject *aAtkObj);
     194             :   static gint                getMdiZorderCB(AtkObject *aAtkObj);
     195             :   static void                SetNameCB(AtkObject *aAtkObj,
     196             :   const gchar *name);
     197             :   static void                SetDescriptionCB(AtkObject *aAtkObj,
     198             :   const gchar *description);
     199             :   static void                SetParentCB(AtkObject *aAtkObj,
     200             :   AtkObject *parent);
     201             :   static void                SetRoleCB(AtkObject *aAtkObj,
     202             :   AtkRole role);
     203             :   static guint               ConnectPropertyChangeHandlerCB(
     204             :   AtkObject  *aObj,
     205             :   AtkPropertyChangeHandler *handler);
     206             :   static void                RemovePropertyChangeHandlerCB(
     207             :   AtkObject *aAtkObj,
     208             :   guint handler_id);
     209             :   static void                InitializeCB(AtkObject *aAtkObj,
     210             :   gpointer data);
     211             :   static void                ChildrenChangedCB(AtkObject *aAtkObj,
     212             :   guint change_index,
     213             :   gpointer changed_child);
     214             :   static void                FocusEventCB(AtkObject *aAtkObj,
     215             :   gboolean focus_in);
     216             :   static void                PropertyChangeCB(AtkObject *aAtkObj,
     217             :   AtkPropertyValues *values);
     218             :   static void                StateChangeCB(AtkObject *aAtkObj,
     219             :   const gchar *name,
     220             :   gboolean state_set);
     221             :   static void                VisibleDataChangedCB(AtkObject *aAtkObj);
     222             : */
     223             : G_END_DECLS
     224             : 
     225             : static GType GetMaiAtkType(uint16_t interfacesBits);
     226             : static const char * GetUniqueMaiAtkTypeName(uint16_t interfacesBits);
     227             : 
     228             : static gpointer parent_class = nullptr;
     229             : 
     230             : GType
     231           0 : mai_atk_object_get_type(void)
     232             : {
     233             :     static GType type = 0;
     234             : 
     235           0 :     if (!type) {
     236             :         static const GTypeInfo tinfo = {
     237             :             sizeof(MaiAtkObjectClass),
     238             :             (GBaseInitFunc)nullptr,
     239             :             (GBaseFinalizeFunc)nullptr,
     240             :             (GClassInitFunc)classInitCB,
     241             :             (GClassFinalizeFunc)nullptr,
     242             :             nullptr, /* class data */
     243             :             sizeof(MaiAtkObject), /* instance size */
     244             :             0, /* nb preallocs */
     245             :             (GInstanceInitFunc)nullptr,
     246             :             nullptr /* value table */
     247             :         };
     248             : 
     249           0 :         type = g_type_register_static(ATK_TYPE_OBJECT,
     250             :                                       "MaiAtkObject", &tinfo, GTypeFlags(0));
     251           0 :         quark_mai_hyperlink = g_quark_from_static_string("MaiHyperlink");
     252             :     }
     253           0 :     return type;
     254             : }
     255             : 
     256           0 : AccessibleWrap::
     257           0 :   AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
     258           0 :   Accessible(aContent, aDoc), mAtkObject(nullptr)
     259             : {
     260           0 : }
     261             : 
     262           0 : AccessibleWrap::~AccessibleWrap()
     263             : {
     264           0 :     NS_ASSERTION(!mAtkObject, "ShutdownAtkObject() is not called");
     265           0 : }
     266             : 
     267             : void
     268           0 : AccessibleWrap::ShutdownAtkObject()
     269             : {
     270           0 :   if (!mAtkObject)
     271           0 :     return;
     272             : 
     273           0 :   NS_ASSERTION(IS_MAI_OBJECT(mAtkObject), "wrong type of atk object");
     274           0 :   if (IS_MAI_OBJECT(mAtkObject))
     275           0 :     MAI_ATK_OBJECT(mAtkObject)->Shutdown();
     276             : 
     277           0 :   g_object_unref(mAtkObject);
     278           0 :   mAtkObject = nullptr;
     279             : }
     280             : 
     281             : void
     282           0 : AccessibleWrap::Shutdown()
     283             : {
     284           0 :   ShutdownAtkObject();
     285           0 :   Accessible::Shutdown();
     286           0 : }
     287             : 
     288             : void
     289           0 : AccessibleWrap::GetNativeInterface(void** aOutAccessible)
     290             : {
     291           0 :   *aOutAccessible = nullptr;
     292             : 
     293           0 :   if (!mAtkObject) {
     294           0 :     if (IsDefunct() || IsText()) {
     295             :       // We don't create ATK objects for node which has been shutdown or
     296             :       // plain text leaves
     297           0 :       return;
     298             :     }
     299             : 
     300           0 :     GType type = GetMaiAtkType(CreateMaiInterfaces());
     301           0 :     if (!type)
     302           0 :       return;
     303             : 
     304           0 :     mAtkObject = reinterpret_cast<AtkObject*>(g_object_new(type, nullptr));
     305           0 :     if (!mAtkObject)
     306           0 :       return;
     307             : 
     308           0 :     atk_object_initialize(mAtkObject, this);
     309           0 :     mAtkObject->role = ATK_ROLE_INVALID;
     310           0 :     mAtkObject->layer = ATK_LAYER_INVALID;
     311             :   }
     312             : 
     313           0 :   *aOutAccessible = mAtkObject;
     314             : }
     315             : 
     316             : AtkObject *
     317           0 : AccessibleWrap::GetAtkObject(void)
     318             : {
     319           0 :     void *atkObj = nullptr;
     320           0 :     GetNativeInterface(&atkObj);
     321           0 :     return static_cast<AtkObject *>(atkObj);
     322             : }
     323             : 
     324             : // Get AtkObject from Accessible interface
     325             : /* static */
     326             : AtkObject *
     327           0 : AccessibleWrap::GetAtkObject(Accessible* acc)
     328             : {
     329           0 :     void *atkObjPtr = nullptr;
     330           0 :     acc->GetNativeInterface(&atkObjPtr);
     331           0 :     return atkObjPtr ? ATK_OBJECT(atkObjPtr) : nullptr;
     332             : }
     333             : 
     334             : /* private */
     335             : uint16_t
     336           0 : AccessibleWrap::CreateMaiInterfaces(void)
     337             : {
     338           0 :   uint16_t interfacesBits = 0;
     339             : 
     340             :   // The Component interface is supported by all accessibles.
     341           0 :   interfacesBits |= 1 << MAI_INTERFACE_COMPONENT;
     342             : 
     343             :   // Add Action interface if the action count is more than zero.
     344           0 :   if (ActionCount() > 0)
     345           0 :     interfacesBits |= 1 << MAI_INTERFACE_ACTION;
     346             : 
     347             :   // Text, Editabletext, and Hypertext interface.
     348           0 :   HyperTextAccessible* hyperText = AsHyperText();
     349           0 :   if (hyperText && hyperText->IsTextRole()) {
     350           0 :     interfacesBits |= 1 << MAI_INTERFACE_TEXT;
     351           0 :     interfacesBits |= 1 << MAI_INTERFACE_EDITABLE_TEXT;
     352           0 :     if (!nsAccUtils::MustPrune(this))
     353           0 :       interfacesBits |= 1 << MAI_INTERFACE_HYPERTEXT;
     354             :   }
     355             : 
     356             :   // Value interface.
     357           0 :   if (HasNumericValue())
     358           0 :     interfacesBits |= 1 << MAI_INTERFACE_VALUE;
     359             : 
     360             :   // Document interface.
     361           0 :   if (IsDoc())
     362           0 :     interfacesBits |= 1 << MAI_INTERFACE_DOCUMENT;
     363             : 
     364           0 :   if (IsImage())
     365           0 :     interfacesBits |= 1 << MAI_INTERFACE_IMAGE;
     366             : 
     367             :   // HyperLink interface.
     368           0 :   if (IsLink())
     369           0 :     interfacesBits |= 1 << MAI_INTERFACE_HYPERLINK_IMPL;
     370             : 
     371           0 :   if (!nsAccUtils::MustPrune(this)) {  // These interfaces require children
     372             :     // Table interface.
     373           0 :     if (AsTable())
     374           0 :       interfacesBits |= 1 << MAI_INTERFACE_TABLE;
     375             : 
     376           0 :     if (AsTableCell())
     377           0 :       interfacesBits |= 1 << MAI_INTERFACE_TABLE_CELL;
     378             : 
     379             :     // Selection interface.
     380           0 :     if (IsSelect()) {
     381           0 :       interfacesBits |= 1 << MAI_INTERFACE_SELECTION;
     382             :     }
     383             :   }
     384             : 
     385           0 :   return interfacesBits;
     386             : }
     387             : 
     388             : static GType
     389           0 : GetMaiAtkType(uint16_t interfacesBits)
     390             : {
     391             :     GType type;
     392             :     static const GTypeInfo tinfo = {
     393             :         sizeof(MaiAtkObjectClass),
     394             :         (GBaseInitFunc) nullptr,
     395             :         (GBaseFinalizeFunc) nullptr,
     396             :         (GClassInitFunc) nullptr,
     397             :         (GClassFinalizeFunc) nullptr,
     398             :         nullptr, /* class data */
     399             :         sizeof(MaiAtkObject), /* instance size */
     400             :         0, /* nb preallocs */
     401             :         (GInstanceInitFunc) nullptr,
     402             :         nullptr /* value table */
     403             :     };
     404             : 
     405             :     /*
     406             :      * The members we use to register GTypes are GetAtkTypeForMai
     407             :      * and atk_if_infos, which are constant values to each MaiInterface
     408             :      * So we can reuse the registered GType when having
     409             :      * the same MaiInterface types.
     410             :      */
     411           0 :     const char *atkTypeName = GetUniqueMaiAtkTypeName(interfacesBits);
     412           0 :     type = g_type_from_name(atkTypeName);
     413           0 :     if (type) {
     414           0 :         return type;
     415             :     }
     416             : 
     417             :     /*
     418             :      * gobject limits the number of types that can directly derive from any
     419             :      * given object type to 4095.
     420             :      */
     421             :     static uint16_t typeRegCount = 0;
     422           0 :     if (typeRegCount++ >= 4095) {
     423           0 :         return G_TYPE_INVALID;
     424             :     }
     425           0 :     type = g_type_register_static(MAI_TYPE_ATK_OBJECT,
     426             :                                   atkTypeName,
     427           0 :                                   &tinfo, GTypeFlags(0));
     428             : 
     429           0 :     for (uint32_t index = 0; index < ArrayLength(atk_if_infos); index++) {
     430           0 :       if (interfacesBits & (1 << index)) {
     431           0 :         g_type_add_interface_static(type,
     432             :                                     GetAtkTypeForMai((MaiInterfaceType)index),
     433           0 :                                     &atk_if_infos[index]);
     434             :       }
     435             :     }
     436             : 
     437             :     // Special case AtkTableCell so we can check what version of Atk we are
     438             :     // dealing with.
     439           0 :     if (IsAtkVersionAtLeast(2, 12) && (interfacesBits & (1 << MAI_INTERFACE_TABLE_CELL))) {
     440             :       const GInterfaceInfo cellInfo = {
     441             :         (GInterfaceInitFunc)tableCellInterfaceInitCB,
     442           0 :         (GInterfaceFinalizeFunc)nullptr, nullptr};
     443           0 :       g_type_add_interface_static(type, gAtkTableCellGetTypeFunc(), &cellInfo);
     444             :     }
     445             : 
     446           0 :     return type;
     447             : }
     448             : 
     449             : static const char*
     450           0 : GetUniqueMaiAtkTypeName(uint16_t interfacesBits)
     451             : {
     452             : #define MAI_ATK_TYPE_NAME_LEN (30)     /* 10+sizeof(uint16_t)*8/4+1 < 30 */
     453             : 
     454             :     static gchar namePrefix[] = "MaiAtkType";   /* size = 10 */
     455             :     static gchar name[MAI_ATK_TYPE_NAME_LEN + 1];
     456             : 
     457           0 :     SprintfLiteral(name, "%s%x", namePrefix, interfacesBits);
     458           0 :     name[MAI_ATK_TYPE_NAME_LEN] = '\0';
     459             : 
     460           0 :     return name;
     461             : }
     462             : 
     463             : bool
     464           0 : AccessibleWrap::IsValidObject()
     465             : {
     466             :     // to ensure we are not shut down
     467           0 :     return !IsDefunct();
     468             : }
     469             : 
     470             : /* static functions for ATK callbacks */
     471             : void
     472           0 : classInitCB(AtkObjectClass *aClass)
     473             : {
     474           0 :     GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);
     475             : 
     476           0 :     parent_class = g_type_class_peek_parent(aClass);
     477             : 
     478           0 :     aClass->get_name = getNameCB;
     479           0 :     aClass->get_description = getDescriptionCB;
     480           0 :     aClass->get_parent = getParentCB;
     481           0 :     aClass->get_n_children = getChildCountCB;
     482           0 :     aClass->ref_child = refChildCB;
     483           0 :     aClass->get_index_in_parent = getIndexInParentCB;
     484           0 :     aClass->get_role = getRoleCB;
     485           0 :     aClass->get_attributes = getAttributesCB;
     486           0 :     aClass->get_object_locale = GetLocaleCB;
     487           0 :     aClass->ref_state_set = refStateSetCB;
     488           0 :     aClass->ref_relation_set = refRelationSetCB;
     489             : 
     490           0 :     aClass->initialize = initializeCB;
     491             : 
     492           0 :     gobject_class->finalize = finalizeCB;
     493             : 
     494           0 :     mai_atk_object_signals [ACTIVATE] =
     495           0 :     g_signal_new ("activate",
     496             :                   MAI_TYPE_ATK_OBJECT,
     497             :                   G_SIGNAL_RUN_LAST,
     498             :                   0, /* default signal handler */
     499             :                   nullptr, nullptr,
     500             :                   g_cclosure_marshal_VOID__VOID,
     501             :                   G_TYPE_NONE, 0);
     502           0 :     mai_atk_object_signals [CREATE] =
     503           0 :     g_signal_new ("create",
     504             :                   MAI_TYPE_ATK_OBJECT,
     505             :                   G_SIGNAL_RUN_LAST,
     506             :                   0, /* default signal handler */
     507             :                   nullptr, nullptr,
     508             :                   g_cclosure_marshal_VOID__VOID,
     509             :                   G_TYPE_NONE, 0);
     510           0 :     mai_atk_object_signals [DEACTIVATE] =
     511           0 :     g_signal_new ("deactivate",
     512             :                   MAI_TYPE_ATK_OBJECT,
     513             :                   G_SIGNAL_RUN_LAST,
     514             :                   0, /* default signal handler */
     515             :                   nullptr, nullptr,
     516             :                   g_cclosure_marshal_VOID__VOID,
     517             :                   G_TYPE_NONE, 0);
     518           0 :     mai_atk_object_signals [DESTROY] =
     519           0 :     g_signal_new ("destroy",
     520             :                   MAI_TYPE_ATK_OBJECT,
     521             :                   G_SIGNAL_RUN_LAST,
     522             :                   0, /* default signal handler */
     523             :                   nullptr, nullptr,
     524             :                   g_cclosure_marshal_VOID__VOID,
     525             :                   G_TYPE_NONE, 0);
     526           0 :     mai_atk_object_signals [MAXIMIZE] =
     527           0 :     g_signal_new ("maximize",
     528             :                   MAI_TYPE_ATK_OBJECT,
     529             :                   G_SIGNAL_RUN_LAST,
     530             :                   0, /* default signal handler */
     531             :                   nullptr, nullptr,
     532             :                   g_cclosure_marshal_VOID__VOID,
     533             :                   G_TYPE_NONE, 0);
     534           0 :     mai_atk_object_signals [MINIMIZE] =
     535           0 :     g_signal_new ("minimize",
     536             :                   MAI_TYPE_ATK_OBJECT,
     537             :                   G_SIGNAL_RUN_LAST,
     538             :                   0, /* default signal handler */
     539             :                   nullptr, nullptr,
     540             :                   g_cclosure_marshal_VOID__VOID,
     541             :                   G_TYPE_NONE, 0);
     542           0 :     mai_atk_object_signals [RESIZE] =
     543           0 :     g_signal_new ("resize",
     544             :                   MAI_TYPE_ATK_OBJECT,
     545             :                   G_SIGNAL_RUN_LAST,
     546             :                   0, /* default signal handler */
     547             :                   nullptr, nullptr,
     548             :                   g_cclosure_marshal_VOID__VOID,
     549             :                   G_TYPE_NONE, 0);
     550           0 :     mai_atk_object_signals [RESTORE] =
     551           0 :     g_signal_new ("restore",
     552             :                   MAI_TYPE_ATK_OBJECT,
     553             :                   G_SIGNAL_RUN_LAST,
     554             :                   0, /* default signal handler */
     555             :                   nullptr, nullptr,
     556             :                   g_cclosure_marshal_VOID__VOID,
     557             :                   G_TYPE_NONE, 0);
     558             : 
     559           0 : }
     560             : 
     561             : void
     562           0 : initializeCB(AtkObject *aAtkObj, gpointer aData)
     563             : {
     564           0 :     NS_ASSERTION((IS_MAI_OBJECT(aAtkObj)), "Invalid AtkObject");
     565           0 :     NS_ASSERTION(aData, "Invalid Data to init AtkObject");
     566           0 :     if (!aAtkObj || !aData)
     567           0 :         return;
     568             : 
     569             :     /* call parent init function */
     570             :     /* AtkObjectClass has not a "initialize" function now,
     571             :      * maybe it has later
     572             :      */
     573             : 
     574           0 :     if (ATK_OBJECT_CLASS(parent_class)->initialize)
     575           0 :         ATK_OBJECT_CLASS(parent_class)->initialize(aAtkObj, aData);
     576             : 
     577             :   /* initialize object */
     578           0 :   MAI_ATK_OBJECT(aAtkObj)->accWrap.SetBits(reinterpret_cast<uintptr_t>(aData));
     579             : }
     580             : 
     581             : void
     582           0 : finalizeCB(GObject *aObj)
     583             : {
     584           0 :     if (!IS_MAI_OBJECT(aObj))
     585           0 :         return;
     586           0 :     NS_ASSERTION(MAI_ATK_OBJECT(aObj)->accWrap.IsNull(), "AccWrap NOT null");
     587             : 
     588             :     // call parent finalize function
     589             :     // finalize of GObjectClass will unref the accessible parent if has
     590           0 :     if (G_OBJECT_CLASS (parent_class)->finalize)
     591           0 :         G_OBJECT_CLASS (parent_class)->finalize(aObj);
     592             : }
     593             : 
     594             : const gchar*
     595           0 : getNameCB(AtkObject* aAtkObj)
     596             : {
     597           0 :   nsAutoString name;
     598           0 :   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
     599           0 :   if (accWrap)
     600           0 :     accWrap->Name(name);
     601           0 :   else if (ProxyAccessible* proxy = GetProxy(aAtkObj))
     602           0 :     proxy->Name(name);
     603             :   else
     604           0 :     return nullptr;
     605             : 
     606             :   // XXX Firing an event from here does not seem right
     607           0 :   MaybeFireNameChange(aAtkObj, name);
     608             : 
     609           0 :   return aAtkObj->name;
     610             : }
     611             : 
     612             : static void
     613           0 : MaybeFireNameChange(AtkObject* aAtkObj, const nsString& aNewName)
     614             : {
     615           0 :   NS_ConvertUTF16toUTF8 newNameUTF8(aNewName);
     616           0 :   if (aAtkObj->name && !strcmp(aAtkObj->name, newNameUTF8.get()))
     617           0 :     return;
     618             : 
     619             :   // Below we duplicate the functionality of atk_object_set_name(),
     620             :   // but without calling atk_object_get_name(). Instead of
     621             :   // atk_object_get_name() we directly access aAtkObj->name. This is because
     622             :   // atk_object_get_name() would call getNameCB() which would call
     623             :   // MaybeFireNameChange() (or atk_object_set_name() before this problem was
     624             :   // fixed) and we would get an infinite recursion.
     625             :   // See http://bugzilla.mozilla.org/733712
     626             : 
     627             :   // Do not notify for initial name setting.
     628             :   // See bug http://bugzilla.gnome.org/665870
     629           0 :   bool notify = !!aAtkObj->name;
     630             : 
     631           0 :   free(aAtkObj->name);
     632           0 :   aAtkObj->name = strdup(newNameUTF8.get());
     633             : 
     634           0 :   if (notify)
     635           0 :     g_object_notify(G_OBJECT(aAtkObj), "accessible-name");
     636             : }
     637             : 
     638             : const gchar *
     639           0 : getDescriptionCB(AtkObject *aAtkObj)
     640             : {
     641           0 :   nsAutoString uniDesc;
     642           0 :   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
     643           0 :   if (accWrap) {
     644           0 :     if (accWrap->IsDefunct())
     645           0 :       return nullptr;
     646             : 
     647           0 :     accWrap->Description(uniDesc);
     648           0 :   } else if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
     649           0 :     proxy->Description(uniDesc);
     650             :   } else {
     651           0 :     return nullptr;
     652             :   }
     653             : 
     654           0 :     NS_ConvertUTF8toUTF16 objDesc(aAtkObj->description);
     655           0 :     if (!uniDesc.Equals(objDesc))
     656           0 :         atk_object_set_description(aAtkObj,
     657           0 :                                    NS_ConvertUTF16toUTF8(uniDesc).get());
     658             : 
     659           0 :     return aAtkObj->description;
     660             : }
     661             : 
     662             : AtkRole
     663           0 : getRoleCB(AtkObject *aAtkObj)
     664             : {
     665           0 :   if (aAtkObj->role != ATK_ROLE_INVALID)
     666           0 :     return aAtkObj->role;
     667             : 
     668           0 :   AccessibleOrProxy acc = GetInternalObj(aAtkObj);
     669           0 :   if (acc.IsNull()) {
     670           0 :     return ATK_ROLE_INVALID;
     671             :   }
     672             : 
     673             : #ifdef DEBUG
     674           0 :   if (AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj)) {
     675           0 :     NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(accWrap),
     676             :                  "Does not support Text interface when it should");
     677             :   }
     678             : #endif
     679             : 
     680             : #define ROLE(geckoRole, stringRole, atkRole, macRole, \
     681             :              msaaRole, ia2Role, nameRule) \
     682             :   case roles::geckoRole: \
     683             :     aAtkObj->role = atkRole; \
     684             :     break;
     685             : 
     686           0 :   switch (acc.Role()) {
     687             : #include "RoleMap.h"
     688             :     default:
     689           0 :       MOZ_CRASH("Unknown role.");
     690             :   }
     691             : 
     692             : #undef ROLE
     693             : 
     694           0 :   if (aAtkObj->role == ATK_ROLE_LIST_BOX && !IsAtkVersionAtLeast(2, 1))
     695           0 :     aAtkObj->role = ATK_ROLE_LIST;
     696           0 :   else if (aAtkObj->role == ATK_ROLE_TABLE_ROW && !IsAtkVersionAtLeast(2, 1))
     697           0 :     aAtkObj->role = ATK_ROLE_LIST_ITEM;
     698           0 :   else if (aAtkObj->role == ATK_ROLE_MATH && !IsAtkVersionAtLeast(2, 12))
     699           0 :     aAtkObj->role = ATK_ROLE_SECTION;
     700           0 :   else if (aAtkObj->role == ATK_ROLE_COMMENT && !IsAtkVersionAtLeast(2, 12))
     701           0 :     aAtkObj->role = ATK_ROLE_SECTION;
     702           0 :   else if (aAtkObj->role == ATK_ROLE_LANDMARK && !IsAtkVersionAtLeast(2, 12))
     703           0 :     aAtkObj->role = ATK_ROLE_SECTION;
     704           0 :   else if (aAtkObj->role == ATK_ROLE_FOOTNOTE && !IsAtkVersionAtLeast(2, 25, 2))
     705           0 :     aAtkObj->role = ATK_ROLE_SECTION;
     706           0 :   else if (aAtkObj->role == ATK_ROLE_STATIC && !IsAtkVersionAtLeast(2, 16))
     707           0 :     aAtkObj->role = ATK_ROLE_TEXT;
     708           0 :   else if ((aAtkObj->role == ATK_ROLE_MATH_FRACTION ||
     709           0 :             aAtkObj->role == ATK_ROLE_MATH_ROOT) && !IsAtkVersionAtLeast(2, 16))
     710           0 :     aAtkObj->role = ATK_ROLE_SECTION;
     711             : 
     712           0 :   return aAtkObj->role;
     713             : }
     714             : 
     715             : static AtkAttributeSet*
     716           0 : ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes)
     717             : {
     718           0 :     if (!aAttributes)
     719           0 :         return nullptr;
     720             : 
     721           0 :     AtkAttributeSet *objAttributeSet = nullptr;
     722           0 :     nsCOMPtr<nsISimpleEnumerator> propEnum;
     723           0 :     nsresult rv = aAttributes->Enumerate(getter_AddRefs(propEnum));
     724           0 :     NS_ENSURE_SUCCESS(rv, nullptr);
     725             : 
     726             :     bool hasMore;
     727           0 :     while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
     728           0 :         nsCOMPtr<nsISupports> sup;
     729           0 :         rv = propEnum->GetNext(getter_AddRefs(sup));
     730           0 :         NS_ENSURE_SUCCESS(rv, objAttributeSet);
     731             : 
     732           0 :         nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
     733           0 :         NS_ENSURE_TRUE(propElem, objAttributeSet);
     734             : 
     735           0 :         nsAutoCString name;
     736           0 :         rv = propElem->GetKey(name);
     737           0 :         NS_ENSURE_SUCCESS(rv, objAttributeSet);
     738             : 
     739           0 :         nsAutoString value;
     740           0 :         rv = propElem->GetValue(value);
     741           0 :         NS_ENSURE_SUCCESS(rv, objAttributeSet);
     742             : 
     743           0 :         AtkAttribute *objAttr = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
     744           0 :         objAttr->name = g_strdup(name.get());
     745           0 :         objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
     746           0 :         objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
     747             :     }
     748             : 
     749             :     //libspi will free it
     750           0 :     return objAttributeSet;
     751             : }
     752             : 
     753             : AtkAttributeSet*
     754           0 : GetAttributeSet(Accessible* aAccessible)
     755             : {
     756           0 :   nsCOMPtr<nsIPersistentProperties> attributes = aAccessible->Attributes();
     757           0 :   if (attributes)
     758           0 :     return ConvertToAtkAttributeSet(attributes);
     759             : 
     760           0 :   return nullptr;
     761             : }
     762             : 
     763             : AtkAttributeSet *
     764           0 : getAttributesCB(AtkObject *aAtkObj)
     765             : {
     766           0 :   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
     767           0 :   if (accWrap)
     768           0 :     return GetAttributeSet(accWrap);
     769             : 
     770           0 :   ProxyAccessible* proxy = GetProxy(aAtkObj);
     771           0 :   if (!proxy)
     772           0 :     return nullptr;
     773             : 
     774           0 :   AutoTArray<Attribute, 10> attrs;
     775           0 :   proxy->Attributes(&attrs);
     776           0 :   if (attrs.IsEmpty())
     777           0 :     return nullptr;
     778             : 
     779           0 :   AtkAttributeSet* objAttributeSet = nullptr;
     780           0 :   for (uint32_t i = 0; i < attrs.Length(); i++) {
     781           0 :     AtkAttribute *objAttr = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
     782           0 :     objAttr->name = g_strdup(attrs[i].Name().get());
     783           0 :     objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(attrs[i].Value()).get());
     784           0 :     objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
     785             :   }
     786             : 
     787           0 :   return objAttributeSet;
     788             : }
     789             : 
     790             : const gchar*
     791           0 : GetLocaleCB(AtkObject* aAtkObj)
     792             : {
     793           0 :   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
     794           0 :   if (!accWrap)
     795           0 :     return nullptr;
     796             : 
     797           0 :   nsAutoString locale;
     798           0 :   accWrap->Language(locale);
     799           0 :   return AccessibleWrap::ReturnString(locale);
     800             : }
     801             : 
     802             : AtkObject *
     803           0 : getParentCB(AtkObject *aAtkObj)
     804             : {
     805           0 :   if (aAtkObj->accessible_parent)
     806           0 :     return aAtkObj->accessible_parent;
     807             : 
     808           0 :   AccessibleOrProxy acc = GetInternalObj(aAtkObj);
     809           0 :   if (acc.IsNull()) {
     810           0 :     return nullptr;
     811             :   }
     812             : 
     813           0 :   AccessibleOrProxy parent = acc.Parent();
     814           0 :   AtkObject* atkParent = !parent.IsNull() ? GetWrapperFor(parent) : nullptr;
     815           0 :   if (atkParent)
     816           0 :     atk_object_set_parent(aAtkObj, atkParent);
     817             : 
     818           0 :   return aAtkObj->accessible_parent;
     819             : }
     820             : 
     821             : gint
     822           0 : getChildCountCB(AtkObject *aAtkObj)
     823             : {
     824           0 :   if (AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj)) {
     825           0 :     if (nsAccUtils::MustPrune(accWrap)) {
     826           0 :       return 0;
     827             :     }
     828             : 
     829           0 :     uint32_t count = accWrap->EmbeddedChildCount();
     830           0 :     if (count) {
     831           0 :       return static_cast<gint>(count);
     832             :     }
     833             : 
     834           0 :     OuterDocAccessible* outerDoc = accWrap->AsOuterDoc();
     835           0 :     if (outerDoc && outerDoc->RemoteChildDoc()) {
     836           0 :       return 1;
     837             :     }
     838             :   }
     839             : 
     840           0 :   ProxyAccessible* proxy = GetProxy(aAtkObj);
     841           0 :   if (proxy && !proxy->MustPruneChildren()) {
     842           0 :     return proxy->EmbeddedChildCount();
     843             :   }
     844             : 
     845           0 :   return 0;
     846             : }
     847             : 
     848             : AtkObject *
     849           0 : refChildCB(AtkObject *aAtkObj, gint aChildIndex)
     850             : {
     851             :   // aChildIndex should not be less than zero
     852           0 :   if (aChildIndex < 0) {
     853           0 :     return nullptr;
     854             :   }
     855             : 
     856           0 :   AtkObject* childAtkObj = nullptr;
     857           0 :   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
     858           0 :   if (accWrap) {
     859           0 :     if (nsAccUtils::MustPrune(accWrap)) {
     860           0 :       return nullptr;
     861             :     }
     862             : 
     863           0 :     Accessible* accChild = accWrap->GetEmbeddedChildAt(aChildIndex);
     864           0 :     if (accChild) {
     865           0 :       childAtkObj = AccessibleWrap::GetAtkObject(accChild);
     866             :     } else {
     867           0 :       OuterDocAccessible* docOwner = accWrap->AsOuterDoc();
     868           0 :       if (docOwner) {
     869           0 :         ProxyAccessible* proxyDoc = docOwner->RemoteChildDoc();
     870           0 :         if (proxyDoc)
     871           0 :           childAtkObj = GetWrapperFor(proxyDoc);
     872             :       }
     873             :     }
     874           0 :   } else if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
     875           0 :     if (proxy->MustPruneChildren())
     876           0 :       return nullptr;
     877             : 
     878           0 :     ProxyAccessible* child = proxy->EmbeddedChildAt(aChildIndex);
     879           0 :     if (child)
     880           0 :       childAtkObj = GetWrapperFor(child);
     881             :   } else {
     882           0 :     return nullptr;
     883             :   }
     884             : 
     885           0 :   NS_ASSERTION(childAtkObj, "Fail to get AtkObj");
     886           0 :   if (!childAtkObj)
     887           0 :     return nullptr;
     888             : 
     889           0 :   g_object_ref(childAtkObj);
     890             : 
     891           0 :   if (aAtkObj != childAtkObj->accessible_parent)
     892           0 :     atk_object_set_parent(childAtkObj, aAtkObj);
     893             : 
     894           0 :   return childAtkObj;
     895             : }
     896             : 
     897             : gint
     898           0 : getIndexInParentCB(AtkObject* aAtkObj)
     899             : {
     900             :   // We don't use Accessible::IndexInParent() because we don't include text
     901             :   // leaf nodes as children in ATK.
     902           0 :   if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
     903           0 :     if (ProxyAccessible* parent = proxy->Parent())
     904           0 :       return parent->IndexOfEmbeddedChild(proxy);
     905             : 
     906           0 :     if (proxy->OuterDocOfRemoteBrowser())
     907           0 :       return 0;
     908             : 
     909           0 :     return -1;
     910             :   }
     911             : 
     912           0 :     AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
     913           0 :     if (!accWrap) {
     914           0 :         return -1;
     915             :     }
     916             : 
     917           0 :     Accessible* parent = accWrap->Parent();
     918           0 :     if (!parent)
     919           0 :         return -1; // No parent
     920             : 
     921           0 :     return parent->GetIndexOfEmbeddedChild(accWrap);
     922             : }
     923             : 
     924             : static void
     925           0 : TranslateStates(uint64_t aState, AtkStateSet* aStateSet)
     926             : {
     927             :   // atk doesn't have a read only state so read only things shouldn't be
     928             :   // editable.
     929           0 :   if (aState & states::READONLY)
     930           0 :     aState &= ~states::EDITABLE;
     931             : 
     932             :   // Convert every state to an entry in AtkStateMap
     933           0 :   uint32_t stateIndex = 0;
     934           0 :   uint64_t bitMask = 1;
     935           0 :   while (gAtkStateMap[stateIndex].stateMapEntryType != kNoSuchState) {
     936           0 :     if (gAtkStateMap[stateIndex].atkState) { // There's potentially an ATK state for this
     937           0 :       bool isStateOn = (aState & bitMask) != 0;
     938           0 :       if (gAtkStateMap[stateIndex].stateMapEntryType == kMapOpposite) {
     939           0 :         isStateOn = !isStateOn;
     940             :       }
     941           0 :       if (isStateOn) {
     942           0 :         atk_state_set_add_state(aStateSet, gAtkStateMap[stateIndex].atkState);
     943             :       }
     944             :     }
     945           0 :     bitMask <<= 1;
     946           0 :     ++ stateIndex;
     947             :   }
     948           0 : }
     949             : 
     950             : AtkStateSet *
     951           0 : refStateSetCB(AtkObject *aAtkObj)
     952             : {
     953           0 :   AtkStateSet *state_set = nullptr;
     954           0 :   state_set = ATK_OBJECT_CLASS(parent_class)->ref_state_set(aAtkObj);
     955             : 
     956           0 :   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
     957           0 :   if (accWrap)
     958           0 :     TranslateStates(accWrap->State(), state_set);
     959           0 :   else if (ProxyAccessible* proxy = GetProxy(aAtkObj))
     960           0 :     TranslateStates(proxy->State(), state_set);
     961             :   else
     962           0 :     TranslateStates(states::DEFUNCT, state_set);
     963             : 
     964           0 :   return state_set;
     965             : }
     966             : 
     967             : static void
     968           0 : UpdateAtkRelation(RelationType aType, Accessible* aAcc,
     969             :                   AtkRelationType aAtkType, AtkRelationSet* aAtkSet)
     970             : {
     971           0 :   if (aAtkType == ATK_RELATION_NULL)
     972           0 :     return;
     973             : 
     974             :   AtkRelation* atkRelation =
     975           0 :     atk_relation_set_get_relation_by_type(aAtkSet, aAtkType);
     976           0 :   if (atkRelation)
     977           0 :     atk_relation_set_remove(aAtkSet, atkRelation);
     978             : 
     979           0 :   Relation rel(aAcc->RelationByType(aType));
     980           0 :   nsTArray<AtkObject*> targets;
     981           0 :   Accessible* tempAcc = nullptr;
     982           0 :   while ((tempAcc = rel.Next()))
     983           0 :     targets.AppendElement(AccessibleWrap::GetAtkObject(tempAcc));
     984             : 
     985           0 :   if (aType == RelationType::EMBEDS && aAcc->IsRoot()) {
     986           0 :     if (ProxyAccessible* proxyDoc =
     987           0 :         aAcc->AsRoot()->GetPrimaryRemoteTopLevelContentDoc()) {
     988           0 :       targets.AppendElement(GetWrapperFor(proxyDoc));
     989             :     }
     990             :   }
     991             : 
     992           0 :   if (targets.Length()) {
     993           0 :     atkRelation = atk_relation_new(targets.Elements(),
     994           0 :                                    targets.Length(), aAtkType);
     995           0 :     atk_relation_set_add(aAtkSet, atkRelation);
     996           0 :     g_object_unref(atkRelation);
     997             :   }
     998             : }
     999             : 
    1000             : AtkRelationSet *
    1001           0 : refRelationSetCB(AtkObject *aAtkObj)
    1002             : {
    1003             :   AtkRelationSet* relation_set =
    1004           0 :     ATK_OBJECT_CLASS(parent_class)->ref_relation_set(aAtkObj);
    1005             : 
    1006             :   const AtkRelationType typeMap[] = {
    1007             : #define RELATIONTYPE(gecko, s, atk, m, i) atk,
    1008             : #include "RelationTypeMap.h"
    1009             : #undef RELATIONTYPE
    1010           0 :   };
    1011             : 
    1012           0 :   if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
    1013           0 :     nsTArray<RelationType> types;
    1014           0 :     nsTArray<nsTArray<ProxyAccessible*>> targetSets;
    1015           0 :     proxy->Relations(&types, &targetSets);
    1016             : 
    1017           0 :     size_t relationCount = types.Length();
    1018           0 :     for (size_t i = 0; i < relationCount; i++) {
    1019           0 :       if (typeMap[static_cast<uint32_t>(types[i])] == ATK_RELATION_NULL)
    1020           0 :         continue;
    1021             : 
    1022           0 :       size_t targetCount = targetSets[i].Length();
    1023           0 :       AutoTArray<AtkObject*, 5> wrappers;
    1024           0 :       for (size_t j = 0; j < targetCount; j++)
    1025           0 :         wrappers.AppendElement(GetWrapperFor(targetSets[i][j]));
    1026             : 
    1027           0 :       AtkRelationType atkType = typeMap[static_cast<uint32_t>(types[i])];
    1028             :       AtkRelation* atkRelation =
    1029           0 :         atk_relation_set_get_relation_by_type(relation_set, atkType);
    1030           0 :       if (atkRelation)
    1031           0 :         atk_relation_set_remove(relation_set, atkRelation);
    1032             : 
    1033           0 :       atkRelation = atk_relation_new(wrappers.Elements(), wrappers.Length(),
    1034           0 :                                      atkType);
    1035           0 :       atk_relation_set_add(relation_set, atkRelation);
    1036           0 :       g_object_unref(atkRelation);
    1037             :     }
    1038             :   }
    1039             : 
    1040           0 :   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
    1041           0 :   if (!accWrap)
    1042           0 :     return relation_set;
    1043             : 
    1044             : #define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
    1045             :   UpdateAtkRelation(RelationType::geckoType, accWrap, atkType, relation_set);
    1046             : 
    1047             : #include "RelationTypeMap.h"
    1048             : 
    1049             : #undef RELATIONTYPE
    1050             : 
    1051           0 :   return relation_set;
    1052             : }
    1053             : 
    1054             : // Check if aAtkObj is a valid MaiAtkObject, and return the AccessibleWrap
    1055             : // for it.
    1056             : AccessibleWrap*
    1057           0 : GetAccessibleWrap(AtkObject* aAtkObj)
    1058             : {
    1059           0 :   bool isMAIObject = IS_MAI_OBJECT(aAtkObj);
    1060           0 :   NS_ENSURE_TRUE(isMAIObject || MAI_IS_ATK_SOCKET(aAtkObj),
    1061             :                  nullptr);
    1062             : 
    1063           0 :   AccessibleWrap* accWrap = nullptr;
    1064           0 :   if (isMAIObject) {
    1065           0 :     Accessible* acc = MAI_ATK_OBJECT(aAtkObj)->accWrap.AsAccessible();
    1066           0 :     accWrap = static_cast<AccessibleWrap*>(acc);
    1067             :   } else {
    1068           0 :     accWrap = MAI_ATK_SOCKET(aAtkObj)->accWrap;
    1069             :   }
    1070             : 
    1071             :   // Check if the accessible was deconstructed.
    1072           0 :   if (!accWrap)
    1073           0 :     return nullptr;
    1074             : 
    1075           0 :   NS_ENSURE_TRUE(accWrap->GetAtkObject() == aAtkObj, nullptr);
    1076             : 
    1077           0 :   AccessibleWrap* appAccWrap = ApplicationAcc();
    1078           0 :   if (appAccWrap != accWrap && !accWrap->IsValidObject())
    1079           0 :     return nullptr;
    1080             : 
    1081           0 :   return accWrap;
    1082             : }
    1083             : 
    1084             : ProxyAccessible*
    1085           0 : GetProxy(AtkObject* aObj)
    1086             : {
    1087           0 :   return GetInternalObj(aObj).AsProxy();
    1088             : }
    1089             : 
    1090             : AccessibleOrProxy
    1091           0 : GetInternalObj(AtkObject* aObj)
    1092             : {
    1093           0 :   if (!aObj || !IS_MAI_OBJECT(aObj))
    1094           0 :     return nullptr;
    1095             : 
    1096           0 :   return MAI_ATK_OBJECT(aObj)->accWrap;
    1097             : }
    1098             : 
    1099             : AtkObject*
    1100           0 : GetWrapperFor(ProxyAccessible* aProxy)
    1101             : {
    1102           0 :   return reinterpret_cast<AtkObject*>(aProxy->GetWrapper() & ~IS_PROXY);
    1103             : }
    1104             : 
    1105             : AtkObject*
    1106           0 : GetWrapperFor(AccessibleOrProxy aObj)
    1107             : {
    1108           0 :   if (aObj.IsProxy()) {
    1109           0 :     return GetWrapperFor(aObj.AsProxy());
    1110             :   }
    1111             : 
    1112           0 :   return AccessibleWrap::GetAtkObject(aObj.AsAccessible());
    1113             : }
    1114             : 
    1115             : static uint16_t
    1116           0 : GetInterfacesForProxy(ProxyAccessible* aProxy, uint32_t aInterfaces)
    1117             : {
    1118           0 :   uint16_t interfaces = 1 << MAI_INTERFACE_COMPONENT;
    1119           0 :   if (aInterfaces & Interfaces::HYPERTEXT)
    1120           0 :     interfaces |= (1 << MAI_INTERFACE_HYPERTEXT) | (1 << MAI_INTERFACE_TEXT)
    1121             :         | (1 << MAI_INTERFACE_EDITABLE_TEXT);
    1122             : 
    1123           0 :   if (aInterfaces & Interfaces::HYPERLINK)
    1124           0 :     interfaces |= 1 << MAI_INTERFACE_HYPERLINK_IMPL;
    1125             : 
    1126           0 :   if (aInterfaces & Interfaces::VALUE)
    1127           0 :     interfaces |= 1 << MAI_INTERFACE_VALUE;
    1128             : 
    1129           0 :   if (aInterfaces & Interfaces::TABLE)
    1130           0 :     interfaces |= 1 << MAI_INTERFACE_TABLE;
    1131             : 
    1132           0 :   if (aInterfaces & Interfaces::TABLECELL)
    1133           0 :     interfaces |= 1 << MAI_INTERFACE_TABLE_CELL;
    1134             : 
    1135           0 :   if (aInterfaces & Interfaces::IMAGE)
    1136           0 :     interfaces |= 1 << MAI_INTERFACE_IMAGE;
    1137             : 
    1138           0 :   if (aInterfaces & Interfaces::DOCUMENT)
    1139           0 :     interfaces |= 1 << MAI_INTERFACE_DOCUMENT;
    1140             : 
    1141           0 :   if (aInterfaces & Interfaces::SELECTION) {
    1142           0 :     interfaces |= 1 << MAI_INTERFACE_SELECTION;
    1143             :   }
    1144             : 
    1145           0 :   if (aInterfaces & Interfaces::ACTION) {
    1146           0 :     interfaces |= 1 << MAI_INTERFACE_ACTION;
    1147             :   }
    1148             : 
    1149           0 :   return interfaces;
    1150             : }
    1151             : 
    1152             : void
    1153           0 : a11y::ProxyCreated(ProxyAccessible* aProxy, uint32_t aInterfaces)
    1154             : {
    1155           0 :   GType type = GetMaiAtkType(GetInterfacesForProxy(aProxy, aInterfaces));
    1156           0 :   NS_ASSERTION(type, "why don't we have a type!");
    1157             : 
    1158             :   AtkObject* obj =
    1159             :     reinterpret_cast<AtkObject *>
    1160           0 :     (g_object_new(type, nullptr));
    1161           0 :   if (!obj)
    1162           0 :     return;
    1163             : 
    1164           0 :   uintptr_t inner = reinterpret_cast<uintptr_t>(aProxy) | IS_PROXY;
    1165           0 :   atk_object_initialize(obj, reinterpret_cast<gpointer>(inner));
    1166           0 :   obj->role = ATK_ROLE_INVALID;
    1167           0 :   obj->layer = ATK_LAYER_INVALID;
    1168           0 :   aProxy->SetWrapper(reinterpret_cast<uintptr_t>(obj) | IS_PROXY);
    1169             : }
    1170             : 
    1171             : void
    1172           0 : a11y::ProxyDestroyed(ProxyAccessible* aProxy)
    1173             : {
    1174           0 :   auto obj = reinterpret_cast<MaiAtkObject*>(aProxy->GetWrapper() & ~IS_PROXY);
    1175           0 :   if (!obj) {
    1176           0 :     return;
    1177             :   }
    1178             : 
    1179           0 :   obj->Shutdown();
    1180           0 :   g_object_unref(obj);
    1181           0 :   aProxy->SetWrapper(0);
    1182             : }
    1183             : 
    1184             : nsresult
    1185           0 : AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
    1186             : {
    1187           0 :   nsresult rv = Accessible::HandleAccEvent(aEvent);
    1188           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1189             : 
    1190           0 :   if (IPCAccessibilityActive()) {
    1191           0 :     return NS_OK;
    1192             :   }
    1193             : 
    1194           0 :     Accessible* accessible = aEvent->GetAccessible();
    1195           0 :     NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);
    1196             : 
    1197             :     // The accessible can become defunct if we have an xpcom event listener
    1198             :     // which decides it would be fun to change the DOM and flush layout.
    1199           0 :     if (accessible->IsDefunct())
    1200           0 :         return NS_OK;
    1201             : 
    1202           0 :     uint32_t type = aEvent->GetEventType();
    1203             : 
    1204           0 :     AtkObject* atkObj = AccessibleWrap::GetAtkObject(accessible);
    1205             : 
    1206             :   // We don't create ATK objects for plain text leaves, just return NS_OK in
    1207             :   // such case.
    1208           0 :     if (!atkObj) {
    1209           0 :         NS_ASSERTION(type == nsIAccessibleEvent::EVENT_SHOW ||
    1210             :                      type == nsIAccessibleEvent::EVENT_HIDE,
    1211             :                      "Event other than SHOW and HIDE fired for plain text leaves");
    1212           0 :         return NS_OK;
    1213             :     }
    1214             : 
    1215           0 :     AccessibleWrap* accWrap = GetAccessibleWrap(atkObj);
    1216           0 :     if (!accWrap) {
    1217           0 :         return NS_OK; // Node is shut down
    1218             :     }
    1219             : 
    1220           0 :     switch (type) {
    1221             :     case nsIAccessibleEvent::EVENT_STATE_CHANGE:
    1222             :       {
    1223           0 :         AccStateChangeEvent* event = downcast_accEvent(aEvent);
    1224           0 :         MAI_ATK_OBJECT(atkObj)->FireStateChangeEvent(event->GetState(),
    1225           0 :                                                      event->IsStateEnabled());
    1226           0 :         break;
    1227             :       }
    1228             : 
    1229             :     case nsIAccessibleEvent::EVENT_TEXT_REMOVED:
    1230             :     case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
    1231             :       {
    1232           0 :         AccTextChangeEvent* event = downcast_accEvent(aEvent);
    1233           0 :         NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
    1234             : 
    1235           0 :         MAI_ATK_OBJECT(atkObj)-> FireTextChangeEvent(event->ModifiedText(),
    1236             :                                                      event->GetStartOffset(),
    1237             :                                                      event->GetLength(),
    1238           0 :                                                      event->IsTextInserted(),
    1239           0 :                                                      event->IsFromUserInput());
    1240             : 
    1241           0 :         return NS_OK;
    1242             :       }
    1243             : 
    1244             :     case nsIAccessibleEvent::EVENT_FOCUS:
    1245             :       {
    1246           0 :         a11y::RootAccessible* rootAccWrap = accWrap->RootAccessible();
    1247           0 :         if (rootAccWrap && rootAccWrap->mActivated) {
    1248           0 :             atk_focus_tracker_notify(atkObj);
    1249             :             // Fire state change event for focus
    1250           0 :             atk_object_notify_state_change(atkObj, ATK_STATE_FOCUSED, true);
    1251           0 :             return NS_OK;
    1252             :         }
    1253           0 :       } break;
    1254             : 
    1255             :     case nsIAccessibleEvent::EVENT_NAME_CHANGE:
    1256             :       {
    1257           0 :         nsAutoString newName;
    1258           0 :         accessible->Name(newName);
    1259             : 
    1260           0 :         MaybeFireNameChange(atkObj, newName);
    1261             : 
    1262           0 :         break;
    1263             :       }
    1264             : 
    1265             :   case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
    1266             :   case nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE:
    1267           0 :     if (accessible->HasNumericValue()) {
    1268             :       // Make sure this is a numeric value. Don't fire for string value changes
    1269             :       // (e.g. text editing) ATK values are always numeric.
    1270           0 :       g_object_notify((GObject*)atkObj, "accessible-value");
    1271             :     }
    1272           0 :     break;
    1273             : 
    1274             :     case nsIAccessibleEvent::EVENT_SELECTION:
    1275             :     case nsIAccessibleEvent::EVENT_SELECTION_ADD:
    1276             :     case nsIAccessibleEvent::EVENT_SELECTION_REMOVE:
    1277             :     {
    1278             :       // XXX: dupe events may be fired
    1279           0 :       AccSelChangeEvent* selChangeEvent = downcast_accEvent(aEvent);
    1280           0 :       g_signal_emit_by_name(AccessibleWrap::GetAtkObject(selChangeEvent->Widget()),
    1281           0 :                             "selection_changed");
    1282           0 :       break;
    1283             :     }
    1284             : 
    1285             :     case nsIAccessibleEvent::EVENT_SELECTION_WITHIN:
    1286             :     {
    1287           0 :       g_signal_emit_by_name(atkObj, "selection_changed");
    1288           0 :       break;
    1289             :     }
    1290             : 
    1291             :     case nsIAccessibleEvent::EVENT_ALERT:
    1292             :       // A hack using state change showing events as alert events.
    1293           0 :       atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, true);
    1294           0 :       break;
    1295             : 
    1296             :     case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
    1297           0 :         g_signal_emit_by_name(atkObj, "text_selection_changed");
    1298           0 :         break;
    1299             : 
    1300             :     case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED:
    1301             :       {
    1302           0 :         AccCaretMoveEvent* caretMoveEvent = downcast_accEvent(aEvent);
    1303           0 :         NS_ASSERTION(caretMoveEvent, "Event needs event data");
    1304           0 :         if (!caretMoveEvent)
    1305           0 :             break;
    1306             : 
    1307           0 :         int32_t caretOffset = caretMoveEvent->GetCaretOffset();
    1308           0 :         g_signal_emit_by_name(atkObj, "text_caret_moved", caretOffset);
    1309           0 :       } break;
    1310             : 
    1311             :     case nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED:
    1312           0 :         g_signal_emit_by_name(atkObj, "text-attributes-changed");
    1313           0 :         break;
    1314             : 
    1315             :     case nsIAccessibleEvent::EVENT_TABLE_MODEL_CHANGED:
    1316           0 :         g_signal_emit_by_name(atkObj, "model_changed");
    1317           0 :         break;
    1318             : 
    1319             :     case nsIAccessibleEvent::EVENT_TABLE_ROW_INSERT:
    1320             :       {
    1321           0 :         AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
    1322           0 :         NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
    1323             : 
    1324           0 :         int32_t rowIndex = tableEvent->GetIndex();
    1325           0 :         int32_t numRows = tableEvent->GetCount();
    1326             : 
    1327           0 :         g_signal_emit_by_name(atkObj, "row_inserted", rowIndex, numRows);
    1328           0 :      } break;
    1329             : 
    1330             :    case nsIAccessibleEvent::EVENT_TABLE_ROW_DELETE:
    1331             :      {
    1332           0 :         AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
    1333           0 :         NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
    1334             : 
    1335           0 :         int32_t rowIndex = tableEvent->GetIndex();
    1336           0 :         int32_t numRows = tableEvent->GetCount();
    1337             : 
    1338           0 :         g_signal_emit_by_name(atkObj, "row_deleted", rowIndex, numRows);
    1339           0 :       } break;
    1340             : 
    1341             :     case nsIAccessibleEvent::EVENT_TABLE_ROW_REORDER:
    1342             :       {
    1343           0 :         g_signal_emit_by_name(atkObj, "row_reordered");
    1344           0 :         break;
    1345             :       }
    1346             : 
    1347             :     case nsIAccessibleEvent::EVENT_TABLE_COLUMN_INSERT:
    1348             :       {
    1349           0 :         AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
    1350           0 :         NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
    1351             : 
    1352           0 :         int32_t colIndex = tableEvent->GetIndex();
    1353           0 :         int32_t numCols = tableEvent->GetCount();
    1354           0 :         g_signal_emit_by_name(atkObj, "column_inserted", colIndex, numCols);
    1355           0 :       } break;
    1356             : 
    1357             :     case nsIAccessibleEvent::EVENT_TABLE_COLUMN_DELETE:
    1358             :       {
    1359           0 :         AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
    1360           0 :         NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
    1361             : 
    1362           0 :         int32_t colIndex = tableEvent->GetIndex();
    1363           0 :         int32_t numCols = tableEvent->GetCount();
    1364           0 :         g_signal_emit_by_name(atkObj, "column_deleted", colIndex, numCols);
    1365           0 :       } break;
    1366             : 
    1367             :     case nsIAccessibleEvent::EVENT_TABLE_COLUMN_REORDER:
    1368           0 :         g_signal_emit_by_name(atkObj, "column_reordered");
    1369           0 :         break;
    1370             : 
    1371             :     case nsIAccessibleEvent::EVENT_SECTION_CHANGED:
    1372           0 :         g_signal_emit_by_name(atkObj, "visible_data_changed");
    1373           0 :         break;
    1374             : 
    1375             :     case nsIAccessibleEvent::EVENT_SHOW:
    1376             :       {
    1377           0 :         AccMutationEvent* event = downcast_accEvent(aEvent);
    1378           0 :         Accessible* parentAcc = event ? event->Parent() : accessible->Parent();
    1379           0 :         AtkObject* parent = AccessibleWrap::GetAtkObject(parentAcc);
    1380           0 :         NS_ENSURE_STATE(parent);
    1381           0 :         auto obj = reinterpret_cast<MaiAtkObject*>(atkObj);
    1382           0 :         obj->FireAtkShowHideEvent(parent, true, aEvent->IsFromUserInput());
    1383           0 :         return NS_OK;
    1384             :       }
    1385             : 
    1386             :     case nsIAccessibleEvent::EVENT_HIDE:
    1387             :       {
    1388             :         // XXX - Handle native dialog accessibles.
    1389           0 :         if (!accessible->IsRoot() && accessible->HasARIARole() &&
    1390           0 :             accessible->ARIARole() == roles::DIALOG) {
    1391           0 :           guint id = g_signal_lookup("deactivate", MAI_TYPE_ATK_OBJECT);
    1392           0 :           g_signal_emit(atkObj, id, 0);
    1393             :         }
    1394             : 
    1395           0 :         AccMutationEvent* event = downcast_accEvent(aEvent);
    1396           0 :         Accessible* parentAcc = event ? event->Parent() : accessible->Parent();
    1397           0 :         AtkObject* parent = AccessibleWrap::GetAtkObject(parentAcc);
    1398           0 :         NS_ENSURE_STATE(parent);
    1399           0 :         auto obj = reinterpret_cast<MaiAtkObject*>(atkObj);
    1400           0 :         obj->FireAtkShowHideEvent(parent, false, aEvent->IsFromUserInput());
    1401           0 :         return NS_OK;
    1402             :       }
    1403             : 
    1404             :         /*
    1405             :          * Because dealing with menu is very different between nsIAccessible
    1406             :          * and ATK, and the menu activity is important, specially transfer the
    1407             :          * following two event.
    1408             :          * Need more verification by AT test.
    1409             :          */
    1410             :     case nsIAccessibleEvent::EVENT_MENU_START:
    1411             :     case nsIAccessibleEvent::EVENT_MENU_END:
    1412           0 :         break;
    1413             : 
    1414             :     case nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE:
    1415             :       {
    1416           0 :         accessible->AsRoot()->mActivated = true;
    1417           0 :         guint id = g_signal_lookup("activate", MAI_TYPE_ATK_OBJECT);
    1418           0 :         g_signal_emit(atkObj, id, 0);
    1419             : 
    1420             :         // Always fire a current focus event after activation.
    1421           0 :         FocusMgr()->ForceFocusEvent();
    1422           0 :       } break;
    1423             : 
    1424             :     case nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE:
    1425             :       {
    1426           0 :         accessible->AsRoot()->mActivated = false;
    1427           0 :         guint id = g_signal_lookup("deactivate", MAI_TYPE_ATK_OBJECT);
    1428           0 :         g_signal_emit(atkObj, id, 0);
    1429           0 :       } break;
    1430             : 
    1431             :     case nsIAccessibleEvent::EVENT_WINDOW_MAXIMIZE:
    1432             :       {
    1433           0 :         guint id = g_signal_lookup("maximize", MAI_TYPE_ATK_OBJECT);
    1434           0 :         g_signal_emit(atkObj, id, 0);
    1435           0 :       } break;
    1436             : 
    1437             :     case nsIAccessibleEvent::EVENT_WINDOW_MINIMIZE:
    1438             :       {
    1439           0 :         guint id = g_signal_lookup("minimize", MAI_TYPE_ATK_OBJECT);
    1440           0 :         g_signal_emit(atkObj, id, 0);
    1441           0 :       } break;
    1442             : 
    1443             :     case nsIAccessibleEvent::EVENT_WINDOW_RESTORE:
    1444             :       {
    1445           0 :         guint id = g_signal_lookup("restore", MAI_TYPE_ATK_OBJECT);
    1446           0 :         g_signal_emit(atkObj, id, 0);
    1447           0 :       } break;
    1448             : 
    1449             :     case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
    1450           0 :         g_signal_emit_by_name (atkObj, "load_complete");
    1451             :         // XXX - Handle native dialog accessibles.
    1452           0 :         if (!accessible->IsRoot() && accessible->HasARIARole() &&
    1453           0 :             accessible->ARIARole() == roles::DIALOG) {
    1454           0 :           guint id = g_signal_lookup("activate", MAI_TYPE_ATK_OBJECT);
    1455           0 :           g_signal_emit(atkObj, id, 0);
    1456             :         }
    1457           0 :       break;
    1458             : 
    1459             :     case nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD:
    1460           0 :         g_signal_emit_by_name (atkObj, "reload");
    1461           0 :       break;
    1462             : 
    1463             :     case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED:
    1464           0 :         g_signal_emit_by_name (atkObj, "load_stopped");
    1465           0 :       break;
    1466             : 
    1467             :     case nsIAccessibleEvent::EVENT_MENUPOPUP_START:
    1468           0 :         atk_focus_tracker_notify(atkObj); // fire extra focus event
    1469           0 :         atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, true);
    1470           0 :         atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, true);
    1471           0 :         break;
    1472             : 
    1473             :     case nsIAccessibleEvent::EVENT_MENUPOPUP_END:
    1474           0 :         atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, false);
    1475           0 :         atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, false);
    1476           0 :         break;
    1477             :     }
    1478             : 
    1479           0 :     return NS_OK;
    1480             : }
    1481             : 
    1482             : void
    1483           0 : a11y::ProxyEvent(ProxyAccessible* aTarget, uint32_t aEventType)
    1484             : {
    1485           0 :   AtkObject* wrapper = GetWrapperFor(aTarget);
    1486             : 
    1487           0 :   switch (aEventType) {
    1488             :   case nsIAccessibleEvent::EVENT_FOCUS:
    1489           0 :     atk_focus_tracker_notify(wrapper);
    1490           0 :     atk_object_notify_state_change(wrapper, ATK_STATE_FOCUSED, true);
    1491           0 :     break;
    1492             :   case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
    1493           0 :     g_signal_emit_by_name(wrapper, "load_complete");
    1494           0 :     break;
    1495             :   case nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD:
    1496           0 :     g_signal_emit_by_name(wrapper, "reload");
    1497           0 :     break;
    1498             :   case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED:
    1499           0 :     g_signal_emit_by_name(wrapper, "load_stopped");
    1500           0 :     break;
    1501             :   case nsIAccessibleEvent::EVENT_MENUPOPUP_START:
    1502           0 :     atk_focus_tracker_notify(wrapper); // fire extra focus event
    1503           0 :     atk_object_notify_state_change(wrapper, ATK_STATE_VISIBLE, true);
    1504           0 :     atk_object_notify_state_change(wrapper, ATK_STATE_SHOWING, true);
    1505           0 :     break;
    1506             :   case nsIAccessibleEvent::EVENT_MENUPOPUP_END:
    1507           0 :     atk_object_notify_state_change(wrapper, ATK_STATE_VISIBLE, false);
    1508           0 :     atk_object_notify_state_change(wrapper, ATK_STATE_SHOWING, false);
    1509           0 :     break;
    1510             :   case nsIAccessibleEvent::EVENT_ALERT:
    1511             :     // A hack using state change showing events as alert events.
    1512           0 :     atk_object_notify_state_change(wrapper, ATK_STATE_SHOWING, true);
    1513           0 :     break;
    1514             :   case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
    1515           0 :     g_object_notify((GObject*)wrapper, "accessible-value");
    1516           0 :     break;
    1517             :   case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
    1518             :   case nsIAccessibleEvent::EVENT_SELECTION_WITHIN:
    1519           0 :     g_signal_emit_by_name(wrapper, "selection_changed");
    1520           0 :     break;
    1521             :   }
    1522           0 : }
    1523             : 
    1524             : void
    1525           0 : a11y::ProxyStateChangeEvent(ProxyAccessible* aTarget, uint64_t aState,
    1526             :                             bool aEnabled)
    1527             : {
    1528           0 :   MaiAtkObject* atkObj = MAI_ATK_OBJECT(GetWrapperFor(aTarget));
    1529           0 :   atkObj->FireStateChangeEvent(aState, aEnabled);
    1530           0 : }
    1531             : 
    1532             : void
    1533           0 : a11y::ProxyCaretMoveEvent(ProxyAccessible* aTarget, int32_t aOffset)
    1534             : {
    1535           0 :   AtkObject* wrapper = GetWrapperFor(aTarget);
    1536           0 :   g_signal_emit_by_name(wrapper, "text_caret_moved", aOffset);
    1537           0 : }
    1538             : 
    1539             : void
    1540           0 : MaiAtkObject::FireStateChangeEvent(uint64_t aState, bool aEnabled)
    1541             : {
    1542           0 :     int32_t stateIndex = AtkStateMap::GetStateIndexFor(aState);
    1543           0 :     if (stateIndex >= 0) {
    1544           0 :         NS_ASSERTION(gAtkStateMap[stateIndex].stateMapEntryType != kNoSuchState,
    1545             :                      "No such state");
    1546             : 
    1547           0 :         if (gAtkStateMap[stateIndex].atkState != kNone) {
    1548           0 :             NS_ASSERTION(gAtkStateMap[stateIndex].stateMapEntryType != kNoStateChange,
    1549             :                          "State changes should not fired for this state");
    1550             : 
    1551           0 :             if (gAtkStateMap[stateIndex].stateMapEntryType == kMapOpposite)
    1552           0 :                 aEnabled = !aEnabled;
    1553             : 
    1554             :             // Fire state change for first state if there is one to map
    1555           0 :             atk_object_notify_state_change(&parent,
    1556           0 :                                            gAtkStateMap[stateIndex].atkState,
    1557           0 :                                            aEnabled);
    1558             :         }
    1559             :     }
    1560           0 : }
    1561             : 
    1562             : void
    1563           0 : a11y::ProxyTextChangeEvent(ProxyAccessible* aTarget, const nsString& aStr,
    1564             :                            int32_t aStart, uint32_t aLen, bool aIsInsert,
    1565             :                            bool aFromUser)
    1566             : {
    1567           0 :   MaiAtkObject* atkObj = MAI_ATK_OBJECT(GetWrapperFor(aTarget));
    1568           0 :   atkObj->FireTextChangeEvent(aStr, aStart, aLen, aIsInsert, aFromUser);
    1569           0 : }
    1570             : 
    1571             : #define OLD_TEXT_INSERTED "text_changed::insert"
    1572             : #define OLD_TEXT_REMOVED "text_changed::delete"
    1573             : static const char* oldTextChangeStrings[2][2] = {
    1574             :   { OLD_TEXT_REMOVED NON_USER_EVENT, OLD_TEXT_INSERTED NON_USER_EVENT },
    1575             :   { OLD_TEXT_REMOVED, OLD_TEXT_INSERTED }
    1576             : };
    1577             : 
    1578             : #define TEXT_INSERTED "text-insert"
    1579             : #define TEXT_REMOVED "text-remove"
    1580             : #define NON_USER_DETAIL "::system"
    1581             : static const char* textChangedStrings[2][2] = {
    1582             :   { TEXT_REMOVED NON_USER_DETAIL, TEXT_INSERTED NON_USER_DETAIL },
    1583             :   { TEXT_REMOVED, TEXT_INSERTED}
    1584             : };
    1585             : 
    1586             : void
    1587           0 : MaiAtkObject::FireTextChangeEvent(const nsString& aStr, int32_t aStart,
    1588             :                                   uint32_t aLen, bool aIsInsert,
    1589             :                                   bool aFromUser)
    1590             : {
    1591           0 :   if (gAvailableAtkSignals == eUnknown)
    1592           0 :     gAvailableAtkSignals =
    1593           0 :       g_signal_lookup("text-insert", G_OBJECT_TYPE(this)) ?
    1594             :         eHaveNewAtkTextSignals : eNoNewAtkSignals;
    1595             : 
    1596           0 :   if (gAvailableAtkSignals == eNoNewAtkSignals) {
    1597             :     // XXX remove this code and the gHaveNewTextSignals check when we can
    1598             :     // stop supporting old atk since it doesn't really work anyway
    1599             :     // see bug 619002
    1600             :     const char* signal_name =
    1601           0 :       oldTextChangeStrings[aFromUser][aIsInsert];
    1602           0 :     g_signal_emit_by_name(this, signal_name, aStart, aLen);
    1603             :   } else {
    1604             :     const char* signal_name =
    1605           0 :       textChangedStrings[aFromUser][aIsInsert];
    1606           0 :     g_signal_emit_by_name(this, signal_name, aStart, aLen,
    1607           0 :                           NS_ConvertUTF16toUTF8(aStr).get());
    1608             :   }
    1609           0 : }
    1610             : 
    1611             : void
    1612           0 : a11y::ProxyShowHideEvent(ProxyAccessible* aTarget, ProxyAccessible* aParent,
    1613             :                          bool aInsert, bool aFromUser)
    1614             : {
    1615           0 :   MaiAtkObject* obj = MAI_ATK_OBJECT(GetWrapperFor(aTarget));
    1616           0 :   obj->FireAtkShowHideEvent(GetWrapperFor(aParent), aInsert, aFromUser);
    1617           0 : }
    1618             : 
    1619             : #define ADD_EVENT "children_changed::add"
    1620             : #define HIDE_EVENT "children_changed::remove"
    1621             : 
    1622             : static const char *kMutationStrings[2][2] = {
    1623             :   { HIDE_EVENT NON_USER_EVENT, ADD_EVENT NON_USER_EVENT },
    1624             :   { HIDE_EVENT, ADD_EVENT },
    1625             : };
    1626             : 
    1627             : void
    1628           0 : MaiAtkObject::FireAtkShowHideEvent(AtkObject* aParent, bool aIsAdded,
    1629             :                                    bool aFromUser)
    1630             : {
    1631           0 :     int32_t indexInParent = getIndexInParentCB(&this->parent);
    1632           0 :     const char *signal_name = kMutationStrings[aFromUser][aIsAdded];
    1633           0 :     g_signal_emit_by_name(aParent, signal_name, indexInParent, this, nullptr);
    1634           0 : }
    1635             : 
    1636             : void
    1637           0 : a11y::ProxySelectionEvent(ProxyAccessible*, ProxyAccessible* aWidget, uint32_t)
    1638             : {
    1639           0 :   MaiAtkObject* obj = MAI_ATK_OBJECT(GetWrapperFor(aWidget));
    1640           0 :     g_signal_emit_by_name(obj, "selection_changed");
    1641           0 : }
    1642             : 
    1643             : // static
    1644             : void
    1645           0 : AccessibleWrap::GetKeyBinding(Accessible* aAccessible, nsAString& aResult)
    1646             : {
    1647             :   // Return all key bindings including access key and keyboard shortcut.
    1648             : 
    1649             :   // Get access key.
    1650           0 :   nsAutoString keyBindingsStr;
    1651           0 :   KeyBinding keyBinding = aAccessible->AccessKey();
    1652           0 :   if (!keyBinding.IsEmpty()) {
    1653           0 :     keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat);
    1654             : 
    1655           0 :     Accessible* parent = aAccessible->Parent();
    1656           0 :     roles::Role role = parent ? parent->Role() : roles::NOTHING;
    1657           0 :     if (role == roles::PARENT_MENUITEM || role == roles::MENUITEM ||
    1658           0 :         role == roles::RADIO_MENU_ITEM || role == roles::CHECK_MENU_ITEM) {
    1659             :       // It is submenu, expose keyboard shortcuts from menu hierarchy like
    1660             :       // "s;<Alt>f:s"
    1661           0 :       nsAutoString keysInHierarchyStr = keyBindingsStr;
    1662           0 :       do {
    1663           0 :         KeyBinding parentKeyBinding = parent->AccessKey();
    1664           0 :         if (!parentKeyBinding.IsEmpty()) {
    1665           0 :           nsAutoString str;
    1666           0 :           parentKeyBinding.ToString(str, KeyBinding::eAtkFormat);
    1667           0 :           str.Append(':');
    1668             : 
    1669           0 :           keysInHierarchyStr.Insert(str, 0);
    1670             :         }
    1671           0 :       } while ((parent = parent->Parent()) && parent->Role() != roles::MENUBAR);
    1672             : 
    1673           0 :       keyBindingsStr.Append(';');
    1674           0 :       keyBindingsStr.Append(keysInHierarchyStr);
    1675             :     }
    1676             :   } else {
    1677             :     // No access key, add ';' to point this.
    1678           0 :     keyBindingsStr.Append(';');
    1679             :   }
    1680             : 
    1681             :   // Get keyboard shortcut.
    1682           0 :   keyBindingsStr.Append(';');
    1683           0 :   keyBinding = aAccessible->KeyboardShortcut();
    1684           0 :   if (!keyBinding.IsEmpty()) {
    1685           0 :     keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat);
    1686             :   }
    1687           0 :   aResult = keyBindingsStr;
    1688           0 : }
    1689             : 
    1690             : // static
    1691             : Accessible*
    1692           0 : AccessibleWrap::GetColumnHeader(TableAccessible* aAccessible, int32_t aColIdx)
    1693             : {
    1694           0 :   if (!aAccessible) {
    1695           0 :     return nullptr;
    1696             :   }
    1697             : 
    1698           0 :   Accessible* cell = aAccessible->CellAt(0, aColIdx);
    1699           0 :   if (!cell) {
    1700           0 :     return nullptr;
    1701             :   }
    1702             : 
    1703             :   // If the cell at the first row is column header then assume it is column
    1704             :   // header for all rows,
    1705           0 :   if (cell->Role() == roles::COLUMNHEADER) {
    1706           0 :     return cell;
    1707             :   }
    1708             : 
    1709             :   // otherwise get column header for the data cell at the first row.
    1710           0 :   TableCellAccessible* tableCell = cell->AsTableCell();
    1711           0 :   if (!tableCell) {
    1712           0 :     return nullptr;
    1713             :   }
    1714             : 
    1715           0 :   AutoTArray<Accessible*, 10> headerCells;
    1716           0 :   tableCell->ColHeaderCells(&headerCells);
    1717           0 :   if (headerCells.IsEmpty()) {
    1718           0 :     return nullptr;
    1719             :   }
    1720             : 
    1721           0 :   return headerCells[0];
    1722             : }
    1723             : 
    1724             : // static
    1725             : Accessible*
    1726           0 : AccessibleWrap::GetRowHeader(TableAccessible* aAccessible, int32_t aRowIdx)
    1727             : {
    1728           0 :   if (!aAccessible) {
    1729           0 :     return nullptr;
    1730             :   }
    1731             : 
    1732           0 :   Accessible* cell = aAccessible->CellAt(aRowIdx, 0);
    1733           0 :   if (!cell) {
    1734           0 :     return nullptr;
    1735             :   }
    1736             : 
    1737             :   // If the cell at the first column is row header then assume it is row
    1738             :   // header for all columns,
    1739           0 :   if (cell->Role() == roles::ROWHEADER) {
    1740           0 :     return cell;
    1741             :   }
    1742             : 
    1743             :   // otherwise get row header for the data cell at the first column.
    1744           0 :   TableCellAccessible* tableCell = cell->AsTableCell();
    1745           0 :   if (!tableCell) {
    1746           0 :     return nullptr;
    1747             :   }
    1748             : 
    1749           0 :   AutoTArray<Accessible*, 10> headerCells;
    1750           0 :   tableCell->RowHeaderCells(&headerCells);
    1751           0 :   if (headerCells.IsEmpty()) {
    1752           0 :     return nullptr;
    1753             :   }
    1754             : 
    1755           0 :   return headerCells[0];
    1756             : }

Generated by: LCOV version 1.13