accessible/src/atk/AccessibleWrap.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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/. */
     7 #include "AccessibleWrap.h"
     9 #include "Accessible-inl.h"
    10 #include "ApplicationAccessibleWrap.h"
    11 #include "InterfaceInitFuncs.h"
    12 #include "nsAccUtils.h"
    13 #include "nsIAccessibleRelation.h"
    14 #include "nsIAccessibleTable.h"
    15 #include "RootAccessible.h"
    16 #include "nsIAccessibleValue.h"
    17 #include "nsMai.h"
    18 #include "nsMaiHyperlink.h"
    19 #include "nsString.h"
    20 #include "nsAutoPtr.h"
    21 #include "prprf.h"
    22 #include "nsStateMap.h"
    23 #include "Relation.h"
    24 #include "RootAccessible.h"
    25 #include "States.h"
    26 #include "nsISimpleEnumerator.h"
    28 #include "mozilla/ArrayUtils.h"
    29 #include "nsXPCOMStrings.h"
    30 #include "nsComponentManagerUtils.h"
    31 #include "nsIPersistentProperties2.h"
    33 using namespace mozilla;
    34 using namespace mozilla::a11y;
    36 AccessibleWrap::EAvailableAtkSignals AccessibleWrap::gAvailableAtkSignals =
    37   eUnknown;
    39 //defined in ApplicationAccessibleWrap.cpp
    40 extern "C" GType g_atk_hyperlink_impl_type;
    42 /* MaiAtkObject */
    44 enum {
    45   ACTIVATE,
    46   CREATE,
    47   DEACTIVATE,
    48   DESTROY,
    49   MAXIMIZE,
    50   MINIMIZE,
    51   RESIZE,
    52   RESTORE,
    53   LAST_SIGNAL
    54 };
    56 enum MaiInterfaceType {
    57     MAI_INTERFACE_COMPONENT, /* 0 */
    58     MAI_INTERFACE_ACTION,
    59     MAI_INTERFACE_VALUE,
    60     MAI_INTERFACE_EDITABLE_TEXT,
    61     MAI_INTERFACE_HYPERTEXT,
    62     MAI_INTERFACE_HYPERLINK_IMPL,
    63     MAI_INTERFACE_SELECTION,
    64     MAI_INTERFACE_TABLE,
    65     MAI_INTERFACE_TEXT,
    66     MAI_INTERFACE_DOCUMENT, 
    67     MAI_INTERFACE_IMAGE /* 10 */
    68 };
    70 static GType GetAtkTypeForMai(MaiInterfaceType type)
    71 {
    72   switch (type) {
    73     case MAI_INTERFACE_COMPONENT:
    74       return ATK_TYPE_COMPONENT;
    75     case MAI_INTERFACE_ACTION:
    76       return ATK_TYPE_ACTION;
    77     case MAI_INTERFACE_VALUE:
    78       return ATK_TYPE_VALUE;
    79     case MAI_INTERFACE_EDITABLE_TEXT:
    80       return ATK_TYPE_EDITABLE_TEXT;
    81     case MAI_INTERFACE_HYPERTEXT:
    82       return ATK_TYPE_HYPERTEXT;
    83     case MAI_INTERFACE_HYPERLINK_IMPL:
    84        return g_atk_hyperlink_impl_type;
    85     case MAI_INTERFACE_SELECTION:
    86       return ATK_TYPE_SELECTION;
    87     case MAI_INTERFACE_TABLE:
    88       return ATK_TYPE_TABLE;
    89     case MAI_INTERFACE_TEXT:
    90       return ATK_TYPE_TEXT;
    91     case MAI_INTERFACE_DOCUMENT:
    92       return ATK_TYPE_DOCUMENT;
    93     case MAI_INTERFACE_IMAGE:
    94       return ATK_TYPE_IMAGE;
    95   }
    96   return G_TYPE_INVALID;
    97 }
    99 static const char* kNonUserInputEvent = ":system";
   101 static const GInterfaceInfo atk_if_infos[] = {
   102     {(GInterfaceInitFunc)componentInterfaceInitCB,
   103      (GInterfaceFinalizeFunc) nullptr, nullptr}, 
   104     {(GInterfaceInitFunc)actionInterfaceInitCB,
   105      (GInterfaceFinalizeFunc) nullptr, nullptr},
   106     {(GInterfaceInitFunc)valueInterfaceInitCB,
   107      (GInterfaceFinalizeFunc) nullptr, nullptr},
   108     {(GInterfaceInitFunc)editableTextInterfaceInitCB,
   109      (GInterfaceFinalizeFunc) nullptr, nullptr},
   110     {(GInterfaceInitFunc)hypertextInterfaceInitCB,
   111      (GInterfaceFinalizeFunc) nullptr, nullptr},
   112     {(GInterfaceInitFunc)hyperlinkImplInterfaceInitCB,
   113      (GInterfaceFinalizeFunc) nullptr, nullptr},
   114     {(GInterfaceInitFunc)selectionInterfaceInitCB,
   115      (GInterfaceFinalizeFunc) nullptr, nullptr},
   116     {(GInterfaceInitFunc)tableInterfaceInitCB,
   117      (GInterfaceFinalizeFunc) nullptr, nullptr},
   118     {(GInterfaceInitFunc)textInterfaceInitCB,
   119      (GInterfaceFinalizeFunc) nullptr, nullptr},
   120     {(GInterfaceInitFunc)documentInterfaceInitCB,
   121      (GInterfaceFinalizeFunc) nullptr, nullptr},
   122     {(GInterfaceInitFunc)imageInterfaceInitCB,
   123      (GInterfaceFinalizeFunc) nullptr, nullptr}
   124 };
   126 /**
   127  * This MaiAtkObject is a thin wrapper, in the MAI namespace, for AtkObject
   128  */
   129 struct MaiAtkObject
   130 {
   131   AtkObject parent;
   132   /*
   133    * The AccessibleWrap whose properties and features are exported
   134    * via this object instance.
   135    */
   136   AccessibleWrap* accWrap;
   137 };
   139 struct MaiAtkObjectClass
   140 {
   141     AtkObjectClass parent_class;
   142 };
   144 static guint mai_atk_object_signals [LAST_SIGNAL] = { 0, };
   146 static void MaybeFireNameChange(AtkObject* aAtkObj, const nsString& aNewName);
   148 G_BEGIN_DECLS
   149 /* callbacks for MaiAtkObject */
   150 static void classInitCB(AtkObjectClass *aClass);
   151 static void initializeCB(AtkObject *aAtkObj, gpointer aData);
   152 static void finalizeCB(GObject *aObj);
   154 /* callbacks for AtkObject virtual functions */
   155 static const gchar*        getNameCB (AtkObject *aAtkObj);
   156 /* getDescriptionCB is also used by image interface */
   157        const gchar*        getDescriptionCB (AtkObject *aAtkObj);
   158 static AtkRole             getRoleCB(AtkObject *aAtkObj);
   159 static AtkAttributeSet*    getAttributesCB(AtkObject *aAtkObj);
   160 static const gchar* GetLocaleCB(AtkObject*);
   161 static AtkObject*          getParentCB(AtkObject *aAtkObj);
   162 static gint                getChildCountCB(AtkObject *aAtkObj);
   163 static AtkObject*          refChildCB(AtkObject *aAtkObj, gint aChildIndex);
   164 static gint                getIndexInParentCB(AtkObject *aAtkObj);
   165 static AtkStateSet*        refStateSetCB(AtkObject *aAtkObj);
   166 static AtkRelationSet*     refRelationSetCB(AtkObject *aAtkObj);
   168 /* the missing atkobject virtual functions */
   169 /*
   170   static AtkLayer            getLayerCB(AtkObject *aAtkObj);
   171   static gint                getMdiZorderCB(AtkObject *aAtkObj);
   172   static void                SetNameCB(AtkObject *aAtkObj,
   173   const gchar *name);
   174   static void                SetDescriptionCB(AtkObject *aAtkObj,
   175   const gchar *description);
   176   static void                SetParentCB(AtkObject *aAtkObj,
   177   AtkObject *parent);
   178   static void                SetRoleCB(AtkObject *aAtkObj,
   179   AtkRole role);
   180   static guint               ConnectPropertyChangeHandlerCB(
   181   AtkObject  *aObj,
   182   AtkPropertyChangeHandler *handler);
   183   static void                RemovePropertyChangeHandlerCB(
   184   AtkObject *aAtkObj,
   185   guint handler_id);
   186   static void                InitializeCB(AtkObject *aAtkObj,
   187   gpointer data);
   188   static void                ChildrenChangedCB(AtkObject *aAtkObj,
   189   guint change_index,
   190   gpointer changed_child);
   191   static void                FocusEventCB(AtkObject *aAtkObj,
   192   gboolean focus_in);
   193   static void                PropertyChangeCB(AtkObject *aAtkObj,
   194   AtkPropertyValues *values);
   195   static void                StateChangeCB(AtkObject *aAtkObj,
   196   const gchar *name,
   197   gboolean state_set);
   198   static void                VisibleDataChangedCB(AtkObject *aAtkObj);
   199 */
   200 G_END_DECLS
   202 static GType GetMaiAtkType(uint16_t interfacesBits);
   203 static const char * GetUniqueMaiAtkTypeName(uint16_t interfacesBits);
   205 static gpointer parent_class = nullptr;
   207 static GQuark quark_mai_hyperlink = 0;
   209 GType
   210 mai_atk_object_get_type(void)
   211 {
   212     static GType type = 0;
   214     if (!type) {
   215         static const GTypeInfo tinfo = {
   216             sizeof(MaiAtkObjectClass),
   217             (GBaseInitFunc)nullptr,
   218             (GBaseFinalizeFunc)nullptr,
   219             (GClassInitFunc)classInitCB,
   220             (GClassFinalizeFunc)nullptr,
   221             nullptr, /* class data */
   222             sizeof(MaiAtkObject), /* instance size */
   223             0, /* nb preallocs */
   224             (GInstanceInitFunc)nullptr,
   225             nullptr /* value table */
   226         };
   228         type = g_type_register_static(ATK_TYPE_OBJECT,
   229                                       "MaiAtkObject", &tinfo, GTypeFlags(0));
   230         quark_mai_hyperlink = g_quark_from_static_string("MaiHyperlink");
   231     }
   232     return type;
   233 }
   235 AccessibleWrap::
   236   AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
   237   Accessible(aContent, aDoc), mAtkObject(nullptr)
   238 {
   239 }
   241 AccessibleWrap::~AccessibleWrap()
   242 {
   243     NS_ASSERTION(!mAtkObject, "ShutdownAtkObject() is not called");
   244 }
   246 void
   247 AccessibleWrap::ShutdownAtkObject()
   248 {
   249     if (mAtkObject) {
   250         if (IS_MAI_OBJECT(mAtkObject)) {
   251             MAI_ATK_OBJECT(mAtkObject)->accWrap = nullptr;
   252         }
   253         SetMaiHyperlink(nullptr);
   254         g_object_unref(mAtkObject);
   255         mAtkObject = nullptr;
   256     }
   257 }
   259 void
   260 AccessibleWrap::Shutdown()
   261 {
   262   ShutdownAtkObject();
   263   Accessible::Shutdown();
   264 }
   266 MaiHyperlink*
   267 AccessibleWrap::GetMaiHyperlink(bool aCreate /* = true */)
   268 {
   269     // make sure mAtkObject is created
   270     GetAtkObject();
   272     NS_ASSERTION(quark_mai_hyperlink, "quark_mai_hyperlink not initialized");
   273     NS_ASSERTION(IS_MAI_OBJECT(mAtkObject), "Invalid AtkObject");
   274     MaiHyperlink* maiHyperlink = nullptr;
   275     if (quark_mai_hyperlink && IS_MAI_OBJECT(mAtkObject)) {
   276         maiHyperlink = (MaiHyperlink*)g_object_get_qdata(G_OBJECT(mAtkObject),
   277                                                          quark_mai_hyperlink);
   278         if (!maiHyperlink && aCreate) {
   279             maiHyperlink = new MaiHyperlink(this);
   280             SetMaiHyperlink(maiHyperlink);
   281         }
   282     }
   283     return maiHyperlink;
   284 }
   286 void
   287 AccessibleWrap::SetMaiHyperlink(MaiHyperlink* aMaiHyperlink)
   288 {
   289     NS_ASSERTION(quark_mai_hyperlink, "quark_mai_hyperlink not initialized");
   290     NS_ASSERTION(IS_MAI_OBJECT(mAtkObject), "Invalid AtkObject");
   291     if (quark_mai_hyperlink && IS_MAI_OBJECT(mAtkObject)) {
   292         MaiHyperlink* maiHyperlink = GetMaiHyperlink(false);
   293         if (!maiHyperlink && !aMaiHyperlink) {
   294             return; // Never set and we're shutting down
   295         }
   296         delete maiHyperlink;
   297         g_object_set_qdata(G_OBJECT(mAtkObject), quark_mai_hyperlink,
   298                            aMaiHyperlink);
   299     }
   300 }
   302 NS_IMETHODIMP
   303 AccessibleWrap::GetNativeInterface(void** aOutAccessible)
   304 {
   305     *aOutAccessible = nullptr;
   307     if (!mAtkObject) {
   308         if (IsDefunct() || !nsAccUtils::IsEmbeddedObject(this)) {
   309             // We don't create ATK objects for node which has been shutdown, or
   310             // nsIAccessible plain text leaves
   311             return NS_ERROR_FAILURE;
   312         }
   314         GType type = GetMaiAtkType(CreateMaiInterfaces());
   315         NS_ENSURE_TRUE(type, NS_ERROR_FAILURE);
   316         mAtkObject =
   317             reinterpret_cast<AtkObject *>
   318                             (g_object_new(type, nullptr));
   319         NS_ENSURE_TRUE(mAtkObject, NS_ERROR_OUT_OF_MEMORY);
   321         atk_object_initialize(mAtkObject, this);
   322         mAtkObject->role = ATK_ROLE_INVALID;
   323         mAtkObject->layer = ATK_LAYER_INVALID;
   324     }
   326     *aOutAccessible = mAtkObject;
   327     return NS_OK;
   328 }
   330 AtkObject *
   331 AccessibleWrap::GetAtkObject(void)
   332 {
   333     void *atkObj = nullptr;
   334     GetNativeInterface(&atkObj);
   335     return static_cast<AtkObject *>(atkObj);
   336 }
   338 // Get AtkObject from nsIAccessible interface
   339 /* static */
   340 AtkObject *
   341 AccessibleWrap::GetAtkObject(nsIAccessible* acc)
   342 {
   343     void *atkObjPtr = nullptr;
   344     acc->GetNativeInterface(&atkObjPtr);
   345     return atkObjPtr ? ATK_OBJECT(atkObjPtr) : nullptr;    
   346 }
   348 /* private */
   349 uint16_t
   350 AccessibleWrap::CreateMaiInterfaces(void)
   351 {
   352   uint16_t interfacesBits = 0;
   354   // The Component interface is supported by all accessibles.
   355   interfacesBits |= 1 << MAI_INTERFACE_COMPONENT;
   357   // Add Action interface if the action count is more than zero.
   358   if (ActionCount() > 0)
   359     interfacesBits |= 1 << MAI_INTERFACE_ACTION;
   361   // Text, Editabletext, and Hypertext interface.
   362   HyperTextAccessible* hyperText = AsHyperText();
   363   if (hyperText && hyperText->IsTextRole()) {
   364     interfacesBits |= 1 << MAI_INTERFACE_TEXT;
   365     interfacesBits |= 1 << MAI_INTERFACE_EDITABLE_TEXT;
   366     if (!nsAccUtils::MustPrune(this))
   367       interfacesBits |= 1 << MAI_INTERFACE_HYPERTEXT;
   368   }
   370   // Value interface.
   371   nsCOMPtr<nsIAccessibleValue> accessInterfaceValue;
   372   QueryInterface(NS_GET_IID(nsIAccessibleValue),
   373                  getter_AddRefs(accessInterfaceValue));
   374   if (accessInterfaceValue) {
   375     interfacesBits |= 1 << MAI_INTERFACE_VALUE; 
   376   }
   378   // Document interface.
   379   if (IsDoc())
   380     interfacesBits |= 1 << MAI_INTERFACE_DOCUMENT;
   382   if (IsImage())
   383     interfacesBits |= 1 << MAI_INTERFACE_IMAGE;
   385   // HyperLink interface.
   386   if (IsLink())
   387     interfacesBits |= 1 << MAI_INTERFACE_HYPERLINK_IMPL;
   389   if (!nsAccUtils::MustPrune(this)) {  // These interfaces require children
   390     // Table interface.
   391     if (AsTable())
   392       interfacesBits |= 1 << MAI_INTERFACE_TABLE;
   394     // Selection interface.
   395     if (IsSelect()) {
   396       interfacesBits |= 1 << MAI_INTERFACE_SELECTION;
   397     }
   398   }
   400   return interfacesBits;
   401 }
   403 static GType
   404 GetMaiAtkType(uint16_t interfacesBits)
   405 {
   406     GType type;
   407     static const GTypeInfo tinfo = {
   408         sizeof(MaiAtkObjectClass),
   409         (GBaseInitFunc) nullptr,
   410         (GBaseFinalizeFunc) nullptr,
   411         (GClassInitFunc) nullptr,
   412         (GClassFinalizeFunc) nullptr,
   413         nullptr, /* class data */
   414         sizeof(MaiAtkObject), /* instance size */
   415         0, /* nb preallocs */
   416         (GInstanceInitFunc) nullptr,
   417         nullptr /* value table */
   418     };
   420     /*
   421      * The members we use to register GTypes are GetAtkTypeForMai
   422      * and atk_if_infos, which are constant values to each MaiInterface
   423      * So we can reuse the registered GType when having
   424      * the same MaiInterface types.
   425      */
   426     const char *atkTypeName = GetUniqueMaiAtkTypeName(interfacesBits);
   427     type = g_type_from_name(atkTypeName);
   428     if (type) {
   429         return type;
   430     }
   432     /*
   433      * gobject limits the number of types that can directly derive from any
   434      * given object type to 4095.
   435      */
   436     static uint16_t typeRegCount = 0;
   437     if (typeRegCount++ >= 4095) {
   438         return G_TYPE_INVALID;
   439     }
   440     type = g_type_register_static(MAI_TYPE_ATK_OBJECT,
   441                                   atkTypeName,
   442                                   &tinfo, GTypeFlags(0));
   444     for (uint32_t index = 0; index < ArrayLength(atk_if_infos); index++) {
   445       if (interfacesBits & (1 << index)) {
   446         g_type_add_interface_static(type,
   447                                     GetAtkTypeForMai((MaiInterfaceType)index),
   448                                     &atk_if_infos[index]);
   449       }
   450     }
   452     return type;
   453 }
   455 static const char*
   456 GetUniqueMaiAtkTypeName(uint16_t interfacesBits)
   457 {
   458 #define MAI_ATK_TYPE_NAME_LEN (30)     /* 10+sizeof(uint16_t)*8/4+1 < 30 */
   460     static gchar namePrefix[] = "MaiAtkType";   /* size = 10 */
   461     static gchar name[MAI_ATK_TYPE_NAME_LEN + 1];
   463     PR_snprintf(name, MAI_ATK_TYPE_NAME_LEN, "%s%x", namePrefix,
   464                 interfacesBits);
   465     name[MAI_ATK_TYPE_NAME_LEN] = '\0';
   467     return name;
   468 }
   470 bool
   471 AccessibleWrap::IsValidObject()
   472 {
   473     // to ensure we are not shut down
   474     return !IsDefunct();
   475 }
   477 /* static functions for ATK callbacks */
   478 void
   479 classInitCB(AtkObjectClass *aClass)
   480 {
   481     GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);
   483     parent_class = g_type_class_peek_parent(aClass);
   485     aClass->get_name = getNameCB;
   486     aClass->get_description = getDescriptionCB;
   487     aClass->get_parent = getParentCB;
   488     aClass->get_n_children = getChildCountCB;
   489     aClass->ref_child = refChildCB;
   490     aClass->get_index_in_parent = getIndexInParentCB;
   491     aClass->get_role = getRoleCB;
   492     aClass->get_attributes = getAttributesCB;
   493     aClass->get_object_locale = GetLocaleCB;
   494     aClass->ref_state_set = refStateSetCB;
   495     aClass->ref_relation_set = refRelationSetCB;
   497     aClass->initialize = initializeCB;
   499     gobject_class->finalize = finalizeCB;
   501     mai_atk_object_signals [ACTIVATE] =
   502     g_signal_new ("activate",
   503                   MAI_TYPE_ATK_OBJECT,
   504                   G_SIGNAL_RUN_LAST,
   505                   0, /* default signal handler */
   506                   nullptr, nullptr,
   507                   g_cclosure_marshal_VOID__VOID,
   508                   G_TYPE_NONE, 0);
   509     mai_atk_object_signals [CREATE] =
   510     g_signal_new ("create",
   511                   MAI_TYPE_ATK_OBJECT,
   512                   G_SIGNAL_RUN_LAST,
   513                   0, /* default signal handler */
   514                   nullptr, nullptr,
   515                   g_cclosure_marshal_VOID__VOID,
   516                   G_TYPE_NONE, 0);
   517     mai_atk_object_signals [DEACTIVATE] =
   518     g_signal_new ("deactivate",
   519                   MAI_TYPE_ATK_OBJECT,
   520                   G_SIGNAL_RUN_LAST,
   521                   0, /* default signal handler */
   522                   nullptr, nullptr,
   523                   g_cclosure_marshal_VOID__VOID,
   524                   G_TYPE_NONE, 0);
   525     mai_atk_object_signals [DESTROY] =
   526     g_signal_new ("destroy",
   527                   MAI_TYPE_ATK_OBJECT,
   528                   G_SIGNAL_RUN_LAST,
   529                   0, /* default signal handler */
   530                   nullptr, nullptr,
   531                   g_cclosure_marshal_VOID__VOID,
   532                   G_TYPE_NONE, 0);
   533     mai_atk_object_signals [MAXIMIZE] =
   534     g_signal_new ("maximize",
   535                   MAI_TYPE_ATK_OBJECT,
   536                   G_SIGNAL_RUN_LAST,
   537                   0, /* default signal handler */
   538                   nullptr, nullptr,
   539                   g_cclosure_marshal_VOID__VOID,
   540                   G_TYPE_NONE, 0);
   541     mai_atk_object_signals [MINIMIZE] =
   542     g_signal_new ("minimize",
   543                   MAI_TYPE_ATK_OBJECT,
   544                   G_SIGNAL_RUN_LAST,
   545                   0, /* default signal handler */
   546                   nullptr, nullptr,
   547                   g_cclosure_marshal_VOID__VOID,
   548                   G_TYPE_NONE, 0);
   549     mai_atk_object_signals [RESIZE] =
   550     g_signal_new ("resize",
   551                   MAI_TYPE_ATK_OBJECT,
   552                   G_SIGNAL_RUN_LAST,
   553                   0, /* default signal handler */
   554                   nullptr, nullptr,
   555                   g_cclosure_marshal_VOID__VOID,
   556                   G_TYPE_NONE, 0);
   557     mai_atk_object_signals [RESTORE] =
   558     g_signal_new ("restore",
   559                   MAI_TYPE_ATK_OBJECT,
   560                   G_SIGNAL_RUN_LAST,
   561                   0, /* default signal handler */
   562                   nullptr, nullptr,
   563                   g_cclosure_marshal_VOID__VOID,
   564                   G_TYPE_NONE, 0);
   566 }
   568 void
   569 initializeCB(AtkObject *aAtkObj, gpointer aData)
   570 {
   571     NS_ASSERTION((IS_MAI_OBJECT(aAtkObj)), "Invalid AtkObject");
   572     NS_ASSERTION(aData, "Invalid Data to init AtkObject");
   573     if (!aAtkObj || !aData)
   574         return;
   576     /* call parent init function */
   577     /* AtkObjectClass has not a "initialize" function now,
   578      * maybe it has later
   579      */
   581     if (ATK_OBJECT_CLASS(parent_class)->initialize)
   582         ATK_OBJECT_CLASS(parent_class)->initialize(aAtkObj, aData);
   584   /* initialize object */
   585   MAI_ATK_OBJECT(aAtkObj)->accWrap =
   586     static_cast<AccessibleWrap*>(aData);
   587 }
   589 void
   590 finalizeCB(GObject *aObj)
   591 {
   592     if (!IS_MAI_OBJECT(aObj))
   593         return;
   594     NS_ASSERTION(MAI_ATK_OBJECT(aObj)->accWrap == nullptr, "AccWrap NOT null");
   596     // call parent finalize function
   597     // finalize of GObjectClass will unref the accessible parent if has
   598     if (G_OBJECT_CLASS (parent_class)->finalize)
   599         G_OBJECT_CLASS (parent_class)->finalize(aObj);
   600 }
   602 const gchar*
   603 getNameCB(AtkObject* aAtkObj)
   604 {
   605   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   606   if (!accWrap)
   607     return nullptr;
   609   nsAutoString name;
   610   accWrap->Name(name);
   612   // XXX Firing an event from here does not seem right
   613   MaybeFireNameChange(aAtkObj, name);
   615   return aAtkObj->name;
   616 }
   618 static void
   619 MaybeFireNameChange(AtkObject* aAtkObj, const nsString& aNewName)
   620 {
   621   NS_ConvertUTF16toUTF8 newNameUTF8(aNewName);
   622   if (aAtkObj->name && newNameUTF8.Equals(aAtkObj->name))
   623     return;
   625   // Below we duplicate the functionality of atk_object_set_name(),
   626   // but without calling atk_object_get_name(). Instead of
   627   // atk_object_get_name() we directly access aAtkObj->name. This is because
   628   // atk_object_get_name() would call getNameCB() which would call
   629   // MaybeFireNameChange() (or atk_object_set_name() before this problem was
   630   // fixed) and we would get an infinite recursion.
   631   // See http://bugzilla.mozilla.org/733712
   633   // Do not notify for initial name setting.
   634   // See bug http://bugzilla.gnome.org/665870
   635   bool notify = !!aAtkObj->name;
   637   free(aAtkObj->name);
   638   aAtkObj->name = strdup(newNameUTF8.get());
   640   if (notify)
   641     g_object_notify(G_OBJECT(aAtkObj), "accessible-name");
   642 }
   644 const gchar *
   645 getDescriptionCB(AtkObject *aAtkObj)
   646 {
   647     AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   648     if (!accWrap || accWrap->IsDefunct())
   649         return nullptr;
   651     /* nsIAccessible is responsible for the nonnull description */
   652     nsAutoString uniDesc;
   653     accWrap->Description(uniDesc);
   655     NS_ConvertUTF8toUTF16 objDesc(aAtkObj->description);
   656     if (!uniDesc.Equals(objDesc))
   657         atk_object_set_description(aAtkObj,
   658                                    NS_ConvertUTF16toUTF8(uniDesc).get());
   660     return aAtkObj->description;
   661 }
   663 AtkRole
   664 getRoleCB(AtkObject *aAtkObj)
   665 {
   666   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   667   if (!accWrap)
   668     return ATK_ROLE_INVALID;
   670 #ifdef DEBUG
   671   NS_ASSERTION(nsAccUtils::IsTextInterfaceSupportCorrect(accWrap),
   672       "Does not support nsIAccessibleText when it should");
   673 #endif
   675   if (aAtkObj->role != ATK_ROLE_INVALID)
   676     return aAtkObj->role;
   678 #define ROLE(geckoRole, stringRole, atkRole, macRole, \
   679              msaaRole, ia2Role, nameRule) \
   680   case roles::geckoRole: \
   681     aAtkObj->role = atkRole; \
   682     break;
   684   switch (accWrap->Role()) {
   685 #include "RoleMap.h"
   686     default:
   687       MOZ_CRASH("Unknown role.");
   688   };
   690 #undef ROLE
   692   if (aAtkObj->role == ATK_ROLE_LIST_BOX && !IsAtkVersionAtLeast(2, 1))
   693     aAtkObj->role = ATK_ROLE_LIST;
   694   else if (aAtkObj->role == ATK_ROLE_TABLE_ROW && !IsAtkVersionAtLeast(2, 1))
   695     aAtkObj->role = ATK_ROLE_LIST_ITEM;
   697   return aAtkObj->role;
   698 }
   700 static AtkAttributeSet*
   701 ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes)
   702 {
   703     if (!aAttributes)
   704         return nullptr;
   706     AtkAttributeSet *objAttributeSet = nullptr;
   707     nsCOMPtr<nsISimpleEnumerator> propEnum;
   708     nsresult rv = aAttributes->Enumerate(getter_AddRefs(propEnum));
   709     NS_ENSURE_SUCCESS(rv, nullptr);
   711     bool hasMore;
   712     while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
   713         nsCOMPtr<nsISupports> sup;
   714         rv = propEnum->GetNext(getter_AddRefs(sup));
   715         NS_ENSURE_SUCCESS(rv, objAttributeSet);
   717         nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
   718         NS_ENSURE_TRUE(propElem, objAttributeSet);
   720         nsAutoCString name;
   721         rv = propElem->GetKey(name);
   722         NS_ENSURE_SUCCESS(rv, objAttributeSet);
   724         nsAutoString value;
   725         rv = propElem->GetValue(value);
   726         NS_ENSURE_SUCCESS(rv, objAttributeSet);
   728         AtkAttribute *objAttr = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
   729         objAttr->name = g_strdup(name.get());
   730         objAttr->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
   731         objAttributeSet = g_slist_prepend(objAttributeSet, objAttr);
   732     }
   734     //libspi will free it
   735     return objAttributeSet;
   736 }
   738 AtkAttributeSet*
   739 GetAttributeSet(Accessible* aAccessible)
   740 {
   741   nsCOMPtr<nsIPersistentProperties> attributes = aAccessible->Attributes();
   742   if (attributes) {
   743     // There is no ATK state for haspopup, must use object attribute to expose
   744     // the same info.
   745     if (aAccessible->State() & states::HASPOPUP) {
   746       nsAutoString unused;
   747       attributes->SetStringProperty(NS_LITERAL_CSTRING("haspopup"),
   748                                     NS_LITERAL_STRING("true"), unused);
   749     }
   751     return ConvertToAtkAttributeSet(attributes);
   752   }
   754   return nullptr;
   755 }
   757 AtkAttributeSet *
   758 getAttributesCB(AtkObject *aAtkObj)
   759 {
   760   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   761   return accWrap ? GetAttributeSet(accWrap) : nullptr;
   762 }
   764 const gchar*
   765 GetLocaleCB(AtkObject* aAtkObj)
   766 {
   767   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   768   if (!accWrap)
   769     return nullptr;
   771   nsAutoString locale;
   772   accWrap->Language(locale);
   773   return AccessibleWrap::ReturnString(locale);
   774 }
   776 AtkObject *
   777 getParentCB(AtkObject *aAtkObj)
   778 {
   779   if (!aAtkObj->accessible_parent) {
   780     AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   781     if (!accWrap)
   782       return nullptr;
   784     Accessible* accParent = accWrap->Parent();
   785     if (!accParent)
   786       return nullptr;
   788     AtkObject* parent = AccessibleWrap::GetAtkObject(accParent);
   789     if (parent)
   790       atk_object_set_parent(aAtkObj, parent);
   791   }
   792   return aAtkObj->accessible_parent;
   793 }
   795 gint
   796 getChildCountCB(AtkObject *aAtkObj)
   797 {
   798     AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   799     if (!accWrap || nsAccUtils::MustPrune(accWrap)) {
   800         return 0;
   801     }
   803     return static_cast<gint>(accWrap->EmbeddedChildCount());
   804 }
   806 AtkObject *
   807 refChildCB(AtkObject *aAtkObj, gint aChildIndex)
   808 {
   809     // aChildIndex should not be less than zero
   810     if (aChildIndex < 0) {
   811       return nullptr;
   812     }
   814     AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   815     if (!accWrap || nsAccUtils::MustPrune(accWrap)) {
   816         return nullptr;
   817     }
   819     Accessible* accChild = accWrap->GetEmbeddedChildAt(aChildIndex);
   820     if (!accChild)
   821         return nullptr;
   823     AtkObject* childAtkObj = AccessibleWrap::GetAtkObject(accChild);
   825     NS_ASSERTION(childAtkObj, "Fail to get AtkObj");
   826     if (!childAtkObj)
   827         return nullptr;
   828     g_object_ref(childAtkObj);
   830   if (aAtkObj != childAtkObj->accessible_parent)
   831     atk_object_set_parent(childAtkObj, aAtkObj);
   833   return childAtkObj;
   834 }
   836 gint
   837 getIndexInParentCB(AtkObject *aAtkObj)
   838 {
   839     // We don't use nsIAccessible::GetIndexInParent() because
   840     // for ATK we don't want to include text leaf nodes as children
   841     AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   842     if (!accWrap) {
   843         return -1;
   844     }
   846     Accessible* parent = accWrap->Parent();
   847     if (!parent)
   848         return -1; // No parent
   850     return parent->GetIndexOfEmbeddedChild(accWrap);
   851 }
   853 static void
   854 TranslateStates(uint64_t aState, AtkStateSet* aStateSet)
   855 {
   856   // atk doesn't have a read only state so read only things shouldn't be
   857   // editable.
   858   if (aState & states::READONLY)
   859     aState &= ~states::EDITABLE;
   861   // Convert every state to an entry in AtkStateMap
   862   uint32_t stateIndex = 0;
   863   uint64_t bitMask = 1;
   864   while (gAtkStateMap[stateIndex].stateMapEntryType != kNoSuchState) {
   865     if (gAtkStateMap[stateIndex].atkState) { // There's potentially an ATK state for this
   866       bool isStateOn = (aState & bitMask) != 0;
   867       if (gAtkStateMap[stateIndex].stateMapEntryType == kMapOpposite) {
   868         isStateOn = !isStateOn;
   869       }
   870       if (isStateOn) {
   871         atk_state_set_add_state(aStateSet, gAtkStateMap[stateIndex].atkState);
   872       }
   873     }
   874     bitMask <<= 1;
   875     ++ stateIndex;
   876   }
   877 }
   879 AtkStateSet *
   880 refStateSetCB(AtkObject *aAtkObj)
   881 {
   882     AtkStateSet *state_set = nullptr;
   883     state_set = ATK_OBJECT_CLASS(parent_class)->ref_state_set(aAtkObj);
   885     AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   886     if (!accWrap) {
   887         TranslateStates(states::DEFUNCT, state_set);
   888         return state_set;
   889     }
   891     // Map states
   892     TranslateStates(accWrap->State(), state_set);
   894     return state_set;
   895 }
   897 static void
   898 UpdateAtkRelation(RelationType aType, Accessible* aAcc,
   899                   AtkRelationType aAtkType, AtkRelationSet* aAtkSet)
   900 {
   901   if (aAtkType == ATK_RELATION_NULL)
   902     return;
   904   AtkRelation* atkRelation =
   905     atk_relation_set_get_relation_by_type(aAtkSet, aAtkType);
   906   if (atkRelation)
   907     atk_relation_set_remove(aAtkSet, atkRelation);
   909   Relation rel(aAcc->RelationByType(aType));
   910   nsTArray<AtkObject*> targets;
   911   Accessible* tempAcc = nullptr;
   912   while ((tempAcc = rel.Next()))
   913     targets.AppendElement(AccessibleWrap::GetAtkObject(tempAcc));
   915   if (targets.Length()) {
   916     atkRelation = atk_relation_new(targets.Elements(),
   917                                    targets.Length(), aAtkType);
   918     atk_relation_set_add(aAtkSet, atkRelation);
   919     g_object_unref(atkRelation);
   920   }
   921 }
   923 AtkRelationSet *
   924 refRelationSetCB(AtkObject *aAtkObj)
   925 {
   926   AtkRelationSet* relation_set =
   927     ATK_OBJECT_CLASS(parent_class)->ref_relation_set(aAtkObj);
   929   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   930   if (!accWrap)
   931     return relation_set;
   933 #define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
   934   UpdateAtkRelation(RelationType::geckoType, accWrap, atkType, relation_set);
   936 #include "RelationTypeMap.h"
   938 #undef RELATIONTYPE
   940   return relation_set;
   941 }
   943 // Check if aAtkObj is a valid MaiAtkObject, and return the AccessibleWrap
   944 // for it.
   945 AccessibleWrap*
   946 GetAccessibleWrap(AtkObject* aAtkObj)
   947 {
   948   NS_ENSURE_TRUE(IS_MAI_OBJECT(aAtkObj), nullptr);
   949   AccessibleWrap* accWrap = MAI_ATK_OBJECT(aAtkObj)->accWrap;
   951   // Check if the accessible was deconstructed.
   952   if (!accWrap)
   953     return nullptr;
   955   NS_ENSURE_TRUE(accWrap->GetAtkObject() == aAtkObj, nullptr);
   957   AccessibleWrap* appAccWrap = ApplicationAcc();
   958   if (appAccWrap != accWrap && !accWrap->IsValidObject())
   959     return nullptr;
   961   return accWrap;
   962 }
   964 nsresult
   965 AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
   966 {
   967   nsresult rv = Accessible::HandleAccEvent(aEvent);
   968   NS_ENSURE_SUCCESS(rv, rv);
   970     Accessible* accessible = aEvent->GetAccessible();
   971     NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);
   973     // The accessible can become defunct if we have an xpcom event listener
   974     // which decides it would be fun to change the DOM and flush layout.
   975     if (accessible->IsDefunct())
   976         return NS_OK;
   978     uint32_t type = aEvent->GetEventType();
   980     AtkObject* atkObj = AccessibleWrap::GetAtkObject(accessible);
   982     // We don't create ATK objects for nsIAccessible plain text leaves,
   983     // just return NS_OK in such case
   984     if (!atkObj) {
   985         NS_ASSERTION(type == nsIAccessibleEvent::EVENT_SHOW ||
   986                      type == nsIAccessibleEvent::EVENT_HIDE,
   987                      "Event other than SHOW and HIDE fired for plain text leaves");
   988         return NS_OK;
   989     }
   991     AccessibleWrap* accWrap = GetAccessibleWrap(atkObj);
   992     if (!accWrap) {
   993         return NS_OK; // Node is shut down
   994     }
   996     switch (type) {
   997     case nsIAccessibleEvent::EVENT_STATE_CHANGE:
   998         return FireAtkStateChangeEvent(aEvent, atkObj);
  1000     case nsIAccessibleEvent::EVENT_TEXT_REMOVED:
  1001     case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
  1002         return FireAtkTextChangedEvent(aEvent, atkObj);
  1004     case nsIAccessibleEvent::EVENT_FOCUS:
  1006         a11y::RootAccessible* rootAccWrap = accWrap->RootAccessible();
  1007         if (rootAccWrap && rootAccWrap->mActivated) {
  1008             atk_focus_tracker_notify(atkObj);
  1009             // Fire state change event for focus
  1010             atk_object_notify_state_change(atkObj, ATK_STATE_FOCUSED, true);
  1011             return NS_OK;
  1013       } break;
  1015     case nsIAccessibleEvent::EVENT_NAME_CHANGE:
  1017         nsAutoString newName;
  1018         accessible->Name(newName);
  1020         MaybeFireNameChange(atkObj, newName);
  1022         break;
  1024     case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
  1026         nsCOMPtr<nsIAccessibleValue> value(do_QueryObject(accessible));
  1027         if (value) {    // Make sure this is a numeric value
  1028             // Don't fire for MSAA string value changes (e.g. text editing)
  1029             // ATK values are always numeric
  1030             g_object_notify( (GObject*)atkObj, "accessible-value" );
  1032       } break;
  1034     case nsIAccessibleEvent::EVENT_SELECTION:
  1035     case nsIAccessibleEvent::EVENT_SELECTION_ADD:
  1036     case nsIAccessibleEvent::EVENT_SELECTION_REMOVE:
  1038       // XXX: dupe events may be fired
  1039       AccSelChangeEvent* selChangeEvent = downcast_accEvent(aEvent);
  1040       g_signal_emit_by_name(AccessibleWrap::GetAtkObject(selChangeEvent->Widget()),
  1041                             "selection_changed");
  1042       break;
  1045     case nsIAccessibleEvent::EVENT_SELECTION_WITHIN:
  1047       g_signal_emit_by_name(atkObj, "selection_changed");
  1048       break;
  1051     case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
  1052         g_signal_emit_by_name(atkObj, "text_selection_changed");
  1053         break;
  1055     case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED:
  1057         AccCaretMoveEvent* caretMoveEvent = downcast_accEvent(aEvent);
  1058         NS_ASSERTION(caretMoveEvent, "Event needs event data");
  1059         if (!caretMoveEvent)
  1060             break;
  1062         int32_t caretOffset = caretMoveEvent->GetCaretOffset();
  1063         g_signal_emit_by_name(atkObj, "text_caret_moved", caretOffset);
  1064       } break;
  1066     case nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED:
  1067         g_signal_emit_by_name(atkObj, "text-attributes-changed");
  1068         break;
  1070     case nsIAccessibleEvent::EVENT_TABLE_MODEL_CHANGED:
  1071         g_signal_emit_by_name(atkObj, "model_changed");
  1072         break;
  1074     case nsIAccessibleEvent::EVENT_TABLE_ROW_INSERT:
  1076         AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
  1077         NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
  1079         int32_t rowIndex = tableEvent->GetIndex();
  1080         int32_t numRows = tableEvent->GetCount();
  1082         g_signal_emit_by_name(atkObj, "row_inserted", rowIndex, numRows);
  1083      } break;
  1085    case nsIAccessibleEvent::EVENT_TABLE_ROW_DELETE:
  1087         AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
  1088         NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
  1090         int32_t rowIndex = tableEvent->GetIndex();
  1091         int32_t numRows = tableEvent->GetCount();
  1093         g_signal_emit_by_name(atkObj, "row_deleted", rowIndex, numRows);
  1094       } break;
  1096     case nsIAccessibleEvent::EVENT_TABLE_ROW_REORDER:
  1098         g_signal_emit_by_name(atkObj, "row_reordered");
  1099         break;
  1102     case nsIAccessibleEvent::EVENT_TABLE_COLUMN_INSERT:
  1104         AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
  1105         NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
  1107         int32_t colIndex = tableEvent->GetIndex();
  1108         int32_t numCols = tableEvent->GetCount();
  1109         g_signal_emit_by_name(atkObj, "column_inserted", colIndex, numCols);
  1110       } break;
  1112     case nsIAccessibleEvent::EVENT_TABLE_COLUMN_DELETE:
  1114         AccTableChangeEvent* tableEvent = downcast_accEvent(aEvent);
  1115         NS_ENSURE_TRUE(tableEvent, NS_ERROR_FAILURE);
  1117         int32_t colIndex = tableEvent->GetIndex();
  1118         int32_t numCols = tableEvent->GetCount();
  1119         g_signal_emit_by_name(atkObj, "column_deleted", colIndex, numCols);
  1120       } break;
  1122     case nsIAccessibleEvent::EVENT_TABLE_COLUMN_REORDER:
  1123         g_signal_emit_by_name(atkObj, "column_reordered");
  1124         break;
  1126     case nsIAccessibleEvent::EVENT_SECTION_CHANGED:
  1127         g_signal_emit_by_name(atkObj, "visible_data_changed");
  1128         break;
  1130     case nsIAccessibleEvent::EVENT_SHOW:
  1131         return FireAtkShowHideEvent(aEvent, atkObj, true);
  1133     case nsIAccessibleEvent::EVENT_HIDE:
  1134         // XXX - Handle native dialog accessibles.
  1135         if (!accessible->IsRoot() && accessible->HasARIARole() &&
  1136             accessible->ARIARole() == roles::DIALOG) {
  1137           guint id = g_signal_lookup("deactivate", MAI_TYPE_ATK_OBJECT);
  1138           g_signal_emit(atkObj, id, 0);
  1140         return FireAtkShowHideEvent(aEvent, atkObj, false);
  1142         /*
  1143          * Because dealing with menu is very different between nsIAccessible
  1144          * and ATK, and the menu activity is important, specially transfer the
  1145          * following two event.
  1146          * Need more verification by AT test.
  1147          */
  1148     case nsIAccessibleEvent::EVENT_MENU_START:
  1149     case nsIAccessibleEvent::EVENT_MENU_END:
  1150         break;
  1152     case nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE:
  1154         accessible->AsRoot()->mActivated = true;
  1155         guint id = g_signal_lookup("activate", MAI_TYPE_ATK_OBJECT);
  1156         g_signal_emit(atkObj, id, 0);
  1158         // Always fire a current focus event after activation.
  1159         FocusMgr()->ForceFocusEvent();
  1160       } break;
  1162     case nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE:
  1164         accessible->AsRoot()->mActivated = false;
  1165         guint id = g_signal_lookup("deactivate", MAI_TYPE_ATK_OBJECT);
  1166         g_signal_emit(atkObj, id, 0);
  1167       } break;
  1169     case nsIAccessibleEvent::EVENT_WINDOW_MAXIMIZE:
  1171         guint id = g_signal_lookup("maximize", MAI_TYPE_ATK_OBJECT);
  1172         g_signal_emit(atkObj, id, 0);
  1173       } break;
  1175     case nsIAccessibleEvent::EVENT_WINDOW_MINIMIZE:
  1177         guint id = g_signal_lookup("minimize", MAI_TYPE_ATK_OBJECT);
  1178         g_signal_emit(atkObj, id, 0);
  1179       } break;
  1181     case nsIAccessibleEvent::EVENT_WINDOW_RESTORE:
  1183         guint id = g_signal_lookup("restore", MAI_TYPE_ATK_OBJECT);
  1184         g_signal_emit(atkObj, id, 0);
  1185       } break;
  1187     case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
  1188         g_signal_emit_by_name (atkObj, "load_complete");
  1189         // XXX - Handle native dialog accessibles.
  1190         if (!accessible->IsRoot() && accessible->HasARIARole() &&
  1191             accessible->ARIARole() == roles::DIALOG) {
  1192           guint id = g_signal_lookup("activate", MAI_TYPE_ATK_OBJECT);
  1193           g_signal_emit(atkObj, id, 0);
  1195       break;
  1197     case nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD:
  1198         g_signal_emit_by_name (atkObj, "reload");
  1199       break;
  1201     case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED:
  1202         g_signal_emit_by_name (atkObj, "load_stopped");
  1203       break;
  1205     case nsIAccessibleEvent::EVENT_MENUPOPUP_START:
  1206         atk_focus_tracker_notify(atkObj); // fire extra focus event
  1207         atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, true);
  1208         atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, true);
  1209         break;
  1211     case nsIAccessibleEvent::EVENT_MENUPOPUP_END:
  1212         atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, false);
  1213         atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, false);
  1214         break;
  1217     return NS_OK;
  1220 nsresult
  1221 AccessibleWrap::FireAtkStateChangeEvent(AccEvent* aEvent,
  1222                                         AtkObject* aObject)
  1224     AccStateChangeEvent* event = downcast_accEvent(aEvent);
  1225     NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
  1227     bool isEnabled = event->IsStateEnabled();
  1228     int32_t stateIndex = AtkStateMap::GetStateIndexFor(event->GetState());
  1229     if (stateIndex >= 0) {
  1230         NS_ASSERTION(gAtkStateMap[stateIndex].stateMapEntryType != kNoSuchState,
  1231                      "No such state");
  1233         if (gAtkStateMap[stateIndex].atkState != kNone) {
  1234             NS_ASSERTION(gAtkStateMap[stateIndex].stateMapEntryType != kNoStateChange,
  1235                          "State changes should not fired for this state");
  1237             if (gAtkStateMap[stateIndex].stateMapEntryType == kMapOpposite)
  1238                 isEnabled = !isEnabled;
  1240             // Fire state change for first state if there is one to map
  1241             atk_object_notify_state_change(aObject,
  1242                                            gAtkStateMap[stateIndex].atkState,
  1243                                            isEnabled);
  1247     return NS_OK;
  1250 nsresult
  1251 AccessibleWrap::FireAtkTextChangedEvent(AccEvent* aEvent,
  1252                                         AtkObject* aObject)
  1254     AccTextChangeEvent* event = downcast_accEvent(aEvent);
  1255     NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
  1257     int32_t start = event->GetStartOffset();
  1258     uint32_t length = event->GetLength();
  1259     bool isInserted = event->IsTextInserted();
  1260     bool isFromUserInput = aEvent->IsFromUserInput();
  1261     char* signal_name = nullptr;
  1263   if (gAvailableAtkSignals == eUnknown)
  1264     gAvailableAtkSignals =
  1265       g_signal_lookup("text-insert", G_OBJECT_TYPE(aObject)) ?
  1266         eHaveNewAtkTextSignals : eNoNewAtkSignals;
  1268   if (gAvailableAtkSignals == eNoNewAtkSignals) {
  1269     // XXX remove this code and the gHaveNewTextSignals check when we can
  1270     // stop supporting old atk since it doesn't really work anyway
  1271     // see bug 619002
  1272     signal_name = g_strconcat(isInserted ? "text_changed::insert" :
  1273                               "text_changed::delete",
  1274                               isFromUserInput ? "" : kNonUserInputEvent, nullptr);
  1275     g_signal_emit_by_name(aObject, signal_name, start, length);
  1276   } else {
  1277     nsAutoString text;
  1278     event->GetModifiedText(text);
  1279     signal_name = g_strconcat(isInserted ? "text-insert" : "text-remove",
  1280                               isFromUserInput ? "" : "::system", nullptr);
  1281     g_signal_emit_by_name(aObject, signal_name, start, length,
  1282                           NS_ConvertUTF16toUTF8(text).get());
  1285   g_free(signal_name);
  1286   return NS_OK;
  1289 nsresult
  1290 AccessibleWrap::FireAtkShowHideEvent(AccEvent* aEvent,
  1291                                      AtkObject* aObject, bool aIsAdded)
  1293     int32_t indexInParent = getIndexInParentCB(aObject);
  1294     AtkObject *parentObject = getParentCB(aObject);
  1295     NS_ENSURE_STATE(parentObject);
  1297     bool isFromUserInput = aEvent->IsFromUserInput();
  1298     char *signal_name = g_strconcat(aIsAdded ? "children_changed::add" :  "children_changed::remove",
  1299                                     isFromUserInput ? "" : kNonUserInputEvent, nullptr);
  1300     g_signal_emit_by_name(parentObject, signal_name, indexInParent, aObject, nullptr);
  1301     g_free(signal_name);
  1303     return NS_OK;

mercurial