Bug 1056803 - added nsiAccessibleObjectAttributeChangedEvent interface. Tests included. r=tbsaunde
authorYura Zenevich <yzenevich@mozilla.com>
Thu, 28 Aug 2014 08:42:06 -0400
changeset 223828 ad8901b59cd04d3bf6b2cec0cc2dc994cdae3a61
parent 223827 688501a435ac6439b26baf02a560b102e50d91b1
child 223829 688a1864cd588fd6d63e98f9239878bd2797834b
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde
bugs1056803, 100644
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1056803 - added nsiAccessibleObjectAttributeChangedEvent interface. Tests included. r=tbsaunde --- accessible/base/AccEvent.cpp | 8 +++++ accessible/base/AccEvent.h | 29 ++++++++++++++++- accessible/generic/DocAccessible.cpp | 8 +++-- accessible/interfaces/moz.build | 1 + .../nsIAccessibleObjectAttributeChangedEvent.idl | 21 ++++++++++++ accessible/tests/mochitest/common.js | 2 ++ accessible/tests/mochitest/events.js | 37 ++++++++++++++++++++++ .../tests/mochitest/events/test_aria_objattr.html | 7 ++-- accessible/xpcom/AccEvents.conf | 1 + 9 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 accessible/interfaces/nsIAccessibleObjectAttributeChangedEvent.idl
accessible/base/AccEvent.cpp
accessible/base/AccEvent.h
accessible/generic/DocAccessible.cpp
accessible/interfaces/moz.build
accessible/interfaces/nsIAccessibleObjectAttributeChangedEvent.idl
accessible/tests/mochitest/common.js
accessible/tests/mochitest/events.js
accessible/tests/mochitest/events/test_aria_objattr.html
accessible/xpcom/AccEvents.conf
--- a/accessible/base/AccEvent.cpp
+++ b/accessible/base/AccEvent.cpp
@@ -246,11 +246,19 @@ a11y::MakeXPCEvent(AccEvent* aEvent)
     xpEvent = new xpcAccVirtualCursorChangeEvent(type, acc, doc, domNode, fromUser,
                                                  vcc->OldAccessible(),
                                                  vcc->OldStartOffset(),
                                                  vcc->OldEndOffset(),
                                                  vcc->Reason());
     return xpEvent.forget();
   }
 
+  if (eventGroup & (1 << AccEvent::eObjectAttrChangedEvent)) {
+    AccObjectAttrChangedEvent* oac = downcast_accEvent(aEvent);
+    xpEvent = new xpcAccObjectAttributeChangedEvent(type, acc, doc, domNode,
+                                                    fromUser,
+                                                    oac->GetAttribute());
+    return xpEvent.forget();
+  }
+
   xpEvent = new xpcAccEvent(type, acc, doc, domNode, fromUser);
   return xpEvent.forget();
   }
--- a/accessible/base/AccEvent.h
+++ b/accessible/base/AccEvent.h
@@ -100,17 +100,18 @@ public:
     eMutationEvent,
     eReorderEvent,
     eHideEvent,
     eShowEvent,
     eCaretMoveEvent,
     eTextSelChangeEvent,
     eSelectionChangeEvent,
     eTableChangeEvent,
-    eVirtualCursorChangeEvent
+    eVirtualCursorChangeEvent,
+    eObjectAttrChangedEvent
   };
 
   static const EventGroup kEventGroup = eGenericEvent;
   virtual unsigned int GetEventGroups() const
   {
     return 1U << eGenericEvent;
   }
 
@@ -490,16 +491,42 @@ public:
 private:
   nsRefPtr<nsIAccessible> mOldAccessible;
   int32_t mOldStart;
   int32_t mOldEnd;
   int16_t mReason;
 };
 
 /**
+ * Accessible object attribute changed event.
+ */
+class AccObjectAttrChangedEvent: public AccEvent
+{
+public:
+  AccObjectAttrChangedEvent(Accessible* aAccessible, nsIAtom* aAttribute) :
+    AccEvent(::nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED, aAccessible),
+    mAttribute(aAttribute) { }
+
+  // AccEvent
+  static const EventGroup kEventGroup = eObjectAttrChangedEvent;
+  virtual unsigned int GetEventGroups() const
+  {
+    return AccEvent::GetEventGroups() | (1U << eObjectAttrChangedEvent);
+  }
+
+  // AccObjectAttrChangedEvent
+  nsIAtom* GetAttribute() const { return mAttribute; }
+
+private:
+  nsCOMPtr<nsIAtom> mAttribute;
+
+  virtual ~AccObjectAttrChangedEvent() { }
+};
+
+/**
  * Downcast the generic accessible event object to derived type.
  */
 class downcast_accEvent
 {
 public:
   explicit downcast_accEvent(AccEvent* e) : mRawPtr(e) { }
 
   template<class Destination>
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -1089,19 +1089,21 @@ DocAccessible::ARIAAttributeChanged(Acce
       new AccStateChangeEvent(aAccessible, states::EXPANDED);
     FireDelayedEvent(event);
     return;
   }
 
   // For aria attributes like drag and drop changes we fire a generic attribute
   // change event; at least until native API comes up with a more meaningful event.
   uint8_t attrFlags = aria::AttrCharacteristicsFor(aAttribute);
-  if (!(attrFlags & ATTR_BYPASSOBJ))
-    FireDelayedEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED,
-                     aAccessible);
+  if (!(attrFlags & ATTR_BYPASSOBJ)) {
+    nsRefPtr<AccEvent> event =
+      new AccObjectAttrChangedEvent(aAccessible, aAttribute);
+    FireDelayedEvent(event);
+  }
 
   nsIContent* elm = aAccessible->GetContent();
 
   if (aAttribute == nsGkAtoms::aria_checked ||
       (aAccessible->IsButton() &&
        aAttribute == nsGkAtoms::aria_pressed)) {
     const uint64_t kState = (aAttribute == nsGkAtoms::aria_checked) ?
                             states::CHECKED : states::PRESSED;
--- a/accessible/interfaces/moz.build
+++ b/accessible/interfaces/moz.build
@@ -13,16 +13,17 @@ XPIDL_SOURCES += [
     'nsIAccessibleCaretMoveEvent.idl',
     'nsIAccessibleDocument.idl',
     'nsIAccessibleEditableText.idl',
     'nsIAccessibleEvent.idl',
     'nsIAccessibleHideEvent.idl',
     'nsIAccessibleHyperLink.idl',
     'nsIAccessibleHyperText.idl',
     'nsIAccessibleImage.idl',
+    'nsIAccessibleObjectAttributeChangedEvent.idl',
     'nsIAccessiblePivot.idl',
     'nsIAccessibleRelation.idl',
     'nsIAccessibleRetrieval.idl',
     'nsIAccessibleRole.idl',
     'nsIAccessibleSelectable.idl',
     'nsIAccessibleStateChangeEvent.idl',
     'nsIAccessibleStates.idl',
     'nsIAccessibleTable.idl',
new file mode 100644
--- /dev/null
+++ b/accessible/interfaces/nsIAccessibleObjectAttributeChangedEvent.idl
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIAccessibleEvent.idl"
+
+interface nsIAtom;
+
+/**
+ * Fired when an attribute of an accessible changes.
+ */
+[scriptable, builtinclass, uuid(4CA96609-23C8-4771-86E7-77C8B651CA24)]
+interface nsIAccessibleObjectAttributeChangedEvent : nsIAccessibleEvent
+{
+  /**
+   * Return the accessible attribute that changed.
+   */
+  readonly attribute nsIAtom changedAttribute;
+};
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -7,16 +7,18 @@ const nsIAccessibleEvent = Components.in
 const nsIAccessibleStateChangeEvent =
   Components.interfaces.nsIAccessibleStateChangeEvent;
 const nsIAccessibleCaretMoveEvent =
   Components.interfaces.nsIAccessibleCaretMoveEvent;
 const nsIAccessibleTextChangeEvent =
   Components.interfaces.nsIAccessibleTextChangeEvent;
 const nsIAccessibleVirtualCursorChangeEvent =
   Components.interfaces.nsIAccessibleVirtualCursorChangeEvent;
+const nsIAccessibleObjectAttributeChangedEvent =
+  Components.interfaces.nsIAccessibleObjectAttributeChangedEvent;
 
 const nsIAccessibleStates = Components.interfaces.nsIAccessibleStates;
 const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole;
 const nsIAccessibleScrollType = Components.interfaces.nsIAccessibleScrollType;
 const nsIAccessibleCoordinateType = Components.interfaces.nsIAccessibleCoordinateType;
 
 const nsIAccessibleRelation = Components.interfaces.nsIAccessibleRelation;
 const nsIAccessibleTextRange = Components.interfaces.nsIAccessibleTextRange;
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -1769,16 +1769,53 @@ function textSelectionChecker(aID, aStar
       ok(true, "Collapsed selection triggered text selection change event.");
     } else {
       testTextGetSelection(aID, aStartOffset, aEndOffset, 0);
     }
   }
 }
 
 /**
+ * Object attribute changed checker
+ */
+function objAttrChangedChecker(aID, aAttr)
+{
+  this.__proto__ = new invokerChecker(EVENT_OBJECT_ATTRIBUTE_CHANGED, aID);
+
+  this.check = function objAttrChangedChecker_check(aEvent)
+  {
+    var event = null;
+    try {
+      var event = aEvent.QueryInterface(
+        nsIAccessibleObjectAttributeChangedEvent);
+    } catch (e) {
+      ok(false, "Object attribute changed event was expected");
+    }
+
+    if (!event) {
+      return;
+    }
+
+    is(event.changedAttribute.toString(), aAttr,
+      "Wrong attribute name of the object attribute changed event.");
+  };
+
+  this.match = function objAttrChangedChecker_match(aEvent)
+  {
+    if (aEvent instanceof nsIAccessibleObjectAttributeChangedEvent) {
+      var scEvent = aEvent.QueryInterface(
+        nsIAccessibleObjectAttributeChangedEvent);
+      return (aEvent.accessible == getAccessible(this.target)) &&
+        (scEvent.changedAttribute.toString() == aAttr);
+    }
+    return false;
+  };
+}
+
+/**
  * State change checker.
  */
 function stateChangeChecker(aState, aIsExtraState, aIsEnabled,
                             aTargetOrFunc, aTargetFuncArg, aIsAsync,
                             aSkipCurrentStateCheck)
 {
   this.__proto__ = new invokerChecker(EVENT_STATE_CHANGE, aTargetOrFunc,
                                       aTargetFuncArg, aIsAsync);
--- a/accessible/tests/mochitest/events/test_aria_objattr.html
+++ b/accessible/tests/mochitest/events/test_aria_objattr.html
@@ -15,35 +15,34 @@
           src="../events.js"></script>
 
   <script type="application/javascript">
 
     /**
      * Do tests.
      */
     var gQueue = null;
-
     function updateAttribute(aID, aAttr, aValue)
     {
       this.node = getNode(aID);
       this.accessible = getAccessible(this.node);
 
       this.eventSeq = [
-        new invokerChecker(EVENT_OBJECT_ATTRIBUTE_CHANGED, this.accessible),
+        new objAttrChangedChecker(aID, aAttr),
       ];
 
       this.invoke = function updateAttribute_invoke()
       {
         this.node.setAttribute(aAttr, aValue);
-      }
+      };
 
       this.getID = function updateAttribute_getID()
       {
         return aAttr + " for " + aID + " " + aValue;
-      }
+      };
     }
 
     // Debug stuff.
     // gA11yEventDumpID = "eventdump";
     //gA11yEventDumpToConsole = true;
 
     function doTests()
     {
--- a/accessible/xpcom/AccEvents.conf
+++ b/accessible/xpcom/AccEvents.conf
@@ -7,11 +7,12 @@
  and should be in nsIAccessible<name>.idl file"""
 
 simple_events = [
     'Event',
     'StateChangeEvent',
     'TextChangeEvent',
     'HideEvent',
     'CaretMoveEvent',
+    'ObjectAttributeChangedEvent',
     'TableChangeEvent',
     'VirtualCursorChangeEvent'
   ]