Bug 381302 - move application accessible to cross platform code, r=aaronlev, ginn.chen, sr=neil
authorsurkov.alexander@gmail.com
Fri, 01 Jun 2007 20:01:38 -0700
changeset 2063 61de7e21eeb57a0361c4645e7075539f0345f96d
parent 2062 8b0b71c447f10b5e1ede078fd3df44031f029386
child 2064 964ef6517ea65f7aa44327a8c394bbafd82e7bcf
push idunknown
push userunknown
push dateunknown
reviewersaaronlev, ginn.chen, neil
bugs381302
milestone1.9a6pre
Bug 381302 - move application accessible to cross platform code, r=aaronlev, ginn.chen, sr=neil
accessible/src/atk/nsAccessNodeWrap.cpp
accessible/src/atk/nsAccessibleWrap.cpp
accessible/src/atk/nsAppRootAccessible.cpp
accessible/src/atk/nsAppRootAccessible.h
accessible/src/atk/nsRootAccessibleWrap.cpp
accessible/src/atk/nsRootAccessibleWrap.h
accessible/src/base/Makefile.in
accessible/src/base/nsAccessNode.cpp
accessible/src/base/nsAccessNode.h
accessible/src/base/nsAccessibilityService.cpp
accessible/src/base/nsAccessible.h
accessible/src/base/nsApplicationAccessible.cpp
accessible/src/base/nsApplicationAccessible.h
accessible/src/base/nsDocAccessible.h
accessible/src/base/nsRootAccessible.cpp
accessible/src/base/nsRootAccessible.h
accessible/src/mac/Makefile.in
accessible/src/mac/nsApplicationAccessibleWrap.h
accessible/src/msaa/Makefile.in
accessible/src/msaa/nsApplicationAccessibleWrap.cpp
accessible/src/msaa/nsApplicationAccessibleWrap.h
accessible/src/other/Makefile.in
accessible/src/other/nsApplicationAccessibleWrap.h
--- a/accessible/src/atk/nsAccessNodeWrap.cpp
+++ b/accessible/src/atk/nsAccessNodeWrap.cpp
@@ -69,10 +69,10 @@ void nsAccessNodeWrap::InitAccessibility
   nsAccessNode::InitXPAccessibility();
 }
 
 void nsAccessNodeWrap::ShutdownAccessibility()
 {
   nsAccessNode::ShutdownXPAccessibility();
 
   // Shutdown accessibility for ATK
-  nsAppRootAccessible::Unload();
+  nsApplicationAccessibleWrap::Unload();
 }
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -36,18 +36,19 @@
  * 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 "nsMai.h"
 #include "nsAccessibleWrap.h"
-#include "nsAppRootAccessible.h"
+#include "nsAccessibleEventData.h"
 #include "nsString.h"
+#include "nsAutoPtr.h"
 #include "prprf.h"
 #include "nsRoleMap.h"
 #include "nsStateMap.h"
 
 #include "nsMaiInterfaceComponent.h"
 #include "nsMaiInterfaceAction.h"
 #include "nsMaiInterfaceText.h"
 #include "nsMaiInterfaceEditableText.h"
@@ -56,16 +57,18 @@
 #include "nsMaiInterfaceHypertext.h"
 #include "nsMaiInterfaceHyperlinkImpl.h"
 #include "nsMaiInterfaceTable.h"
 #include "nsXPCOMStrings.h"
 #include "nsComponentManagerUtils.h"
 #include "nsMaiInterfaceDocument.h"
 #include "nsMaiInterfaceImage.h"
 
+#include "nsAppRootAccessible.h"
+
 extern "C" GType g_atk_hyperlink_impl_type; //defined in nsAppRootAccessible.cpp
 
 /* MaiAtkObject */
 
 enum {
   ACTIVATE,
   CREATE,
   DEACTIVATE,
@@ -1081,17 +1084,22 @@ CheckMaiAtkObject(AtkObject *aAtkObj)
     NS_ENSURE_ARG(IS_MAI_OBJECT(aAtkObj));
     nsAccessibleWrap * tmpAccWrap = MAI_ATK_OBJECT(aAtkObj)->accWrap;
 
     // Check if AccessibleWrap was deconstructed
     if (tmpAccWrap == nsnull) {
         return NS_ERROR_NULL_POINTER;
     }
 
-    if (tmpAccWrap != nsAppRootAccessible::Create() && !tmpAccWrap->IsValidObject())
+    nsRefPtr<nsApplicationAccessibleWrap> appAccWrap =
+        nsAccessNode::GetApplicationAccessible();
+    nsAccessibleWrap* tmpAppAccWrap =
+        NS_STATIC_CAST(nsAccessibleWrap*, appAccWrap.get());
+
+    if (tmpAppAccWrap != tmpAccWrap && !tmpAccWrap->IsValidObject())
         return NS_ERROR_INVALID_POINTER;
 
     NS_ENSURE_TRUE(tmpAccWrap->GetAtkObject() == aAtkObj, NS_ERROR_FAILURE);
     return NS_OK;
 }
 
 // Check if aAtkObj is a valid MaiAtkObject, and return the nsAccessibleWrap
 // for it.
--- a/accessible/src/atk/nsAppRootAccessible.cpp
+++ b/accessible/src/atk/nsAppRootAccessible.cpp
@@ -39,30 +39,28 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsCOMPtr.h"
 #include "nsMai.h"
 #include "nsAppRootAccessible.h"
 #include "prlink.h"
 #include "nsIServiceManager.h"
+#include "nsAutoPtr.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;
 static const char sATKLibName[] = "libatk-1.0.so.0";
 static const char sATKHyperlinkImplGetTypeSymbol[] = "atk_hyperlink_impl_get_type";
 
-/* app root accessible */
-static nsAppRootAccessible *sAppRoot = nsnull;
-
 /* gail function pointer */
 static guint (* gail_add_global_event_listener) (GSignalEmissionHook listener,
                                                  const gchar *event_type);
 static void (* gail_remove_global_event_listener) (guint remove_listener);
 static AtkObject * (*gail_get_root) (void);
 
 /* maiutil */
 
@@ -429,17 +427,18 @@ mai_util_remove_key_event_listener (guin
     if (g_hash_table_size(key_listener_list) == 0) {
         gtk_key_snooper_remove(key_snooper_id);
     }
 }
 
 AtkObject *
 mai_util_get_root(void)
 {
-    nsAppRootAccessible *root = nsAppRootAccessible::Create();
+    nsRefPtr<nsApplicationAccessibleWrap> root =
+        nsAccessNode::GetApplicationAccessible();
 
     if (root)
         return root->GetAtkObject();
 
     // We've shutdown, try to use gail instead
     // (to avoid assert in spi_atk_tidy_windows())
     if (gail_get_root)
         return gail_get_root();
@@ -505,31 +504,31 @@ add_listener (GSignalEmissionHook listen
     else {
         g_warning("Invalid object type %s\n", object_type);
     }
     return rc;
 }
 
 static nsresult LoadGtkModule(GnomeAccessibilityModule& aModule);
 
-nsAppRootAccessible::nsAppRootAccessible():
-    nsAccessibleWrap(nsnull, nsnull),
-    mChildren(nsnull)
+// nsApplicationAccessibleWrap
+
+nsApplicationAccessibleWrap::nsApplicationAccessibleWrap():
+    nsApplicationAccessible()
 {
     MAI_LOG_DEBUG(("======Create AppRootAcc=%p\n", (void*)this));
 }
 
-nsAppRootAccessible::~nsAppRootAccessible()
+nsApplicationAccessibleWrap::~nsApplicationAccessibleWrap()
 {
     MAI_LOG_DEBUG(("======Destory AppRootAcc=%p\n", (void*)this));
 }
 
-/* virtual functions */
-
-NS_IMETHODIMP nsAppRootAccessible::Init()
+NS_IMETHODIMP
+nsApplicationAccessibleWrap::Init()
 {
     // load and initialize gail library
     nsresult rv = LoadGtkModule(sGail);
     if (NS_SUCCEEDED(rv)) {
         (*sGail.init)();
     }
     else {
         MAI_LOG_DEBUG(("Fail to load lib: %s\n", sGail.libName));
@@ -544,23 +543,22 @@ NS_IMETHODIMP nsAppRootAccessible::Init(
     rv = LoadGtkModule(sAtkBridge);
     if (NS_SUCCEEDED(rv)) {
         // init atk-bridge
         (*sAtkBridge.init)();
     }
     else
         MAI_LOG_DEBUG(("Fail to load lib: %s\n", sAtkBridge.libName));
 
-    mChildren = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
-    return rv;
+    return nsApplicationAccessible::Init();
 }
 
-/* static */ void nsAppRootAccessible::Unload()
+void
+nsApplicationAccessibleWrap::Unload()
 {
-    NS_IF_RELEASE(sAppRoot);
     if (sAtkBridge.lib) {
         // Do not shutdown/unload atk-bridge,
         // an exit function registered will take care of it
         // if (sAtkBridge.shutdown)
         //     (*sAtkBridge.shutdown)();
         // PR_UnloadLibrary(sAtkBridge.lib);
         sAtkBridge.lib = NULL;
         sAtkBridge.init = NULL;
@@ -578,160 +576,18 @@ NS_IMETHODIMP nsAppRootAccessible::Init(
         sGail.shutdown = NULL;
     }
     // if (sATKLib) {
     //     PR_UnloadLibrary(sATKLib);
     //     sATKLib = nsnull;
     // }
 }
 
-NS_IMETHODIMP nsAppRootAccessible::GetName(nsAString& _retval)
-{
-    nsCOMPtr<nsIStringBundleService> bundleService = 
-      do_GetService(NS_STRINGBUNDLE_CONTRACTID);
-
-    NS_ASSERTION(bundleService, "String bundle service must be present!");
-
-    nsCOMPtr<nsIStringBundle> bundle;
-    bundleService->CreateBundle("chrome://branding/locale/brand.properties",
-                                getter_AddRefs(bundle));
-    nsXPIDLString appName;
-
-    if (bundle) {
-      bundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
-                                getter_Copies(appName));
-    } else {
-      NS_WARNING("brand.properties not present, using default app name");
-      appName.AssignLiteral("Mozilla");
-    }
-
-    _retval.Assign(appName);
-    return NS_OK;
-}
-
-NS_IMETHODIMP nsAppRootAccessible::GetDescription(nsAString& aDescription)
-{
-    GetName(aDescription);
-    aDescription.AppendLiteral(" Root Accessible");
-    return NS_OK;
-}
-
-NS_IMETHODIMP nsAppRootAccessible::GetRole(PRUint32 *aRole)
-{
-    *aRole = nsIAccessibleRole::ROLE_APP_ROOT;
-    return NS_OK;
-}
-
-NS_IMETHODIMP nsAppRootAccessible::GetFinalRole(PRUint32 *aFinalRole)
-{
-    return GetRole(aFinalRole);
-}
-
 NS_IMETHODIMP
-nsAppRootAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
-{
-  *aState = 0;
-  if (aExtraState)
-    *aExtraState = 0;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsAppRootAccessible::GetParent(nsIAccessible **  aParent)
-{
-    *aParent = nsnull;
-    return NS_OK;
-}
-
-NS_IMETHODIMP nsAppRootAccessible::GetChildAt(PRInt32 aChildNum,
-                                              nsIAccessible **aChild)
-{
-    PRUint32 count = 0;
-    nsresult rv = NS_OK;
-    *aChild = nsnull;
-    if (mChildren)
-        rv = mChildren->GetLength(&count);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    if (aChildNum >= NS_STATIC_CAST(PRInt32, count) || count == 0)
-        return NS_ERROR_INVALID_ARG;
-
-    if (aChildNum < 0)
-        aChildNum = count - 1;
-
-    nsCOMPtr<nsIWeakReference> childWeakRef;
-    rv = mChildren->QueryElementAt(aChildNum, NS_GET_IID(nsIWeakReference),
-                                   getter_AddRefs(childWeakRef));
-    if (childWeakRef) {
-        MAI_LOG_DEBUG(("GetChildAt(%d), has weak ref\n", aChildNum));
-        nsCOMPtr<nsIAccessible> childAcc = do_QueryReferent(childWeakRef);
-        if (childAcc) {
-            MAI_LOG_DEBUG(("GetChildAt(%d), has Acc Child ref\n", aChildNum));
-            NS_IF_ADDREF(*aChild = childAcc);
-        }
-        else
-            MAI_LOG_DEBUG(("GetChildAt(%d), NOT has Acc Child ref\n",
-                           aChildNum));
-
-    }
-    else
-        MAI_LOG_DEBUG(("GetChildAt(%d), NOT has weak ref\n", aChildNum));
-    return rv;
-}
-
-void nsAppRootAccessible::CacheChildren()
-{
-    if (!mChildren) {
-        mAccChildCount = eChildCountUninitialized;
-        return;
-    }
-
-    if (mAccChildCount == eChildCountUninitialized) {
-        nsCOMPtr<nsISimpleEnumerator> enumerator;
-        mChildren->Enumerate(getter_AddRefs(enumerator));
-
-        nsCOMPtr<nsIWeakReference> childWeakRef;
-        nsCOMPtr<nsIAccessible> accessible;
-        nsCOMPtr<nsPIAccessible> previousAccessible;
-        PRBool hasMoreElements;
-        while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements))
-              && hasMoreElements) {
-            enumerator->GetNext(getter_AddRefs(childWeakRef));
-            accessible = do_QueryReferent(childWeakRef);
-            if (accessible) {
-                if (previousAccessible) {
-                    previousAccessible->SetNextSibling(accessible);
-                }
-                else {
-                    SetFirstChild(accessible);
-                }
-                previousAccessible = do_QueryInterface(accessible);
-                previousAccessible->SetParent(this);
-            }
-        }
-
-        PRUint32 count = 0;
-        mChildren->GetLength(&count);
-        mAccChildCount = NS_STATIC_CAST(PRInt32, count);
-    }
-}
-
-NS_IMETHODIMP nsAppRootAccessible::GetNextSibling(nsIAccessible * *aNextSibling) 
-{ 
-    *aNextSibling = nsnull; 
-    return NS_OK;  
-}
-
-NS_IMETHODIMP nsAppRootAccessible::GetPreviousSibling(nsIAccessible * *aPreviousSibling) 
-{
-    *aPreviousSibling = nsnull;
-    return NS_OK;  
-}
-
-NS_IMETHODIMP nsAppRootAccessible::GetNativeInterface(void **aOutAccessible)
+nsApplicationAccessibleWrap::GetNativeInterface(void **aOutAccessible)
 {
     *aOutAccessible = nsnull;
 
     if (!mAtkObject) {
         mAtkObject =
             NS_REINTERPRET_CAST(AtkObject *,
                                 g_object_new(MAI_TYPE_ATK_OBJECT, NULL));
         NS_ENSURE_TRUE(mAtkObject, NS_ERROR_OUT_OF_MEMORY);
@@ -741,25 +597,23 @@ NS_IMETHODIMP nsAppRootAccessible::GetNa
         mAtkObject->layer = ATK_LAYER_INVALID;
     }
 
     *aOutAccessible = mAtkObject;
     return NS_OK;
 }
 
 nsresult
-nsAppRootAccessible::AddRootAccessible(nsIAccessible *aRootAccWrap)
+nsApplicationAccessibleWrap::AddRootAccessible(nsIAccessible *aRootAccWrap)
 {
     NS_ENSURE_ARG_POINTER(aRootAccWrap);
 
-    nsresult rv = NS_ERROR_FAILURE;
-
     // add by weak reference
-    rv = mChildren->AppendElement(aRootAccWrap, PR_TRUE);
-    InvalidateChildren();
+    nsresult rv = nsApplicationAccessible::AddRootAccessible(aRootAccWrap);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     void* atkAccessible;
     aRootAccWrap->GetNativeInterface(&atkAccessible);
     atk_object_set_parent((AtkObject*)atkAccessible, mAtkObject);
     PRUint32 count = 0;
     mChildren->GetLength(&count);
     g_signal_emit_by_name(mAtkObject, "children_changed::add", count - 1,
                           atkAccessible, NULL);
@@ -773,17 +627,17 @@ nsAppRootAccessible::AddRootAccessible(n
         MAI_LOG_DEBUG(("\nAdd RootAcc=%p Failed, count=%d\n",
                        (void*)aRootAccWrap, count));
 #endif
 
     return rv;
 }
 
 nsresult
-nsAppRootAccessible::RemoveRootAccessible(nsIAccessible *aRootAccWrap)
+nsApplicationAccessibleWrap::RemoveRootAccessible(nsIAccessible *aRootAccWrap)
 {
     NS_ENSURE_ARG_POINTER(aRootAccWrap);
 
     PRUint32 index = 0;
     nsresult rv = NS_ERROR_FAILURE;
 
     // we must use weak ref to get the index
     nsCOMPtr<nsIWeakReference> weakPtr = do_GetWeakReference(aRootAccWrap);
@@ -811,42 +665,29 @@ nsAppRootAccessible::RemoveRootAccessibl
     NS_ENSURE_SUCCESS(rv, rv);
     rv = mChildren->RemoveElementAt(index);
 
 #endif
     InvalidateChildren();
     return rv;
 }
 
-nsAppRootAccessible *
-nsAppRootAccessible::Create()
+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) {
                 g_atk_hyperlink_impl_type = pfn_atk_hyperlink_impl_get_type();
             }
         }
         sATKChecked = PR_TRUE;
     }
-    if (!sAppRoot && gIsAccessibilityActive) {
-        sAppRoot = new nsAppRootAccessible();
-        NS_ASSERTION(sAppRoot, "OUT OF MEMORY");
-        if (sAppRoot) {
-            if (NS_FAILED(sAppRoot->Init())) {
-                delete sAppRoot;
-                sAppRoot = nsnull;
-            }
-            else
-                NS_IF_ADDREF(sAppRoot);
-        }
-    }
-    return sAppRoot;
 }
 
 static nsresult
 LoadGtkModule(GnomeAccessibilityModule& aModule)
 {
     NS_ENSURE_ARG(aModule.libName);
 
     if (!(aModule.lib = PR_LoadLibrary(aModule.libName))) {
--- a/accessible/src/atk/nsAppRootAccessible.h
+++ b/accessible/src/atk/nsAppRootAccessible.h
@@ -37,64 +37,32 @@
  * 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 __NS_APP_ROOT_ACCESSIBLE_H__
 #define __NS_APP_ROOT_ACCESSIBLE_H__
 
-#include "nsIMutableArray.h"
-#include "nsIAccessibleDocument.h"
-#include "nsAccessibilityService.h"
-#include "nsAccessibleWrap.h"
-#include "nsRootAccessibleWrap.h"
-
-#define MAI_TYPE_APP_ROOT (MAI_TYPE_ATK_OBJECT)
+#include "nsApplicationAccessible.h"
 
-/* nsAppRootAccessible is for the whole application of Mozilla.
- * Only one instance of nsAppRootAccessible exists for one Mozilla instance.
- * And this one should be created when Mozilla Startup (if accessibility
- * feature has been enabled) and destroyed when Mozilla Shutdown.
- *
- * All the accessibility objects for toplevel windows are direct children of
- * the nsAppRootAccessible instance.
- */
-class nsAppRootAccessible;
-class nsAppRootAccessible: public nsAccessibleWrap
+class nsApplicationAccessibleWrap: public nsApplicationAccessible
 {
 public:
-    virtual ~nsAppRootAccessible();
-
-    static nsAppRootAccessible *Create();
     static void Unload();
+    static void PreCreate();
 
 public:
-    nsAppRootAccessible();
-
-    /* virtual function from nsAccessNode */
-    NS_IMETHOD Init();
+    nsApplicationAccessibleWrap();
+    virtual ~nsApplicationAccessibleWrap();
 
-    /* virtual functions from nsAccessible */
-    NS_IMETHOD GetName(nsAString & aName);
-    NS_IMETHOD GetDescription(nsAString & aDescription);
-    NS_IMETHOD GetRole(PRUint32 *aRole);
-    NS_IMETHOD GetFinalRole(PRUint32 *aFinalRole);
-    NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
-    NS_IMETHOD GetParent(nsIAccessible * *aParent);
-    NS_IMETHOD GetNextSibling(nsIAccessible * *aNextSibling);
-    NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling);
-    NS_IMETHOD GetChildAt(PRInt32 aChildNum, nsIAccessible **aChild);
+    // nsPIAccessNode
+    NS_IMETHOD Init();
 
     // return the atk object for app root accessible
     NS_IMETHOD GetNativeInterface(void **aOutAccessible);
 
-    nsresult AddRootAccessible(nsIAccessible *aRootAccWrap);
-    nsresult RemoveRootAccessible(nsIAccessible *aRootAccWrap);
-
-protected:
-    virtual void CacheChildren();
-
-private:
-    nsCOMPtr<nsIMutableArray> mChildren;
+    // nsApplicationAccessible
+    virtual nsresult AddRootAccessible(nsIAccessible *aRootAccWrap);
+    virtual nsresult RemoveRootAccessible(nsIAccessible *aRootAccWrap);
 };
 
 #endif   /* __NS_APP_ROOT_ACCESSIBLE_H__ */
--- a/accessible/src/atk/nsRootAccessibleWrap.cpp
+++ b/accessible/src/atk/nsRootAccessibleWrap.cpp
@@ -36,70 +36,15 @@
  * 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 "nsMai.h"
 #include "nsRootAccessibleWrap.h"
-#include "nsAppRootAccessible.h"
-#include "nsIDOMWindow.h"
-#include "nsPIDOMWindow.h"
-#include "nsIDOMXULMultSelectCntrlEl.h"
-#include "nsIFocusController.h"
-
-#ifdef MOZ_XUL
-#include "nsIAccessibleTreeCache.h"
-#endif
-
-nsRootAccessibleWrap::nsRootAccessibleWrap(nsIDOMNode *aDOMNode,
-                                           nsIWeakReference* aShell):
-    nsRootAccessible(aDOMNode, aShell)
-{
-    MAI_LOG_DEBUG(("New Root Acc=%p\n", (void*)this));
-}
-
-NS_IMETHODIMP nsRootAccessibleWrap::Init()
-{
-    nsresult rv = nsRootAccessible::Init();
-    nsAppRootAccessible *root = nsAppRootAccessible::Create();
-    if (root) {
-        root->AddRootAccessible(this);
-    }
-    return rv;
-}
-
-nsRootAccessibleWrap::~nsRootAccessibleWrap()
-{
-    MAI_LOG_DEBUG(("Delete Root Acc=%p\n", (void*)this));
-}
-
-NS_IMETHODIMP nsRootAccessibleWrap::Shutdown()
-{
-    nsAppRootAccessible *root = nsAppRootAccessible::Create();
-    if (root) {
-        root->RemoveRootAccessible(this);
-        root = nsnull;
-    }
-    return nsRootAccessible::Shutdown();
-}
-
-NS_IMETHODIMP nsRootAccessibleWrap::GetParent(nsIAccessible **  aParent)
-{
-    nsAppRootAccessible *root = nsAppRootAccessible::Create();
-    nsresult rv = NS_OK;
-    if (root) {
-        NS_IF_ADDREF(*aParent = root);
-    }
-    else {
-        *aParent = nsnull;
-        rv = NS_ERROR_FAILURE;
-    }
-    return rv;
-}
 
 nsNativeRootAccessibleWrap::nsNativeRootAccessibleWrap(AtkObject *aAccessible):
     nsRootAccessible(nsnull, nsnull)
 {
     g_object_ref(aAccessible);
     nsAccessibleWrap::mAtkObject = aAccessible;
 }
--- a/accessible/src/atk/nsRootAccessibleWrap.h
+++ b/accessible/src/atk/nsRootAccessibleWrap.h
@@ -39,33 +39,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_ROOT_ACCESSIBLE_WRAP_H__
 #define __NS_ROOT_ACCESSIBLE_WRAP_H__
 
 #include "nsRootAccessible.h"
 
-/* nsRootAccessibleWrap is the accessible class for toplevel Window.
- * The instance of nsRootAccessibleWrap will be child of MaiAppRoot instance.
+typedef nsRootAccessible nsRootAccessibleWrap;
+
+/* nsNativeRootAccessibleWrap is the accessible class for gtk+ native window.
+ * The instance of nsNativeRootAccessibleWrap is a child of MaiAppRoot instance.
  * It is added into root when the toplevel window is created, and removed
  * from root when the toplevel window is destroyed.
  */
-
-class nsRootAccessibleWrap: public nsRootAccessible
-{
-public:
-    nsRootAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference* aShell);
-    virtual ~nsRootAccessibleWrap();
-
-    NS_IMETHOD Init();
-    NS_IMETHOD Shutdown();
-    NS_IMETHOD GetParent(nsIAccessible **  aParent);
-};
-
-// For gtk+ native window
 class nsNativeRootAccessibleWrap: public nsRootAccessible
 {
 public:
     nsNativeRootAccessibleWrap(AtkObject *aAccessible);
 };
 
 #endif   /* __NS_ROOT_ACCESSIBLE_WRAP_H__ */
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -80,16 +80,17 @@ CPPSRCS = \
   nsAccessibilityUtils.cpp \
   nsAccessibilityService.cpp \
   nsAccessible.cpp \
   nsAccessibleRelation.cpp \
   nsAccessibleTreeWalker.cpp \
   nsBaseWidgetAccessible.cpp \
   nsFormControlAccessible.cpp \
   nsRootAccessible.cpp \
+  nsApplicationAccessible.cpp \
   nsCaretAccessible.cpp \
   nsTextAccessible.cpp \
   $(NULL)
 
 EXPORTS = \
   nsRootAccessible.h \
   nsAccessibleEventData.h \
   nsAccessNode.h \
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -65,29 +65,37 @@
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsIStringBundle.h"
 #include "nsITimer.h"
 #include "nsRootAccessible.h"
 #include "nsIFocusController.h"
 #include "nsIObserverService.h"
 
+#ifdef MOZ_ACCESSIBILITY_ATK
+#include "nsAppRootAccessible.h"
+#else
+#include "nsApplicationAccessibleWrap.h"
+#endif
+
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 nsIStringBundle *nsAccessNode::gStringBundle = 0;
 nsIStringBundle *nsAccessNode::gKeyStringBundle = 0;
 nsITimer *nsAccessNode::gDoCommandTimer = 0;
 nsIDOMNode *nsAccessNode::gLastFocusedNode = 0;
 PRBool nsAccessNode::gIsAccessibilityActive = PR_FALSE;
 PRBool nsAccessNode::gIsCacheDisabled = PR_FALSE;
 PRBool nsAccessNode::gIsFormFillEnabled = PR_FALSE;
 nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> nsAccessNode::gGlobalDocAccessibleCache;
 
+nsApplicationAccessibleWrap *nsAccessNode::gApplicationAccessible = nsnull;
+
 nsIAccessibilityService *nsAccessNode::sAccService = nsnull;
 nsIAccessibilityService *nsAccessNode::GetAccService()
 {
   if (!sAccService) {
     nsresult rv = CallGetService("@mozilla.org/accessibilityService;1",
                                  &sAccService);
     NS_ASSERTION(NS_SUCCEEDED(rv), "No accessibility service");
   }
@@ -196,16 +204,39 @@ NS_IMETHODIMP nsAccessNode::GetUniqueID(
 
 NS_IMETHODIMP nsAccessNode::GetOwnerWindow(void **aWindow)
 {
   nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
   NS_ASSERTION(docAccessible, "No root accessible pointer back, Init() not called.");
   return docAccessible->GetWindowHandle(aWindow);
 }
 
+already_AddRefed<nsApplicationAccessibleWrap>
+nsAccessNode::GetApplicationAccessible()
+{
+  if (!gApplicationAccessible && gIsAccessibilityActive) {
+    nsApplicationAccessibleWrap::PreCreate();
+
+    gApplicationAccessible = new nsApplicationAccessibleWrap();
+    if (!gApplicationAccessible)
+      return nsnull;
+
+    NS_ADDREF(gApplicationAccessible);
+
+    nsresult rv = gApplicationAccessible->Init();
+    if (NS_FAILED(rv)) {
+      NS_RELEASE(gApplicationAccessible);
+      return nsnull;
+    }
+  }
+
+  NS_ADDREF(gApplicationAccessible);
+  return gApplicationAccessible;
+}
+
 void nsAccessNode::InitXPAccessibility()
 {
   if (gIsAccessibilityActive) {
     return;
   }
 
   nsCOMPtr<nsIStringBundleService> stringBundleService =
     do_GetService(NS_STRINGBUNDLE_CONTRACTID);
@@ -253,16 +284,17 @@ void nsAccessNode::ShutdownXPAccessibili
   if (!gIsAccessibilityActive) {
     return;
   }
   NS_IF_RELEASE(gStringBundle);
   NS_IF_RELEASE(gKeyStringBundle);
   NS_IF_RELEASE(gDoCommandTimer);
   NS_IF_RELEASE(gLastFocusedNode);
   NS_IF_RELEASE(sAccService);
+  NS_IF_RELEASE(gApplicationAccessible);
 
   ClearCache(gGlobalDocAccessibleCache);
 
   gIsAccessibilityActive = PR_FALSE;
   NotifyA11yInitOrShutdown();
 }
 
 already_AddRefed<nsIPresShell> nsAccessNode::GetPresShell()
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -59,16 +59,17 @@
 
 class nsIPresShell;
 class nsPresContext;
 class nsIAccessibleDocument;
 class nsIFrame;
 class nsIDOMNodeList;
 class nsITimer;
 class nsRootAccessible;
+class nsApplicationAccessibleWrap;
 
 #define ACCESSIBLE_BUNDLE_URL "chrome://global-platform/locale/accessible.properties"
 #define PLATFORM_KEYS_BUNDLE_URL "chrome://global-platform/locale/platformKeys.properties"
 
 /* hashkey wrapper using void* KeyType
  *
  * @see nsTHashtable::EntryType for specification
  */
@@ -101,16 +102,21 @@ class nsAccessNode: public nsIAccessNode
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIACCESSNODE
     NS_DECL_NSPIACCESSNODE
 
     static void InitXPAccessibility();
     static void ShutdownXPAccessibility();
 
+    /**
+     * Return an application accessible.
+     */
+    static already_AddRefed<nsApplicationAccessibleWrap> GetApplicationAccessible();
+
     // Static methods for handling per-document cache
     static void PutCacheEntry(nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode>& aCache, 
                               void* aUniqueID, nsIAccessNode *aAccessNode);
     static void GetCacheEntry(nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode>& aCache, void* aUniqueID, 
                               nsIAccessNode **aAccessNode);
     static void ClearCache(nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode>& aCache);
 
     static PLDHashOperator PR_CALLBACK ClearCacheEntry(const void* aKey, nsCOMPtr<nsIAccessNode>& aAccessNode, void* aUserArg);
@@ -177,12 +183,13 @@ protected:
     static PRBool gIsAccessibilityActive;
     static PRBool gIsCacheDisabled;
     static PRBool gIsFormFillEnabled;
 
     static nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> gGlobalDocAccessibleCache;
 
 private:
   static nsIAccessibilityService *sAccService;
+  static nsApplicationAccessibleWrap *gApplicationAccessible;
 };
 
 #endif
 
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -93,25 +93,27 @@
 #include "nsXULTreeAccessibleWrap.h"
 #endif
 
 // For native window support for object/embed/applet tags
 #ifdef XP_WIN
 #include "nsHTMLWin32ObjectAccessible.h"
 #endif
 
-#ifdef MOZ_ACCESSIBILITY_ATK
-#include "nsAppRootAccessible.h"
-#endif
-
 #ifndef DISABLE_XFORMS_HOOKS
 #include "nsXFormsFormControlsAccessible.h"
 #include "nsXFormsWidgetsAccessible.h"
 #endif
 
+#ifdef MOZ_ACCESSIBILITY_ATK
+#include "nsAppRootAccessible.h"
+#else
+#include "nsApplicationAccessibleWrap.h"
+#endif
+
 nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nsnull;
 
 /**
   * nsAccessibilityService
   */
 
 nsAccessibilityService::nsAccessibilityService()
 {
@@ -1594,32 +1596,38 @@ NS_IMETHODIMP nsAccessibilityService::Ad
 {
 #ifdef MOZ_ACCESSIBILITY_ATK
   nsNativeRootAccessibleWrap* rootAccWrap =
     new nsNativeRootAccessibleWrap((AtkObject*)aAtkAccessible);
 
   *aRootAccessible = NS_STATIC_CAST(nsIAccessible*, rootAccWrap);
   NS_ADDREF(*aRootAccessible);
 
-  nsAppRootAccessible *appRoot = nsAppRootAccessible::Create();
+  nsRefPtr<nsApplicationAccessibleWrap> appRoot =
+    nsAccessNode::GetApplicationAccessible();
+  NS_ENSURE_STATE(appRoot);
+
   appRoot->AddRootAccessible(*aRootAccessible);
 
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 }
 
 NS_IMETHODIMP nsAccessibilityService::RemoveNativeRootAccessible(nsIAccessible * aRootAccessible)
 {
 #ifdef MOZ_ACCESSIBILITY_ATK
   void* atkAccessible;
   aRootAccessible->GetNativeInterface(&atkAccessible);
 
-  nsAppRootAccessible *appRoot = nsAppRootAccessible::Create();
+  nsRefPtr<nsApplicationAccessibleWrap> appRoot =
+    nsAccessNode::GetApplicationAccessible();
+  NS_ENSURE_STATE(appRoot);
+
   appRoot->RemoveRootAccessible(aRootAccessible);
 
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 }
 
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -45,16 +45,17 @@
 #include "nsIAccessible.h"
 #include "nsPIAccessible.h"
 #include "nsIAccessibleHyperLink.h"
 #include "nsIAccessibleSelectable.h"
 #include "nsIAccessibleValue.h"
 #include "nsIAccessibleRole.h"
 #include "nsIAccessibleStates.h"
 #include "nsAccessibleRelationWrap.h"
+#include "nsIAccessibleEvent.h"
 
 #include "nsIDOMNodeList.h"
 #include "nsINameSpaceManager.h"
 #include "nsWeakReference.h"
 #include "nsString.h"
 #include "nsIDOMDOMStringList.h"
 
 struct nsRect;
new file mode 100755
--- /dev/null
+++ b/accessible/src/base/nsApplicationAccessible.cpp
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** 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):
+ *   Bolian Yin <bolian.yin@sun.com>
+ *   Ginn Chen <ginn.chen@sun.com>
+ *   Alexander Surkov <surkov.alexander@gmail.com>
+ *
+ * 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 "nsApplicationAccessible.h"
+
+#include "nsIComponentManager.h"
+#include "nsServiceManagerUtils.h"
+
+nsApplicationAccessible::nsApplicationAccessible():
+    nsAccessibleWrap(nsnull, nsnull), mChildren(nsnull)
+{
+}
+
+// nsISupports
+NS_IMPL_ISUPPORTS_INHERITED0(nsApplicationAccessible,
+                             nsAccessible)
+
+// nsIAccessNode
+NS_IMETHODIMP
+nsApplicationAccessible::Init()
+{
+  nsresult rv;
+  mChildren = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+  return rv;
+}
+
+// nsIAccessible
+
+NS_IMETHODIMP
+nsApplicationAccessible::GetName(nsAString& aName)
+{
+  nsCOMPtr<nsIStringBundleService> bundleService =
+    do_GetService(NS_STRINGBUNDLE_CONTRACTID);
+
+  NS_ASSERTION(bundleService, "String bundle service must be present!");
+  NS_ENSURE_STATE(bundleService);
+
+  nsCOMPtr<nsIStringBundle> bundle;
+  bundleService->CreateBundle("chrome://branding/locale/brand.properties",
+                              getter_AddRefs(bundle));
+
+  nsXPIDLString appName;
+  if (bundle) {
+    bundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
+                              getter_Copies(appName));
+  } else {
+    NS_WARNING("brand.properties not present, using default app name");
+    appName.AssignLiteral("Mozilla");
+  }
+
+  aName.Assign(appName);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsApplicationAccessible::GetDescription(nsAString& aDescription)
+{
+  GetName(aDescription);
+  aDescription.AppendLiteral(" Application Accessible");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsApplicationAccessible::GetRole(PRUint32 *aRole)
+{
+  *aRole = nsIAccessibleRole::ROLE_APP_ROOT;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsApplicationAccessible::GetFinalRole(PRUint32 *aFinalRole)
+{
+  return GetRole(aFinalRole);
+}
+
+NS_IMETHODIMP
+nsApplicationAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
+{
+  *aState = 0;
+  if (aExtraState)
+    *aExtraState = 0;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsApplicationAccessible::GetParent(nsIAccessible **aParent)
+{
+  *aParent = nsnull;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsApplicationAccessible::GetChildAt(PRInt32 aChildNum, nsIAccessible **aChild)
+{
+  NS_ENSURE_ARG_POINTER(aChild);
+  *aChild = nsnull;
+
+  PRUint32 count = 0;
+  nsresult rv = NS_OK;
+
+  if (mChildren) {
+    rv = mChildren->GetLength(&count);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (aChildNum >= NS_STATIC_CAST(PRInt32, count) || count == 0)
+    return NS_ERROR_INVALID_ARG;
+
+  if (aChildNum < 0)
+    aChildNum = count - 1;
+
+  nsCOMPtr<nsIWeakReference> childWeakRef;
+  rv = mChildren->QueryElementAt(aChildNum, NS_GET_IID(nsIWeakReference),
+                                 getter_AddRefs(childWeakRef));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (childWeakRef) {
+    nsCOMPtr<nsIAccessible> childAcc(do_QueryReferent(childWeakRef));
+    NS_IF_ADDREF(*aChild = childAcc);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsApplicationAccessible::GetNextSibling(nsIAccessible **aNextSibling)
+{
+  NS_ENSURE_ARG_POINTER(aNextSibling);
+
+  *aNextSibling = nsnull;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsApplicationAccessible::GetPreviousSibling(nsIAccessible **aPreviousSibling)
+{
+  NS_ENSURE_ARG_POINTER(aPreviousSibling);
+
+  *aPreviousSibling = nsnull;
+  return NS_OK;
+}
+
+void
+nsApplicationAccessible::CacheChildren()
+{
+  if (!mChildren) {
+    mAccChildCount = eChildCountUninitialized;
+    return;
+  }
+
+  if (mAccChildCount == eChildCountUninitialized) {
+    nsCOMPtr<nsISimpleEnumerator> enumerator;
+    mChildren->Enumerate(getter_AddRefs(enumerator));
+
+    nsCOMPtr<nsIWeakReference> childWeakRef;
+    nsCOMPtr<nsIAccessible> accessible;
+    nsCOMPtr<nsPIAccessible> previousAccessible;
+    PRBool hasMoreElements;
+    while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements))
+          && hasMoreElements) {
+      enumerator->GetNext(getter_AddRefs(childWeakRef));
+      accessible = do_QueryReferent(childWeakRef);
+      if (accessible) {
+        if (previousAccessible)
+          previousAccessible->SetNextSibling(accessible);
+        else
+          SetFirstChild(accessible);
+
+        previousAccessible = do_QueryInterface(accessible);
+        previousAccessible->SetParent(this);
+      }
+    }
+
+    PRUint32 count = 0;
+    mChildren->GetLength(&count);
+    mAccChildCount = NS_STATIC_CAST(PRInt32, count);
+  }
+}
+
+// nsApplicationAccessible
+
+nsresult
+nsApplicationAccessible::AddRootAccessible(nsIAccessible *aRootAccessible)
+{
+  NS_ENSURE_ARG_POINTER(aRootAccessible);
+
+  // add by weak reference
+  nsresult rv = mChildren->AppendElement(aRootAccessible, PR_TRUE);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  InvalidateChildren();
+  return NS_OK;
+}
+
+nsresult
+nsApplicationAccessible::RemoveRootAccessible(nsIAccessible *aRootAccessible)
+{
+  NS_ENSURE_ARG_POINTER(aRootAccessible);
+
+  PRUint32 index = 0;
+
+  // we must use weak ref to get the index
+  nsCOMPtr<nsIWeakReference> weakPtr = do_GetWeakReference(aRootAccessible);
+  nsresult rv = mChildren->IndexOf(0, weakPtr, &index);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = mChildren->RemoveElementAt(index);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  InvalidateChildren();
+  return NS_OK;
+}
+
new file mode 100755
--- /dev/null
+++ b/accessible/src/base/nsApplicationAccessible.h
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** 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):
+ *   Bolian Yin <bolian.yin@sun.com>
+ *   Ginn Chen <ginn.chen@sun.com>
+ *   Alexander Surkov <surkov.alexander@gmail.com>
+ *
+ * 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 __NS_APPLICATION_ACCESSIBLE_H__
+#define __NS_APPLICATION_ACCESSIBLE_H__
+
+#include "nsAccessibleWrap.h"
+#include "nsIMutableArray.h"
+
+/**
+ * nsApplicationAccessible is for the whole application of Mozilla.
+ * Only one instance of nsAppRootAccessible exists for one Mozilla instance.
+ * And this one should be created when Mozilla Startup (if accessibility
+ * feature has been enabled) and destroyed when Mozilla Shutdown.
+ *
+ * All the accessibility objects for toplevel windows are direct children of
+ * the nsApplicationAccessible instance.
+ */
+
+class nsApplicationAccessible: public nsAccessibleWrap
+{
+public:
+  nsApplicationAccessible();
+
+  // nsISupports
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // nsPIAccessNode
+  NS_IMETHOD Init();
+
+  // nsIAccessible
+  NS_IMETHOD GetName(nsAString & aName);
+  NS_IMETHOD GetDescription(nsAString & aDescription);
+  NS_IMETHOD GetRole(PRUint32 *aRole);
+  NS_IMETHOD GetFinalRole(PRUint32 *aFinalRole);
+  NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
+  NS_IMETHOD GetParent(nsIAccessible * *aParent);
+  NS_IMETHOD GetNextSibling(nsIAccessible * *aNextSibling);
+  NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling);
+  NS_IMETHOD GetChildAt(PRInt32 aChildNum, nsIAccessible **aChild);
+
+  // nsApplicationAccessible
+  virtual nsresult AddRootAccessible(nsIAccessible *aRootAccWrap);
+  virtual nsresult RemoveRootAccessible(nsIAccessible *aRootAccWrap);
+
+protected:
+  // nsAccessible
+  virtual void CacheChildren();
+
+  nsCOMPtr<nsIMutableArray> mChildren;
+};
+
+#endif
+
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -37,17 +37,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsDocAccessible_H_
 #define _nsDocAccessible_H_
 
 #include "nsHyperTextAccessibleWrap.h"
 #include "nsIAccessibleDocument.h"
 #include "nsPIAccessibleDocument.h"
-#include "nsIAccessibleEvent.h"
 #include "nsIDocument.h"
 #include "nsIDocumentObserver.h"
 #include "nsIEditor.h"
 #include "nsIObserver.h"
 #include "nsIScrollPositionListener.h"
 #include "nsITimer.h"
 #include "nsIWeakReference.h"
 #include "nsCOMArray.h"
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -79,16 +79,22 @@
 #include "nsIDOMDocumentEvent.h"
 
 #ifdef MOZ_XUL
 #include "nsXULTreeAccessible.h"
 #include "nsIXULDocument.h"
 #include "nsIXULWindow.h"
 #endif
 
+#ifdef MOZ_ACCESSIBILITY_ATK
+#include "nsAppRootAccessible.h"
+#else
+#include "nsApplicationAccessibleWrap.h"
+#endif
+
 // Expanded version of NS_IMPL_ISUPPORTS_INHERITED2 
 // so we can QI directly to concrete nsRootAccessible
 NS_IMPL_QUERY_HEAD(nsRootAccessible)
 NS_IMPL_QUERY_BODY(nsIDOMEventListener)
 if (aIID.Equals(NS_GET_IID(nsRootAccessible)))
   foundInterface = NS_REINTERPRET_CAST(nsISupports*, this);
 else
 NS_IMPL_QUERY_TAIL_INHERITING(nsDocAccessible)
@@ -142,18 +148,23 @@ NS_IMETHODIMP nsRootAccessible::GetName(
     return NS_OK;
   }
 
   return NS_ERROR_FAILURE;
 }
 
 /* readonly attribute nsIAccessible accParent; */
 NS_IMETHODIMP nsRootAccessible::GetParent(nsIAccessible * *aParent) 
-{ 
+{
+  NS_ENSURE_ARG_POINTER(aParent);
   *aParent = nsnull;
+
+  nsRefPtr<nsApplicationAccessibleWrap> root = GetApplicationAccessible();
+  NS_IF_ADDREF(*aParent = root);
+
   return NS_OK;
 }
 
 /* readonly attribute unsigned long accRole; */
 NS_IMETHODIMP nsRootAccessible::GetRole(PRUint32 *aRole) 
 { 
   if (!mDocument) {
     return NS_ERROR_FAILURE;
@@ -894,18 +905,36 @@ void nsRootAccessible::GetTargetNode(nsI
 
 void nsRootAccessible::FireFocusCallback(nsITimer *aTimer, void *aClosure)
 {
   nsRootAccessible *rootAccessible = NS_STATIC_CAST(nsRootAccessible*, aClosure);
   NS_ASSERTION(rootAccessible, "How did we get here without a root accessible?");
   rootAccessible->FireCurrentFocusEvent();
 }
 
+NS_IMETHODIMP
+nsRootAccessible::Init()
+{
+  nsresult rv = nsDocAccessibleWrap::Init();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsRefPtr<nsApplicationAccessibleWrap> root = GetApplicationAccessible();
+  NS_ENSURE_STATE(root);
+
+  root->AddRootAccessible(this);
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsRootAccessible::Shutdown()
 {
+  nsRefPtr<nsApplicationAccessibleWrap> root = GetApplicationAccessible();
+  NS_ENSURE_STATE(root);
+
+  root->RemoveRootAccessible(this);
+
   // Called manually or by nsAccessNode::LastRelease()
   if (!mWeakShell) {
     return NS_OK;  // Already shutdown
   }
   if (mFireFocusTimer) {
     mFireFocusTimer->Cancel();
     mFireFocusTimer = nsnull;
   }
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/base/nsRootAccessible.h
@@ -62,16 +62,17 @@ class nsRootAccessible : public nsDocAcc
                          public nsIDOMEventListener
 {
   NS_DECL_ISUPPORTS_INHERITED
 
   public:
     nsRootAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell);
     virtual ~nsRootAccessible();
 
+    // nsIAccessible
     NS_IMETHOD GetName(nsAString& aName);
     NS_IMETHOD GetParent(nsIAccessible * *aParent);
     NS_IMETHOD GetRole(PRUint32 *aRole);
     NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
     NS_IMETHOD GetAccessibleRelated(PRUint32 aRelationType,
                                     nsIAccessible **aRelated);
 
     // ----- nsPIAccessibleDocument -----------------------
@@ -79,16 +80,17 @@ class nsRootAccessible : public nsDocAcc
 
     // ----- nsIDOMEventListener --------------------------
     NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
 
     // nsIAccessibleDocument
     NS_IMETHOD GetCaretAccessible(nsIAccessible **aAccessibleCaret);
 
     // nsIAccessNode
+    NS_IMETHOD Init();
     NS_IMETHOD Shutdown();
 
     void ShutdownAll();
     
     NS_DECLARE_STATIC_IID_ACCESSOR(NS_ROOTACCESSIBLE_IMPL_CID)
 
     /**
       * Fire an accessible focus event for the current focusAccssible
--- a/accessible/src/mac/Makefile.in
+++ b/accessible/src/mac/Makefile.in
@@ -1,9 +1,9 @@
-# ***** BEGIN LICENSE BLOCK *****
+ # ***** 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,
@@ -80,16 +80,17 @@ EXPORTS = \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
   nsAccessibleRelationWrap.h \
+  nsApplicationAccessibleWrap.h \
   mozDocAccessible.h \
   mozAccessible.h \
   mozAccessibleWrapper.h \
   mozAccessibleProtocol.h \
   mozActionElements.h \
   mozTextAccessible.h \
   nsRoleMap.h \
   $(NULL)
new file mode 100755
--- /dev/null
+++ b/accessible/src/mac/nsApplicationAccessibleWrap.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** 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 __NS_APPLICATION_ACCESSIBLE_WRAP_H__
+#define __NS_APPLICATION_ACCESSIBLE_WRAP_H__
+
+#include "nsApplicationAccessible.h"
+
+class nsApplicationAccessibleWrap: public nsApplicationAccessible
+{
+public:
+  static void PreCreate() {}
+};
+
+#endif
+
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -74,16 +74,17 @@ CPPSRCS = \
   nsRootAccessibleWrap.cpp \
   nsHTMLWin32ObjectAccessible.cpp \
   nsXULMenuAccessibleWrap.cpp \
   nsXULTreeAccessibleWrap.cpp \
   nsHyperTextAccessibleWrap.cpp \
   nsHTMLImageAccessibleWrap.cpp \
   nsHTMLTableAccessibleWrap.cpp \
   nsAccessibleRelationWrap.cpp \
+  nsApplicationAccessibleWrap.cpp \
   CAccessibleAction.cpp \
   CAccessibleImage.cpp \
   CAccessibleComponent.cpp \
   CAccessibleText.cpp \
   CAccessibleEditableText.cpp \
   CAccessibleHyperlink.cpp \
   CAccessibleHypertext.cpp \
   CAccessibleTable.cpp \
@@ -98,16 +99,17 @@ EXPORTS = \
   nsRootAccessibleWrap.h \
   nsHTMLWin32ObjectAccessible.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
   nsAccessibleRelationWrap.h \
+  nsApplicationAccessibleWrap.h \
   CAccessibleAction.h \
   CAccessibleImage.h \
   CAccessibleComponent.h \
   CAccessibleText.h \
   CAccessibleEditableText.h \
   CAccessibleHyperlink.h \
   CAccessibleHypertext.h \
   CAccessibleTable.h \
new file mode 100755
--- /dev/null
+++ b/accessible/src/msaa/nsApplicationAccessibleWrap.cpp
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** 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 "nsApplicationAccessibleWrap.h"
+
+#include "AccessibleApplication_i.c"
+
+// nsISupports
+NS_IMPL_ISUPPORTS_INHERITED0(nsApplicationAccessibleWrap,
+                             nsApplicationAccessible)
+
+// IUnknown
+
+STDMETHODIMP
+nsApplicationAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
+{
+  *ppv = NULL;
+
+  if (IID_IAccessibleApplication == iid) {
+    *ppv = NS_STATIC_CAST(IAccessibleApplication*, this);
+    (NS_REINTERPRET_CAST(IUnknown*, *ppv))->AddRef();
+    return S_OK;
+  }
+
+  return nsAccessibleWrap::QueryInterface(iid, ppv);
+}
+
+// IAccessibleApplication
+
+STDMETHODIMP
+nsApplicationAccessibleWrap::get_appName(BSTR *aName)
+{
+  return E_NOTIMPL;
+}
+
+STDMETHODIMP
+nsApplicationAccessibleWrap::get_appVersion(BSTR *aVersion)
+{
+  return E_NOTIMPL;
+}
+
+STDMETHODIMP
+nsApplicationAccessibleWrap::get_toolkitName(BSTR *aName)
+{
+  return E_NOTIMPL;
+}
+
+STDMETHODIMP
+nsApplicationAccessibleWrap::get_toolkitVersion(BSTR *aVersion)
+{
+  return E_NOTIMPL;
+}
+
+// nsApplicationAccessibleWrap
+
+void
+nsApplicationAccessibleWrap::PreCreate()
+{
+}
+
new file mode 100755
--- /dev/null
+++ b/accessible/src/msaa/nsApplicationAccessibleWrap.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** 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 __NS_APPLICATION_ACCESSIBLE_WRAP_H__
+#define __NS_APPLICATION_ACCESSIBLE_WRAP_H__
+
+#include "nsApplicationAccessible.h"
+
+#include "AccessibleApplication.h"
+
+class nsApplicationAccessibleWrap: public nsApplicationAccessible,
+                                   public IAccessibleApplication
+{
+public:
+  // nsISupporst
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // IUnknown
+  STDMETHODIMP QueryInterface(REFIID, void**);
+
+  // IAccessibleApplication
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_appName(
+            /* [retval][out] */ BSTR *name);
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_appVersion(
+      /* [retval][out] */ BSTR *version);
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_toolkitName(
+      /* [retval][out] */ BSTR *name);
+
+  virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_toolkitVersion(
+          /* [retval][out] */ BSTR *version);
+
+public:
+  static void PreCreate();
+};
+
+#endif
+
--- a/accessible/src/other/Makefile.in
+++ b/accessible/src/other/Makefile.in
@@ -80,16 +80,17 @@ EXPORTS = \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
   nsHyperTextAccessibleWrap.h \
   nsHTMLImageAccessibleWrap.h \
   nsHTMLTableAccessibleWrap.h \
   nsAccessibleRelationWrap.h \
+  nsApplicationAccessibleWrap.h \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
new file mode 100755
--- /dev/null
+++ b/accessible/src/other/nsApplicationAccessibleWrap.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:expandtab:shiftwidth=4:tabstop=4:
+ */
+/* ***** 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 __NS_APPLICATION_ACCESSIBLE_WRAP_H__
+#define __NS_APPLICATION_ACCESSIBLE_WRAP_H__
+
+#include "nsApplicationAccessible.h"
+
+class nsApplicationAccessibleWrap: public nsApplicationAccessible
+{
+public:
+  static void PreCreate() {}
+};
+
+#endif
+