Bug 480317 - Provide a way for atk-based plugins to slot into our a11y tree, r=joshmoz, ginn, surkov, trev, patch=btaylor, mcarrion, mgorse
authorBrad Taylor <brad@getcoded.net>
Wed, 27 Apr 2011 22:42:18 +0900
changeset 68912 0c49216dd89f6b887dfcc8db8f2eb1baccc8582a
parent 68911 e4afb9b58f77a4e1b13fee57d5eb5eb6a36bbed9
child 68913 f9a978db810270a3ce6a10e4e581740c14997325
push id76
push userbzbarsky@mozilla.com
push dateTue, 05 Jul 2011 17:00:57 +0000
treeherdermozilla-beta@d3a2732c35f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoshmoz, ginn, surkov, trev
bugs480317
milestone6.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 480317 - Provide a way for atk-based plugins to slot into our a11y tree, r=joshmoz, ginn, surkov, trev, patch=btaylor, mcarrion, mgorse
accessible/src/atk/AtkSocketAccessible.cpp
accessible/src/atk/AtkSocketAccessible.h
accessible/src/atk/Makefile.in
accessible/src/atk/nsApplicationAccessibleWrap.cpp
accessible/src/atk/nsMaiInterfaceComponent.cpp
accessible/src/atk/nsMaiInterfaceComponent.h
accessible/src/base/nsAccessibilityService.cpp
dom/plugins/ipc/PPluginInstance.ipdl
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginInstanceChild.h
dom/plugins/ipc/PluginInstanceParent.cpp
other-licenses/atk-1.0/atk/atk.h
other-licenses/atk-1.0/atk/atkplug.h
other-licenses/atk-1.0/atk/atksocket.h
new file mode 100644
--- /dev/null
+++ b/accessible/src/atk/AtkSocketAccessible.cpp
@@ -0,0 +1,203 @@
+/* -*- 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
+ * Novell, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brad Taylor <brad@getcoded.net> (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 <atk/atk.h>
+#include "AtkSocketAccessible.h"
+#include "nsMai.h"
+#include "nsMaiInterfaceComponent.h"
+
+void (*AtkSocketAccessible::g_atk_socket_embed) (AtkSocket*, gchar*) = NULL;
+GType AtkSocketAccessible::g_atk_socket_type = G_TYPE_INVALID;
+const char* AtkSocketAccessible::sATKSocketEmbedSymbol = "atk_socket_embed";
+const char* AtkSocketAccessible::sATKSocketGetTypeSymbol = "atk_socket_get_type";
+
+bool AtkSocketAccessible::gCanEmbed = FALSE;
+
+/* MaiAtkSocket */
+
+#define MAI_TYPE_ATK_SOCKET              (mai_atk_socket_get_type ())
+#define MAI_ATK_SOCKET(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
+                                          MAI_TYPE_ATK_SOCKET, MaiAtkSocket))
+#define MAI_IS_ATK_SOCKET(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
+                                          MAI_TYPE_ATK_SOCKET))
+#define MAI_ATK_SOCKET_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass),\
+                                          MAI_TYPE_ATK_SOCKET,\
+                                          MaiAtkSocketClass))
+#define MAI_IS_ATK_SOCKET_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass),\
+                                          MAI_TYPE_ATK_SOCKET))
+#define MAI_ATK_SOCKET_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj),\
+                                          MAI_TYPE_ATK_SOCKET,\
+                                          MaiAtkSocketClass))
+
+typedef struct _MaiAtkSocket             MaiAtkSocket;
+typedef struct _MaiAtkSocketClass        MaiAtkSocketClass;
+
+struct _MaiAtkSocket
+{
+  AtkSocket parent;
+
+  nsAccessibleWrap* accWrap;
+};
+
+struct _MaiAtkSocketClass
+{
+  AtkSocketClass parent_class;
+};
+
+G_BEGIN_DECLS
+
+GType mai_atk_socket_get_type(void);
+AtkObject* mai_atk_socket_new(nsAccessibleWrap* aAccWrap);
+
+void mai_atk_component_iface_init(AtkComponentIface* aIface);
+AtkObject* mai_atk_socket_ref_accessible_at_point(AtkComponent *aComponent,
+                                                  gint aAccX,
+                                                  gint aAccY,
+                                                  AtkCoordType aCoordType);
+void mai_atk_socket_get_extents(AtkComponent* aComponent,
+                                gint* aAccX,
+                                gint* aAccY,
+                                gint* aAccWidth,
+                                gint* aAccHeight,
+                                AtkCoordType aCoordType);
+
+G_END_DECLS
+
+G_DEFINE_TYPE_EXTENDED(MaiAtkSocket, mai_atk_socket,
+                       AtkSocketAccessible::g_atk_socket_type, 0,
+                       G_IMPLEMENT_INTERFACE(ATK_TYPE_COMPONENT,
+                                             mai_atk_component_iface_init))
+
+void
+mai_atk_socket_class_init(MaiAtkSocketClass* aAcc)
+{
+}
+
+void
+mai_atk_socket_init(MaiAtkSocket* aAcc)
+{
+}
+
+AtkObject*
+mai_atk_socket_new(nsAccessibleWrap* aAccWrap)
+{
+  NS_ENSURE_TRUE(aAccWrap, NULL);
+
+  MaiAtkSocket* acc = nsnull;
+  acc = static_cast<MaiAtkSocket*>(g_object_new(MAI_TYPE_ATK_SOCKET, NULL));
+  NS_ENSURE_TRUE(acc, NULL);
+
+  acc->accWrap = aAccWrap;
+  return ATK_OBJECT(acc);
+}
+
+void
+mai_atk_component_iface_init(AtkComponentIface* aIface)
+{
+  NS_ASSERTION(aIface, "Invalid Interface");
+
+  aIface->ref_accessible_at_point = mai_atk_socket_ref_accessible_at_point;
+  aIface->get_extents = mai_atk_socket_get_extents;
+}
+
+AtkObject*
+mai_atk_socket_ref_accessible_at_point(AtkComponent* aComponent,
+                                       gint aX, gint aY,
+                                       AtkCoordType aCoordType)
+{
+  NS_ENSURE_TRUE(MAI_IS_ATK_SOCKET(aComponent), nsnull);
+
+  return refAccessibleAtPointHelper(MAI_ATK_SOCKET(aComponent)->accWrap,
+                                    aX, aY, aCoordType);
+}
+
+void
+mai_atk_socket_get_extents(AtkComponent* aComponent,
+                           gint* aX, gint* aY, gint* aWidth, gint* aHeight,
+                           AtkCoordType aCoordType)
+{
+  *aX = *aY = *aWidth = *aHeight = 0;
+
+  if (!MAI_IS_ATK_SOCKET(aComponent))
+    return;
+
+  getExtentsHelper(MAI_ATK_SOCKET(aComponent)->accWrap,
+                   aX, aY, aWidth, aHeight, aCoordType);
+}
+
+AtkSocketAccessible::AtkSocketAccessible(nsIContent* aContent,
+                                         nsIWeakReference* aShell,
+                                         const nsCString& aPlugId) :
+  nsAccessibleWrap(aContent, aShell)
+{
+  mAtkObject = mai_atk_socket_new(this);
+  if (!mAtkObject)
+    return;
+
+  // Embeds the children of an AtkPlug, specified by plugId, as the children of
+  // this socket.
+  // Using G_TYPE macros instead of ATK_SOCKET macros to avoid undefined
+  // symbols.
+  if (gCanEmbed && G_TYPE_CHECK_INSTANCE_TYPE(mAtkObject, g_atk_socket_type) &&
+      !aPlugId.IsVoid()) {
+    AtkSocket* accSocket =
+      G_TYPE_CHECK_INSTANCE_CAST(mAtkObject, g_atk_socket_type, AtkSocket);
+    g_atk_socket_embed(accSocket, (gchar*)aPlugId.get());
+  }
+}
+
+NS_IMETHODIMP
+AtkSocketAccessible::GetNativeInterface(void** aOutAccessible)
+{
+  *aOutAccessible = mAtkObject;
+  return NS_OK;
+}
+
+void
+AtkSocketAccessible::Shutdown()
+{
+  if (mAtkObject) {
+    if (MAI_IS_ATK_SOCKET(mAtkObject))
+      MAI_ATK_SOCKET(mAtkObject)->accWrap = nsnull;
+    g_object_unref(mAtkObject);
+    mAtkObject = nsnull;
+  }
+  nsAccessibleWrap::Shutdown();
+}
new file mode 100644
--- /dev/null
+++ b/accessible/src/atk/AtkSocketAccessible.h
@@ -0,0 +1,86 @@
+/* -*- 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
+ * Novell, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brad Taylor <brad@getcoded.net> (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 _AtkSocketAccessible_H_
+#define _AtkSocketAccessible_H_
+
+#include "nsAccessibleWrap.h"
+
+// This file gets included by nsAccessibilityService.cpp, which can't include
+// atk.h (or glib.h), so we can't rely on it being included.
+#ifdef __ATK_H__
+typedef void (*AtkSocketEmbedType) (AtkSocket*, gchar*);
+#else
+typedef void (*AtkSocketEmbedType) (void*, void*);
+#endif
+
+/**
+ * Provides a nsAccessibleWrap wrapper around AtkSocket for out-of-process
+ * accessibles.
+ */
+class AtkSocketAccessible: public nsAccessibleWrap
+{
+public:
+
+  // Soft references to AtkSocket
+  static AtkSocketEmbedType g_atk_socket_embed;
+#ifdef __ATK_H__
+  static GType g_atk_socket_type;
+#endif
+  static const char* sATKSocketEmbedSymbol;
+  static const char* sATKSocketGetTypeSymbol;
+
+  /*
+   * True if the current Atk version supports AtkSocket and it was correctly
+   * loaded.
+   */
+  static bool gCanEmbed;
+
+  AtkSocketAccessible(nsIContent* aContent, nsIWeakReference* aShell,
+                      const nsCString& aPlugId);
+
+  // nsAccessNode
+  virtual void Shutdown();
+
+  // nsIAccessible
+  NS_IMETHODIMP GetNativeInterface(void** aOutAccessible);
+};
+
+#endif
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -43,16 +43,17 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_toolkit_s
 EXPORT_LIBRARY = ..
 LIBXUL_LIBRARY = 1
 
 
 CPPSRCS = \
+  AtkSocketAccessible.cpp \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
   nsDocAccessibleWrap.cpp \
   nsRootAccessibleWrap.cpp \
   nsApplicationAccessibleWrap.cpp \
   nsMaiInterfaceComponent.cpp \
   nsMaiInterfaceAction.cpp \
   nsMaiInterfaceText.cpp \
@@ -63,16 +64,17 @@ CPPSRCS = \
   nsMaiInterfaceHypertext.cpp \
   nsMaiInterfaceHyperlinkImpl.cpp \
   nsMaiInterfaceTable.cpp \
   nsMaiInterfaceDocument.cpp \
   nsMaiInterfaceImage.cpp \
   $(NULL)
 
 EXPORTS = \
+  AtkSocketAccessible.h \
   nsAccessNodeWrap.h \
   nsARIAGridAccessibleWrap.h \
   nsAccessibleWrap.h \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsTextAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULListboxAccessibleWrap.h \
--- a/accessible/src/atk/nsApplicationAccessibleWrap.cpp
+++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp
@@ -44,16 +44,17 @@
 #include "nsCOMPtr.h"
 #include "nsMai.h"
 #include "prlink.h"
 #include "prenv.h"
 #include "nsIPrefBranch.h"
 #include "nsIServiceManager.h"
 #include "nsAutoPtr.h"
 #include "nsAccessibilityService.h"
+#include "AtkSocketAccessible.h"
 
 #include <gtk/gtk.h>
 #include <atk/atk.h>
 
 typedef GType (* AtkGetTypeType) (void);
 GType g_atk_hyperlink_impl_type = G_TYPE_INVALID;
 static PRBool sATKChecked = PR_FALSE;
 static PRLibrary *sATKLib = nsnull;
@@ -717,18 +718,33 @@ nsApplicationAccessibleWrap::RemoveChild
 
 void
 nsApplicationAccessibleWrap::PreCreate()
 {
     if (!sATKChecked) {
         sATKLib = PR_LoadLibrary(sATKLibName);
         if (sATKLib) {
             AtkGetTypeType pfn_atk_hyperlink_impl_get_type = (AtkGetTypeType) PR_FindFunctionSymbol(sATKLib, sATKHyperlinkImplGetTypeSymbol);
-            if (pfn_atk_hyperlink_impl_get_type) {
+            if (pfn_atk_hyperlink_impl_get_type)
                 g_atk_hyperlink_impl_type = pfn_atk_hyperlink_impl_get_type();
+
+            AtkGetTypeType pfn_atk_socket_get_type;
+            pfn_atk_socket_get_type = (AtkGetTypeType)
+                                      PR_FindFunctionSymbol(sATKLib,
+                                                            AtkSocketAccessible::sATKSocketGetTypeSymbol);
+            if (pfn_atk_socket_get_type) {
+                AtkSocketAccessible::g_atk_socket_type =
+                  pfn_atk_socket_get_type();
+                AtkSocketAccessible::g_atk_socket_embed = (AtkSocketEmbedType)
+                  PR_FindFunctionSymbol(sATKLib,
+                                        AtkSocketAccessible
+                                          ::sATKSocketEmbedSymbol);
+            AtkSocketAccessible::gCanEmbed =
+              AtkSocketAccessible::g_atk_socket_type != G_TYPE_INVALID &&
+              AtkSocketAccessible::g_atk_socket_embed;
             }
         }
         sATKChecked = PR_TRUE;
     }
 }
 
 static nsresult
 LoadGtkModule(GnomeAccessibilityModule& aModule)
--- a/accessible/src/atk/nsMaiInterfaceComponent.cpp
+++ b/accessible/src/atk/nsMaiInterfaceComponent.cpp
@@ -1,10 +1,10 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim:expandtab:shiftwidth=4:tabstop=4:
+/* -*- 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/
@@ -62,81 +62,89 @@ componentInterfaceInitCB(AtkComponentIfa
      * Use default implementation in atk for contains, get_position,
      * and get_size
      */
     aIface->ref_accessible_at_point = refAccessibleAtPointCB;
     aIface->get_extents = getExtentsCB;
     aIface->grab_focus = grabFocusCB;
 }
 
-AtkObject *
-refAccessibleAtPointCB(AtkComponent *aComponent,
-                       gint aAccX, gint aAccY,
+AtkObject*
+refAccessibleAtPointCB(AtkComponent* aComponent, gint aAccX, gint aAccY,
                        AtkCoordType aCoordType)
 {
-    nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aComponent));
-    if (!accWrap || nsAccUtils::MustPrune(accWrap))
-        return nsnull;
-
-    // nsIAccessible getChildAtPoint (x,y) is in screen pixels.
-    if (aCoordType == ATK_XY_WINDOW) {
-        nsIntPoint winCoords =
-          nsCoreUtils::GetScreenCoordsForWindow(accWrap->GetNode());
-        aAccX += winCoords.x;
-        aAccY += winCoords.y;
-    }
-
-    nsCOMPtr<nsIAccessible> pointAcc;
-    accWrap->GetChildAtPoint(aAccX, aAccY, getter_AddRefs(pointAcc));
-    if (!pointAcc) {
-        return nsnull;
-    }
-
-    AtkObject *atkObj = nsAccessibleWrap::GetAtkObject(pointAcc);
-    if (atkObj) {
-        g_object_ref(atkObj);
-    }
-    return atkObj;
+  return refAccessibleAtPointHelper(GetAccessibleWrap(ATK_OBJECT(aComponent)),
+                                    aAccX, aAccY, aCoordType);
 }
 
 void
-getExtentsCB(AtkComponent *aComponent,
-             gint *aAccX,
-             gint *aAccY,
-             gint *aAccWidth,
-             gint *aAccHeight,
-             AtkCoordType aCoordType)
+getExtentsCB(AtkComponent* aComponent, gint* aX, gint* aY,
+             gint* aWidth, gint* aHeight, AtkCoordType aCoordType)
 {
-    *aAccX = *aAccY = *aAccWidth = *aAccHeight = 0;
-
-    nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aComponent));
-    if (!accWrap)
-        return;
-
-    PRInt32 nsAccX, nsAccY, nsAccWidth, nsAccHeight;
-    // Returned in screen coordinates
-    nsresult rv = accWrap->GetBounds(&nsAccX, &nsAccY,
-                                     &nsAccWidth, &nsAccHeight);
-    if (NS_FAILED(rv))
-        return;
-    if (aCoordType == ATK_XY_WINDOW) {
-        nsIntPoint winCoords =
-          nsCoreUtils::GetScreenCoordsForWindow(accWrap->GetNode());
-        nsAccX -= winCoords.x;
-        nsAccY -= winCoords.y;
-    }
-
-    *aAccX = nsAccX;
-    *aAccY = nsAccY;
-    *aAccWidth = nsAccWidth;
-    *aAccHeight = nsAccHeight;
+  getExtentsHelper(GetAccessibleWrap(ATK_OBJECT(aComponent)),
+                   aX, aY, aWidth, aHeight, aCoordType);
 }
 
 gboolean
-grabFocusCB(AtkComponent *aComponent)
+grabFocusCB(AtkComponent* aComponent)
+{
+  nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aComponent));
+  if (!accWrap)
+    return FALSE;
+
+  nsresult rv = accWrap->TakeFocus();
+  return (NS_FAILED(rv)) ? FALSE : TRUE;
+}
+
+AtkObject*
+refAccessibleAtPointHelper(nsAccessibleWrap* aAccWrap, gint aX, gint aY,
+                           AtkCoordType aCoordType)
 {
-    nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aComponent));
-    if (!accWrap)
-        return FALSE;
+  if (!aAccWrap || aAccWrap->IsDefunct() || nsAccUtils::MustPrune(aAccWrap))
+    return nsnull;
+
+  // nsAccessible::GetChildAtPoint(x,y) is in screen pixels.
+  if (aCoordType == ATK_XY_WINDOW) {
+    nsIntPoint winCoords =
+      nsCoreUtils::GetScreenCoordsForWindow(aAccWrap->GetNode());
+    aX += winCoords.x;
+    aY += winCoords.y;
+  }
+
+  nsAccessible* accAtPoint = aAccWrap->GetChildAtPoint(aX, aY,
+                                                       nsAccessible::eDirectChild);
+  if (!accAtPoint)
+    return nsnull;
+
+  AtkObject* atkObj = nsAccessibleWrap::GetAtkObject(accAtPoint);
+  if (atkObj)
+    g_object_ref(atkObj);
+  return atkObj;
+}
 
-    nsresult rv = accWrap->TakeFocus();
-    return (NS_FAILED(rv)) ? FALSE : TRUE;
+void
+getExtentsHelper(nsAccessibleWrap* aAccWrap,
+                 gint* aX, gint* aY, gint* aWidth, gint* aHeight,
+                 AtkCoordType aCoordType)
+{
+  *aX = *aY = *aWidth = *aHeight = 0;
+
+  if (!aAccWrap || aAccWrap->IsDefunct())
+    return;
+
+  PRInt32 x = 0, y = 0, width = 0, height = 0;
+  // Returned in screen coordinates
+  nsresult rv = aAccWrap->GetBounds(&x, &y, &width, &height);
+  if (NS_FAILED(rv))
+    return;
+
+  if (aCoordType == ATK_XY_WINDOW) {
+    nsIntPoint winCoords =
+      nsCoreUtils::GetScreenCoordsForWindow(aAccWrap->GetNode());
+    x -= winCoords.x;
+    y -= winCoords.y;
+  }
+
+  *aX = x;
+  *aY = y;
+  *aWidth = width;
+  *aHeight = height;
 }
--- a/accessible/src/atk/nsMaiInterfaceComponent.h
+++ b/accessible/src/atk/nsMaiInterfaceComponent.h
@@ -1,10 +1,10 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim:expandtab:shiftwidth=4:tabstop=4:
+/* -*- 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/
@@ -41,36 +41,40 @@
 #ifndef __MAI_INTERFACE_COMPONENT_H__
 #define __MAI_INTERFACE_COMPONENT_H__
 
 #include "nsMai.h"
 
 G_BEGIN_DECLS
 
 /* component interface callbacks */
-void componentInterfaceInitCB(AtkComponentIface *aIface);
-AtkObject *refAccessibleAtPointCB(AtkComponent *aComponent,
-                                  gint aAccX, gint aAccY,
+void componentInterfaceInitCB(AtkComponentIface* aIface);
+AtkObject* refAccessibleAtPointCB(AtkComponent* aComponent,
+                                  gint aX, gint aY,
                                   AtkCoordType aCoordType);
-void getExtentsCB(AtkComponent *aComponent,
-                  gint *aAccX, gint *aAccY,
-                  gint *aAccWidth, gint *aAccHeight,
+void getExtentsCB(AtkComponent* aComponent,
+                  gint* aX, gint* aY, gint* aWidth, gint* aHeight,
                   AtkCoordType aCoordType);
 /* the "contains", "get_position", "get_size" can take advantage of
  * "get_extents", there is no need to implement them now.
  */
-gboolean grabFocusCB(AtkComponent *aComponent);
+gboolean grabFocusCB(AtkComponent* aComponent);
 
-/* what are missing now for atk component */
-
-/* ==================================================
+/* what are missing now for atk component:
+ *
  * add_focus_handler
  * remove_focus_handler
  * set_extents
  * set_position
  * set_size
  * get_layer
  * get_mdi_zorder
- * ==================================================
  */
+
+AtkObject* refAccessibleAtPointHelper(nsAccessibleWrap* aAccWrap,
+                                      gint aX, gint aY, AtkCoordType aCoordType);
+void getExtentsHelper(nsAccessibleWrap* aAccWrap,
+                      gint* aX, gint* aY, gint* aWidth, gint* aHeight,
+                      AtkCoordType aCoordType);
+
 G_END_DECLS
 
 #endif /* __MAI_INTERFACE_COMPONENT_H__ */
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -90,16 +90,21 @@
 #include "nsXULTreeGridAccessibleWrap.h"
 #endif
 
 // For native window support for object/embed/applet tags
 #ifdef XP_WIN
 #include "nsHTMLWin32ObjectAccessible.h"
 #endif
 
+// For embedding plugin accessibles
+#ifdef MOZ_ACCESSIBILITY_ATK
+#include "AtkSocketAccessible.h"
+#endif
+
 #ifndef DISABLE_XFORMS_HOOKS
 #include "nsXFormsFormControlsAccessible.h"
 #include "nsXFormsWidgetsAccessible.h"
 #endif
 
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/dom/Element.h"
 #include "nsImageMapUtils.h"
@@ -334,30 +339,47 @@ nsAccessibilityService::CreateHTMLObject
   nsCOMPtr<nsIDOMHTMLObjectElement> obj(do_QueryInterface(aContent));
   if (obj) {
     nsCOMPtr<nsIDOMDocument> domDoc;
     obj->GetContentDocument(getter_AddRefs(domDoc));
     if (domDoc)
       return CreateOuterDocAccessible(aContent, aPresShell);
   }
 
-#ifdef XP_WIN
+#if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
   // 2) for plugins
-  nsCOMPtr<nsIPluginInstance> pluginInstance ;
-  aFrame->GetPluginInstance(*getter_AddRefs(pluginInstance));
-  if (pluginInstance) {
+  nsCOMPtr<nsIPluginInstance> pluginInstance;
+  if (NS_SUCCEEDED(aFrame->GetPluginInstance(*getter_AddRefs(pluginInstance))) &&
+      pluginInstance) {
+#ifdef XP_WIN
     // Note: pluginPort will be null if windowless.
     HWND pluginPort = nsnull;
     aFrame->GetPluginPort(&pluginPort);
 
     nsAccessible* accessible = new nsHTMLWin32ObjectOwnerAccessible(aContent,
                                                                     weakShell,
                                                                     pluginPort);
     NS_IF_ADDREF(accessible);
     return accessible;
+
+#elif MOZ_ACCESSIBILITY_ATK
+    if (!AtkSocketAccessible::gCanEmbed)
+      return nsnull;
+
+    nsCString plugId;
+    nsresult rv = pluginInstance->GetValueFromPlugin(
+      NPPVpluginNativeAccessibleAtkPlugId, &plugId);
+    if (NS_SUCCEEDED(rv) && !plugId.IsVoid()) {
+      AtkSocketAccessible* socketAccessible =
+        new AtkSocketAccessible(aContent, weakShell, plugId);
+
+      NS_IF_ADDREF(socketAccessible);
+      return socketAccessible;
+    }
+#endif
   }
 #endif
 
   // 3) for images and imagemaps, or anything else with a child frame
   // we have the object frame, get the image frame
   nsIFrame* frame = aFrame->GetFirstChild(nsnull);
   return frame ? frame->CreateAccessible() : nsnull;
 }
--- a/dom/plugins/ipc/PPluginInstance.ipdl
+++ b/dom/plugins/ipc/PPluginInstance.ipdl
@@ -99,16 +99,18 @@ child:
 
   // this message is not used on non-X platforms
   rpc NPP_GetValue_NPPVpluginNeedsXEmbed()
     returns (bool value, NPError result);
   rpc NPP_GetValue_NPPVpluginScriptableNPObject()
     returns (nullable PPluginScriptableObject value, NPError result);
 
   rpc NPP_SetValue_NPNVprivateModeBool(bool value) returns (NPError result);
+  rpc NPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId()
+    returns (nsCString plug_id, NPError result);
 
   rpc NPP_HandleEvent(NPRemoteEvent event)
     returns (int16_t handled);
   // special cases where we need to a shared memory buffer
   rpc NPP_HandleEvent_Shmem(NPRemoteEvent event, Shmem buffer)
     returns (int16_t handled, Shmem rtnbuffer);
   // special cases where we need an iosurface
   rpc NPP_HandleEvent_IOSurface(NPRemoteEvent event, uint32_t surfaceid)
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -582,16 +582,45 @@ PluginInstanceChild::AnswerNPP_GetValue_
     }
 
     *aValue = nsnull;
     *aResult = result;
     return true;
 }
 
 bool
+PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId(
+                                          nsCString* aPlugId,
+                                          NPError* aResult)
+{
+    AssertPluginThread();
+
+#if MOZ_ACCESSIBILITY_ATK
+
+    char* plugId = NULL;
+    NPError result = NPERR_GENERIC_ERROR;
+    if (mPluginIface->getvalue) {
+        result = mPluginIface->getvalue(GetNPP(),
+                                        NPPVpluginNativeAccessibleAtkPlugId,
+                                        &plugId);
+    }
+
+    *aPlugId = nsCString(plugId);
+    *aResult = result;
+    return true;
+
+#else
+
+    NS_RUNTIMEABORT("shouldn't be called on non-ATK platforms");
+    return false;
+
+#endif
+}
+
+bool
 PluginInstanceChild::AnswerNPP_SetValue_NPNVprivateModeBool(const bool& value,
                                                             NPError* result)
 {
     if (!mPluginIface->setvalue) {
         *result = NPERR_GENERIC_ERROR;
         return true;
     }
 
--- a/dom/plugins/ipc/PluginInstanceChild.h
+++ b/dom/plugins/ipc/PluginInstanceChild.h
@@ -87,17 +87,19 @@ class PluginInstanceChild : public PPlug
 protected:
     virtual bool AnswerNPP_SetWindow(const NPRemoteWindow& window);
 
     virtual bool
     AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(bool* needs, NPError* rv);
     virtual bool
     AnswerNPP_GetValue_NPPVpluginScriptableNPObject(PPluginScriptableObjectChild** value,
                                                     NPError* result);
-
+    virtual bool
+    AnswerNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId(nsCString* aPlugId,
+                                                     NPError* aResult);
     virtual bool
     AnswerNPP_SetValue_NPNVprivateModeBool(const bool& value, NPError* result);
 
     virtual bool
     AnswerNPP_HandleEvent(const NPRemoteEvent& event, int16_t* handled);
     virtual bool
     AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event, Shmem& mem, int16_t* handled, Shmem* rtnmem);
     virtual bool
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -956,16 +956,33 @@ PluginInstanceParent::NPP_GetValue(NPPVa
         NPObject* object =
             static_cast<PluginScriptableObjectParent*>(actor)->GetObject(true);
         NS_ASSERTION(object, "This shouldn't ever be null!");
 
         (*(NPObject**)_retval) = npn->retainobject(object);
         return NPERR_NO_ERROR;
     }
 
+#ifdef MOZ_ACCESSIBILITY_ATK
+    case NPPVpluginNativeAccessibleAtkPlugId: {
+        nsCString plugId;
+        NPError rv;
+        if (!CallNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId(&plugId, &rv)) {
+            return NPERR_GENERIC_ERROR;
+        }
+
+        if (NPERR_NO_ERROR != rv) {
+            return rv;
+        }
+
+        (*(nsCString*)_retval) = plugId;
+        return NPERR_NO_ERROR;
+    }
+#endif
+
     default:
         PR_LOG(gPluginLog, PR_LOG_WARNING,
                ("In PluginInstanceParent::NPP_GetValue: Unhandled NPPVariable %i (%s)",
                 (int) aVariable, NPPVariableToString(aVariable)));
         return NPERR_GENERIC_ERROR;
     }
 }
 
--- a/other-licenses/atk-1.0/atk/atk.h
+++ b/other-licenses/atk-1.0/atk/atk.h
@@ -15,35 +15,41 @@
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
 
 #ifndef __ATK_H__
 #define __ATK_H__
 
+#define __ATK_H_INSIDE__
+
 #include <atk/atkobject.h>
 #include <atk/atkaction.h>
 #include <atk/atkcomponent.h>
 #include <atk/atkdocument.h>
 #include <atk/atkeditabletext.h>
 #include <atk/atkgobjectaccessible.h>
 #include <atk/atkhyperlink.h>
 #include <atk/atkhyperlinkimpl.h>
 #include <atk/atkhypertext.h>
 #include <atk/atkimage.h>
 #include <atk/atknoopobject.h>
 #include <atk/atknoopobjectfactory.h>
 #include <atk/atkobjectfactory.h>
+#include <atk/atkplug.h>
 #include <atk/atkregistry.h>
 #include <atk/atkrelation.h>
 #include <atk/atkrelationset.h>
 #include <atk/atkrelationtype.h>
 #include <atk/atkselection.h>
+#include <atk/atksocket.h>
 #include <atk/atkstate.h>
 #include <atk/atkstateset.h>
 #include <atk/atkstreamablecontent.h>
 #include <atk/atktable.h>
 #include <atk/atktext.h>
 #include <atk/atkutil.h>
 #include <atk/atkvalue.h>
 
+#undef __ATK_H_INSIDE__
+
 #endif /* __ATK_H__ */
new file mode 100644
--- /dev/null
+++ b/other-licenses/atk-1.0/atk/atkplug.h
@@ -0,0 +1,61 @@
+/* ATK -  Accessibility Toolkit
+ * Copyright 2009 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if defined(ATK_DISABLE_SINGLE_INCLUDES) && !defined (__ATK_H_INSIDE__) && !defined (ATK_COMPILATION)
+#error "Only <atk/atk.h> can be included directly."
+#endif
+
+#ifndef __ATK_PLUG_H__
+#define __ATK_PLUG_H__
+
+G_BEGIN_DECLS
+
+#define ATK_TYPE_PLUG               (atk_plug_get_type ())
+#define ATK_PLUG(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATK_TYPE_PLUG, AtkPlug))
+#define ATK_IS_PLUG(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATK_TYPE_PLUG))
+#define ATK_PLUG_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), ATK_TYPE_PLUG, AtkPlugClass))
+#define ATK_IS_PLUG_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), ATK_TYPE_PLUG))
+#define ATK_PLUG_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), ATK_TYPE_PLUG, AtkPlugClass))
+
+typedef struct _AtkPlug         AtkPlug;
+typedef struct _AtkPlugClass    AtkPlugClass;
+
+struct _AtkPlug
+{
+  AtkObject parent;
+};
+
+GType atk_plug_get_type (void);
+
+struct _AtkPlugClass
+{
+  AtkObjectClass parent_class;
+  
+  /* to be subscribed to by atk-bridge */
+
+  /*< protected >*/
+  gchar* (* get_object_id) (AtkPlug* obj);
+};
+
+AtkObject*    atk_plug_new     (void);
+gchar*        atk_plug_get_id  (AtkPlug* plug);
+
+G_END_DECLS
+
+#endif /* __ATK_PLUG_H__ */
new file mode 100644
--- /dev/null
+++ b/other-licenses/atk-1.0/atk/atksocket.h
@@ -0,0 +1,65 @@
+/* ATK -  Accessibility Toolkit
+ * Copyright 2009 Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if defined(ATK_DISABLE_SINGLE_INCLUDES) && !defined (__ATK_H_INSIDE__) && !defined (ATK_COMPILATION)
+#error "Only <atk/atk.h> can be included directly."
+#endif
+
+#ifndef __ATK_SOCKET_H__
+#define __ATK_SOCKET_H__
+
+G_BEGIN_DECLS
+
+#define ATK_TYPE_SOCKET               (atk_socket_get_type ())
+#define ATK_SOCKET(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATK_TYPE_SOCKET, AtkSocket))
+#define ATK_IS_SOCKET(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ATK_TYPE_SOCKET))
+#define ATK_SOCKET_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), ATK_TYPE_SOCKET, AtkSocketClass))
+#define ATK_IS_SOCKET_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), ATK_TYPE_SOCKET))
+#define ATK_SOCKET_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), ATK_TYPE_SOCKET, AtkSocketClass))
+
+typedef struct _AtkSocket         AtkSocket;
+typedef struct _AtkSocketClass    AtkSocketClass;
+
+struct _AtkSocket
+{
+  AtkObject parent;
+
+  /*< private >*/
+  gchar* embedded_plug_id;
+};
+
+GType atk_socket_get_type (void);
+
+struct _AtkSocketClass
+{
+  AtkObjectClass parent_class;
+  
+  /* to be subscribed to by atk-bridge */
+
+  /*< protected >*/
+  void (* embed) (AtkSocket *obj, gchar* plug_id);
+};
+
+AtkObject*    atk_socket_new           (void);
+void          atk_socket_embed         (AtkSocket* obj, gchar* plug_id);
+gboolean      atk_socket_is_occupied   (AtkSocket* obj);
+
+G_END_DECLS
+
+#endif /* __ATK_SOCKET_H__ */