Bug 380508 - implement IAccessibleHyperlink, r=aaronlev, sr=neil
authorsurkov.alexander@gmail.com
Tue, 15 May 2007 21:28:38 -0700
changeset 1507 01ffc4f43ddc55785dca95f1a1ed68bd231371a2
parent 1506 0ac54c8f125029102163fc032159e40ec1b661b1
child 1508 8199abd93feee081c735db70f34a86427b8d57b8
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaaronlev, neil
bugs380508
milestone1.9a5pre
Bug 380508 - implement IAccessibleHyperlink, r=aaronlev, sr=neil
accessible/src/msaa/CAccessibleAction.cpp
accessible/src/msaa/CAccessibleAction.h
accessible/src/msaa/CAccessibleHyperlink.cpp
accessible/src/msaa/CAccessibleHyperlink.h
accessible/src/msaa/CAccessibleHypertext.cpp
accessible/src/msaa/Makefile.in
accessible/src/msaa/nsAccessibleWrap.cpp
accessible/src/msaa/nsAccessibleWrap.h
new file mode 100755
--- /dev/null
+++ b/accessible/src/msaa/CAccessibleAction.cpp
@@ -0,0 +1,193 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "CAccessibleAction.h"
+
+#include "AccessibleAction_i.c"
+
+#include "nsIAccessible.h"
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsIDOMDOMStringList.h"
+
+// IUnknown
+
+STDMETHODIMP
+CAccessibleAction::QueryInterface(REFIID iid, void** ppv)
+{
+  *ppv = NULL;
+
+  if (IID_IAccessibleAction == iid) {
+    nsCOMPtr<nsIAccessible> acc(do_QueryInterface(this));
+    if (!acc)
+      return E_FAIL;
+
+    *ppv = NS_STATIC_CAST(IAccessibleAction*, this);
+    (NS_REINTERPRET_CAST(IUnknown*, *ppv))->AddRef();
+    return S_OK;
+  }
+
+  return E_NOINTERFACE;
+}
+
+// IAccessibleAction
+
+STDMETHODIMP
+CAccessibleAction::nActions(long *aNumActions)
+{
+  nsCOMPtr<nsIAccessible> acc(do_QueryInterface(this));
+  if (!acc)
+    return E_FAIL;
+
+  PRUint8 count = 0;
+  nsresult rv = acc->GetNumActions(&count);
+  *aNumActions = count;
+
+  if (NS_SUCCEEDED(rv))
+    return NS_OK;
+  return E_FAIL;
+}
+
+STDMETHODIMP
+CAccessibleAction::doAction(long aActionIndex)
+{
+  nsCOMPtr<nsIAccessible> acc(do_QueryInterface(this));
+  if (!acc)
+    return E_FAIL;
+
+  PRUint8 index = NS_STATIC_CAST(PRUint8, aActionIndex);
+  if (NS_SUCCEEDED(acc->DoAction(index)))
+    return S_OK;
+  return E_FAIL;
+}
+
+STDMETHODIMP
+CAccessibleAction::get_description(long aActionIndex, BSTR *aDescription)
+{
+  *aDescription = NULL;
+
+  nsCOMPtr<nsIAccessible> acc(do_QueryInterface(this));
+  if (!acc)
+    return E_FAIL;
+
+  nsAutoString description;
+  PRUint8 index = NS_STATIC_CAST(PRUint8, aActionIndex);
+  if (NS_FAILED(acc->GetActionDescription(index, description)))
+    return E_FAIL;
+
+  if (!description.IsVoid()) {
+    return ::SysReAllocStringLen(aDescription, description.get(),
+                                 description.Length());
+  }
+
+  return S_OK;
+}
+
+STDMETHODIMP
+CAccessibleAction::get_keyBinding(long aActionIndex, long aNumMaxBinding,
+                                 BSTR **aKeyBinding,
+                                 long *aNumBinding)
+{
+  *aKeyBinding = NULL;
+  aNumBinding = 0;
+
+  nsCOMPtr<nsIAccessible> acc(do_QueryInterface(this));
+  if (!acc)
+    return E_FAIL;
+
+  nsCOMPtr<nsIDOMDOMStringList> keys;
+  PRUint8 index = NS_STATIC_CAST(PRUint8, aActionIndex);
+  nsresult rv = acc->GetKeyBindings(index, getter_AddRefs(keys));
+  if (NS_FAILED(rv))
+    return E_FAIL;
+
+  PRUint32 length = 0;
+  keys->GetLength(&length);
+
+  PRBool aUseNumMaxBinding = length > NS_STATIC_CAST(PRUint32, aNumMaxBinding);
+
+  PRUint32 maxBinding = NS_STATIC_CAST(PRUint32, aNumMaxBinding);
+
+  PRUint32 numBinding = length > maxBinding ? maxBinding : length;
+  *aNumBinding = numBinding;
+
+  *aKeyBinding = new BSTR[numBinding];
+  if (!*aKeyBinding)
+    return E_OUTOFMEMORY;
+
+  for (PRUint32 i = 0; i < numBinding; i++) {
+    nsAutoString key;
+    keys->Item(i, key);
+    HRESULT hr = ::SysReAllocStringLen(aKeyBinding[i], key.get(),
+                                       key.Length());
+    if (FAILED(hr))
+      return hr;
+  }
+
+  return S_OK;
+}
+
+STDMETHODIMP
+CAccessibleAction::get_name(long aActionIndex, BSTR *aName)
+{
+  *aName = NULL;
+
+  nsCOMPtr<nsIAccessible> acc(do_QueryInterface(this));
+  if (!acc)
+    return E_FAIL;
+
+  nsAutoString name;
+  PRUint8 index = NS_STATIC_CAST(PRUint8, aActionIndex);
+  if (NS_FAILED(acc->GetActionName(index, name)))
+    return E_FAIL;
+
+  if (!name.IsVoid())
+    return ::SysReAllocStringLen(aName, name.get(), name.Length());
+
+  return S_OK;
+}
+
+STDMETHODIMP
+CAccessibleAction::get_localizedName(long aActionIndex, BSTR *aLocalizedName)
+{
+  return E_NOTIMPL;
+}
+
new file mode 100755
--- /dev/null
+++ b/accessible/src/msaa/CAccessibleAction.h
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _ACCESSIBLE_ACTION_H
+#define _ACCESSIBLE_ACTION_H
+
+#include "nsISupports.h"
+
+#include "AccessibleAction.h"
+
+class CAccessibleAction: public nsISupports,
+                         public IAccessibleAction
+{
+public:
+
+  // IUnknown
+  STDMETHODIMP QueryInterface(REFIID, void**);
+
+  // IAccessibleAction
+  virtual HRESULT STDMETHODCALLTYPE nActions(
+      /* [retval][out] */ long *nActions);
+
+  virtual HRESULT STDMETHODCALLTYPE doAction(
+      /* [in] */ long actionIndex);
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_description(
+      /* [in] */ long actionIndex,
+      /* [retval][out] */ BSTR *description);
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_keyBinding(
+      /* [in] */ long actionIndex,
+      /* [in] */ long nMaxBinding,
+      /* [length_is][length_is][size_is][size_is][out] */ BSTR **keyBinding,
+      /* [retval][out] */ long *nBinding);
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_name(
+      /* [in] */ long actionIndex,
+      /* [retval][out] */ BSTR *name);
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_localizedName(
+      /* [in] */ long actionIndex,
+      /* [retval][out] */ BSTR *localizedName);
+
+};
+
+
+#define FORWARD_IACCESSIBLEACTION(Class)                                       \
+virtual HRESULT STDMETHODCALLTYPE nActions(long *nActions)                     \
+{                                                                              \
+  return Class::nActions(nActions);                                            \
+}                                                                              \
+                                                                               \
+virtual HRESULT STDMETHODCALLTYPE doAction(long actionIndex)                   \
+{                                                                              \
+  return Class::doAction(actionIndex);                                         \
+}                                                                              \
+                                                                               \
+virtual HRESULT STDMETHODCALLTYPE get_description(long actionIndex,            \
+                                                  BSTR *description)           \
+{                                                                              \
+  return Class::get_description(actionIndex, description);                     \
+}                                                                              \
+                                                                               \
+virtual HRESULT STDMETHODCALLTYPE get_keyBinding(long actionIndex,             \
+                                                 long nMaxBinding,             \
+                                                 BSTR **keyBinding,            \
+                                                 long *nBinding)               \
+{                                                                              \
+  return Class::get_keyBinding(actionIndex, nMaxBinding, keyBinding, nBinding);\
+}                                                                              \
+                                                                               \
+virtual HRESULT STDMETHODCALLTYPE get_name(long actionIndex, BSTR *name)       \
+{                                                                              \
+  return Class::get_name(actionIndex, name);                                   \
+}                                                                              \
+                                                                               \
+virtual HRESULT STDMETHODCALLTYPE get_localizedName(long actionIndex,          \
+                                                    BSTR *localizedName)       \
+{                                                                              \
+  return Class::get_localizedName(actionIndex, localizedName);                 \
+}                                                                              \
+                                                                               \
+
+#endif
+
new file mode 100755
--- /dev/null
+++ b/accessible/src/msaa/CAccessibleHyperlink.cpp
@@ -0,0 +1,187 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "CAccessibleHyperlink.h"
+
+#include "Accessible2.h"
+#include "AccessibleHyperlink.h"
+#include "AccessibleHyperlink_i.c"
+
+#include "nsIAccessible.h"
+#include "nsIAccessibleHyperlink.h"
+#include "nsIWinAccessNode.h"
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+#include "nsIURI.h"
+
+// IUnknown
+
+STDMETHODIMP
+CAccessibleHyperlink::QueryInterface(REFIID iid, void** ppv)
+{
+  *ppv = NULL;
+
+  if (IID_IAccessibleHyperlink == iid) {
+    nsCOMPtr<nsIAccessibleHyperLink> acc(do_QueryInterface(this));
+    if (!acc)
+      return E_FAIL;
+
+    *ppv = NS_STATIC_CAST(IAccessibleHyperlink*, this);
+    (NS_REINTERPRET_CAST(IUnknown*, *ppv))->AddRef();
+    return S_OK;
+  }
+
+  return CAccessibleAction::QueryInterface(iid, ppv);
+}
+
+// IAccessibleHyperlink
+
+STDMETHODIMP
+CAccessibleHyperlink::get_anchor(long aIndex, VARIANT *aAnchor)
+{
+  VariantInit(aAnchor);
+
+  nsCOMPtr<nsIAccessibleHyperLink> acc(do_QueryInterface(this));
+  if (!acc)
+    return E_FAIL;
+
+  nsCOMPtr<nsIAccessible> anchor;
+  acc->GetObject(aIndex, getter_AddRefs(anchor));
+  if (!anchor)
+    return E_FAIL;
+
+  nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryInterface(anchor));
+  if (!winAccessNode)
+    return E_FAIL;
+
+  void *instancePtr = NULL;
+  nsresult rv =  winAccessNode->QueryNativeInterface(IID_IUnknown,
+                                                     &instancePtr);
+  if (NS_FAILED(rv))
+    return E_FAIL;
+
+  IUnknown *unknownPtr = NS_STATIC_CAST(IUnknown*, instancePtr);
+  aAnchor->ppunkVal = &unknownPtr;
+  aAnchor->vt = VT_UNKNOWN;
+
+  return S_OK;
+}
+
+STDMETHODIMP
+CAccessibleHyperlink::get_anchorTarget(long aIndex, VARIANT *aAnchorTarget)
+{
+  VariantInit(aAnchorTarget);
+
+  nsCOMPtr<nsIAccessibleHyperLink> acc(do_QueryInterface(this));
+  if (!acc)
+    return E_FAIL;
+
+  nsCOMPtr<nsIURI> uri;
+  nsresult rv = acc->GetURI(aIndex, getter_AddRefs(uri));
+  if (NS_SUCCEEDED(rv))
+    return E_FAIL;
+
+  nsCAutoString prePath;
+  rv = uri->GetPrePath(prePath);
+  if (NS_SUCCEEDED(rv))
+    return E_FAIL;
+
+  nsCAutoString path;
+  rv = uri->GetPath(path);
+  if (NS_SUCCEEDED(rv))
+    return E_FAIL;
+
+  nsAutoString stringURI;
+  AppendUTF8toUTF16(prePath, stringURI);
+  AppendUTF8toUTF16(path, stringURI);
+
+  aAnchorTarget->vt = VT_BSTR;
+  return ::SysReAllocStringLen(&aAnchorTarget->bstrVal, stringURI.get(),
+                               stringURI.Length());
+}
+
+STDMETHODIMP
+CAccessibleHyperlink::get_startIndex(long *aIndex)
+{
+  *aIndex = 0;
+
+  nsCOMPtr<nsIAccessibleHyperLink> acc(do_QueryInterface(this));
+  if (!acc)
+    return E_FAIL;
+
+  PRInt32 index = 0;
+  nsresult rv = acc->GetStartIndex(&index);
+  *aIndex = index;
+
+  return NS_FAILED(rv) ? E_FAIL : S_OK;
+}
+
+STDMETHODIMP
+CAccessibleHyperlink::get_endIndex(long *aIndex)
+{
+  *aIndex = 0;
+
+  nsCOMPtr<nsIAccessibleHyperLink> acc(do_QueryInterface(this));
+  if (!acc)
+    return E_FAIL;
+
+  PRInt32 index = 0;
+  nsresult rv = acc->GetEndIndex(&index);
+  *aIndex = index;
+
+  return NS_FAILED(rv) ? E_FAIL : S_OK;
+}
+
+STDMETHODIMP
+CAccessibleHyperlink::get_valid(boolean *aValid)
+{
+  nsCOMPtr<nsIAccessibleHyperLink> acc(do_QueryInterface(this));
+  if (!acc)
+    return E_FAIL;
+
+  PRBool isValid = PR_FALSE;
+  nsresult rv = acc->IsValid(&isValid);
+  *aValid = isValid;
+
+  return NS_FAILED(rv) ? E_FAIL : S_OK;
+}
+
new file mode 100755
--- /dev/null
+++ b/accessible/src/msaa/CAccessibleHyperlink.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=2:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _ACCESSIBLE_HYPERLINK_H
+#define _ACCESSIBLE_HYPERLINK_H
+
+#include "nsISupports.h"
+
+#include "CAccessibleAction.h"
+#include "AccessibleHyperlink.h"
+
+class CAccessibleHyperlink: public CAccessibleAction,
+                            public IAccessibleHyperlink
+{
+public:
+
+  // IUnknown
+  STDMETHODIMP QueryInterface(REFIID, void**);
+
+  // IAccessibleAction
+  FORWARD_IACCESSIBLEACTION(CAccessibleAction)
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_anchor(
+      /* [in] */ long index,
+      /* [retval][out] */ VARIANT *anchor);
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_anchorTarget(
+      /* [in] */ long index,
+      /* [retval][out] */ VARIANT *anchorTarget);
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_startIndex(
+      /* [retval][out] */ long *index);
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_endIndex(
+      /* [retval][out] */ long *index);
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_valid(
+      /* [retval][out] */ boolean *valid);
+
+};
+
+#endif
+
--- a/accessible/src/msaa/CAccessibleHypertext.cpp
+++ b/accessible/src/msaa/CAccessibleHypertext.cpp
@@ -36,17 +36,16 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "CAccessibleHypertext.h"
 
 #include "AccessibleHypertext_i.c"
-#include "AccessibleHyperlink_i.c"
 
 #include "nsIAccessibleHypertext.h"
 #include "nsIWinAccessNode.h"
 
 #include "nsCOMPtr.h"
 
 // IUnknown
 
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -73,19 +73,21 @@ CPPSRCS = \
   nsDocAccessibleWrap.cpp \
   nsRootAccessibleWrap.cpp \
   nsHTMLWin32ObjectAccessible.cpp \
   nsXULMenuAccessibleWrap.cpp \
   nsXULTreeAccessibleWrap.cpp \
   nsHyperTextAccessibleWrap.cpp \
   nsHTMLImageAccessibleWrap.cpp \
   nsHTMLTableAccessibleWrap.cpp \
+  CAccessibleAction.cpp \
   CAccessibleImage.cpp \
   CAccessibleText.cpp \
   CAccessibleEditableText.cpp \
+  CAccessibleHyperlink.cpp \
   CAccessibleHypertext.cpp \
   CAccessibleTable.cpp \
   CAccessibleValue.cpp \
   $(NULL)
 
 EXPORTS = \
   nsAccessNodeWrap.h \
   nsAccessibleWrap.h \
@@ -93,19 +95,21 @@ EXPORTS = \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsHTMLWin32ObjectAccessible.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
+  CAccessibleAction.h \
   CAccessibleImage.h \
   CAccessibleText.h \
   CAccessibleEditableText.h \
+  CAccessibleHyperlink.h \
   CAccessibleHypertext.h \
   CAccessibleTable.h \
   CAccessibleValue.h \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -40,17 +40,16 @@
 #include "nsAccessibilityAtoms.h"
 
 #include "nsIAccessibleDocument.h"
 #include "nsIAccessibleSelectable.h"
 #include "nsIAccessibleEvent.h"
 #include "nsIAccessibleWin32Object.h"
 
 #include "Accessible2_i.c"
-#include "AccessibleAction_i.c"
 #include "AccessibleStates.h"
 
 #include "nsIMutableArray.h"
 #include "nsIDOMDocument.h"
 #include "nsIFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsINameSpaceManager.h"
 #include "nsINodeInfo.h"
@@ -112,18 +111,22 @@ STDMETHODIMP nsAccessibleWrap::QueryInte
     long numChildren;
     get_accChildCount(&numChildren);
     if (numChildren > 0)  // Don't support this interface for leaf elements
       *ppv = NS_STATIC_CAST(IEnumVARIANT*, this);
   } else if (IID_IServiceProvider == iid)
     *ppv = NS_STATIC_CAST(IServiceProvider*, this);
   else if (IID_IAccessible2 == iid)
     *ppv = NS_STATIC_CAST(IAccessible2*, this);
-  else if (IID_IAccessibleAction == iid)
-    *ppv = NS_STATIC_CAST(IAccessibleAction*, this);
+
+  if (NULL == *ppv) {
+    HRESULT hr = CAccessibleHyperlink::QueryInterface(iid, ppv);
+    if (SUCCEEDED(hr))
+      return hr;
+  }
 
   if (NULL == *ppv) {
     HRESULT hr = CAccessibleValue::QueryInterface(iid, ppv);
     if (SUCCEEDED(hr))
       return hr;
   }
 
   if (NULL == *ppv)
@@ -1304,113 +1307,16 @@ nsAccessibleWrap::get_attributes(BSTR *a
     strAttrs.Append(value);
     strAttrs.Append(';');
   }
 
   *aAttributes = ::SysAllocString(strAttrs.get());
   return S_OK;
 }
 
-
-// IAccessibleAction
-
-STDMETHODIMP
-nsAccessibleWrap::nActions(long *aNumActions)
-{
-  PRUint8 count = 0;
-  nsresult rv = GetNumActions(&count);
-  *aNumActions = count;
-
-  if (NS_SUCCEEDED(rv))
-    return NS_OK;
-  return E_FAIL;
-}
-
-STDMETHODIMP
-nsAccessibleWrap::doAction(long aActionIndex)
-{
-  PRUint8 index = NS_STATIC_CAST(PRUint8, aActionIndex);
-  if (NS_SUCCEEDED(DoAction(index)))
-    return S_OK;
-  return E_FAIL;
-}
-
-STDMETHODIMP
-nsAccessibleWrap::get_description(long aActionIndex, BSTR *aDescription)
-{
-  *aDescription = NULL;
-
-  nsAutoString description;
-  PRUint8 index = NS_STATIC_CAST(PRUint8, aActionIndex);
-  if (NS_FAILED(GetActionDescription(index, description)))
-    return E_FAIL;
-
-  if (!description.IsVoid())
-    *aDescription = ::SysAllocString(description.get());
-
-  return S_OK;
-}
-
-STDMETHODIMP
-nsAccessibleWrap::get_keyBinding(long aActionIndex, long aNumMaxBinding,
-                                 BSTR **aKeyBinding,
-                                 long *aNumBinding)
-{
-  nsCOMPtr<nsIDOMDOMStringList> keys;
-  PRUint8 index = NS_STATIC_CAST(PRUint8, aActionIndex);
-  nsresult rv = GetKeyBindings(index, getter_AddRefs(keys));
-  if (NS_FAILED(rv))
-    return E_FAIL;
-
-  PRUint32 length = 0;
-  keys->GetLength(&length);
-
-  PRBool aUseNumMaxBinding = length > NS_STATIC_CAST(PRUint32, aNumMaxBinding);
-
-  PRUint32 maxBinding = NS_STATIC_CAST(PRUint32, aNumMaxBinding);
-
-  PRUint32 numBinding = length > maxBinding ? maxBinding : length;
-  *aNumBinding = numBinding;
-
-  *aKeyBinding = new BSTR[numBinding];
-  if (!*aKeyBinding)
-    return E_OUTOFMEMORY;
-
-  for (PRUint32 i = 0; i < numBinding; i++) {
-    nsAutoString key;
-    keys->Item(i, key);
-    *aKeyBinding[i] = ::SysAllocString(key.get());
-  }
-
-  return S_OK;
-}
-
-STDMETHODIMP
-nsAccessibleWrap::get_name(long aActionIndex, BSTR *aName)
-{
-  *aName = NULL;
-
-  nsAutoString name;
-  PRUint8 index = NS_STATIC_CAST(PRUint8, aActionIndex);
-  if (NS_FAILED(GetActionName(index, name)))
-    return E_FAIL;
-
-  if (!name.IsVoid())
-    *aName = ::SysAllocString(name.get());
-
-  return S_OK;
-}
-
-STDMETHODIMP
-nsAccessibleWrap::get_localizedName(long aActionIndex, BSTR *aLocalizedName)
-{
-  return E_NOTIMPL;
-}
-
-
 STDMETHODIMP
 nsAccessibleWrap::Clone(IEnumVARIANT FAR* FAR* ppenum)
 {
   // Clone could be bad, the cloned items aren't tracked for shutdown
   // Then again, as long as the client releases the items in time, we're okay
   *ppenum = nsnull;
 
   nsAccessibleWrap *accessibleWrap = new nsAccessibleWrap(mDOMNode, mWeakShell);
--- a/accessible/src/msaa/nsAccessibleWrap.h
+++ b/accessible/src/msaa/nsAccessibleWrap.h
@@ -41,17 +41,17 @@
  */
 
 #ifndef _nsAccessibleWrap_H_
 #define _nsAccessibleWrap_H_
 
 #include "nsCOMPtr.h"
 #include "nsAccessible.h"
 #include "Accessible2.h"
-#include "AccessibleAction.h"
+#include "CAccessibleHyperlink.h"
 #include "CAccessibleValue.h"
 
 #define DECL_IUNKNOWN_INHERITED                                               \
 public:                                                                       \
 STDMETHODIMP QueryInterface(REFIID, void**);                                  \
 
 #define IMPL_IUNKNOWN_QUERY_HEAD(Class)                                       \
 STDMETHODIMP                                                                  \
@@ -84,19 +84,19 @@ Class::QueryInterface(REFIID iid, void**
   IMPL_IUNKNOWN_QUERY_HEAD(Class)                                             \
   IMPL_IUNKNOWN_QUERY_ENTRY(I1);                                              \
   IMPL_IUNKNOWN_QUERY_ENTRY(I2);                                              \
   IMPL_IUNKNOWN_QUERY_ENTRY(Super)                                            \
   IMPL_IUNKNOWN_QUERY_TAIL                                                    \
 
 
 class nsAccessibleWrap : public nsAccessible,
+                         public CAccessibleHyperlink,
                          public CAccessibleValue,
                          public IAccessible2,
-                         public IAccessibleAction,
                          public IEnumVARIANT,
                          public IServiceProvider
 {
   public: // construction, destruction
     nsAccessibleWrap(nsIDOMNode*, nsIWeakReference *aShell);
     virtual ~nsAccessibleWrap();
 
     // nsISupports
@@ -258,41 +258,16 @@ class nsAccessibleWrap : public nsAccess
         /* [retval][out] */ long *indexInParent);
 
     virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_locale(
         /* [retval][out] */ IA2Locale *locale);
 
     virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_attributes(
         /* [retval][out] */ BSTR *attributes);
 
-  public: // IAccessibleAction
-    virtual HRESULT STDMETHODCALLTYPE nActions(
-        /* [retval][out] */ long *nActions);
-
-    virtual HRESULT STDMETHODCALLTYPE doAction(
-        /* [in] */ long actionIndex);
-
-    virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_description(
-        /* [in] */ long actionIndex,
-        /* [retval][out] */ BSTR *description);
-
-    virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_keyBinding(
-        /* [in] */ long actionIndex,
-        /* [in] */ long nMaxBinding,
-        /* [length_is][length_is][size_is][size_is][out] */ BSTR **keyBinding,
-        /* [retval][out] */ long *nBinding);
-
-    virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_name(
-        /* [in] */ long actionIndex,
-        /* [retval][out] */ BSTR *name);
-
-    virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_localizedName(
-        /* [in] */ long actionIndex,
-        /* [retval][out] */ BSTR *localizedName);
-
   public:   // IEnumVariantMethods
     virtual /* [local] */ HRESULT STDMETHODCALLTYPE Next( 
         /* [in] */ ULONG celt,
         /* [length_is][size_is][out] */ VARIANT __RPC_FAR *rgVar,
         /* [out] */ ULONG __RPC_FAR *pCeltFetched);
   
     virtual HRESULT STDMETHODCALLTYPE Skip( 
         /* [in] */ ULONG celt);