author Ryan VanderMeulen <>
Tue, 27 Sep 2016 17:31:59 -0400
changeset 360600 199ec9b92e148e7040e4fed2079e81bc5c5c1105
parent 359558 10611fcdd32e0592397302afae63f842359394cb
child 361833 7cc58d0708e7ee5f0c06bf0ef760a591153a6fef
permissions -rw-r--r--
Backed out changeset 5285464565a8 for landing with the wrong bug number in the commit message.

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at */

#ifndef mozilla_a11y_DocAccessibleParent_h
#define mozilla_a11y_DocAccessibleParent_h

#include "nsAccessibilityService.h"
#include "mozilla/a11y/PDocAccessibleParent.h"
#include "mozilla/a11y/ProxyAccessible.h"
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
#include "nsISupportsImpl.h"

namespace mozilla {
namespace a11y {

class xpcAccessibleGeneric;

 * These objects live in the main process and comunicate with and represent
 * an accessible document in a content process.
class DocAccessibleParent : public ProxyAccessible,
    public PDocAccessibleParent
  DocAccessibleParent() :
    ProxyAccessible(this), mParentDoc(nullptr),
    mTopLevel(false), mShutdown(false)
  { MOZ_COUNT_CTOR_INHERITED(DocAccessibleParent, ProxyAccessible); }
    MOZ_COUNT_DTOR_INHERITED(DocAccessibleParent, ProxyAccessible);
    MOZ_ASSERT(mChildDocs.Length() == 0);

  void SetTopLevel() { mTopLevel = true; }
  bool IsTopLevel() const { return mTopLevel; }

  bool IsShutdown() const { return mShutdown; }

   * Called when a message from a document in a child process notifies the main
   * process it is firing an event.
  virtual bool RecvEvent(const uint64_t& aID, const uint32_t& aType)

#if defined(XP_WIN)
  virtual bool RecvShowEventInfo(const ShowEventData& aData,
                                 nsTArray<MsaaMapping>* aNewMsaaIds) override;
  virtual bool RecvShowEvent(const ShowEventData& aData, const bool& aFromUser)
#endif // defined(XP_WIN)
  virtual bool RecvHideEvent(const uint64_t& aRootID, const bool& aFromUser)
  virtual bool RecvStateChangeEvent(const uint64_t& aID,
                                    const uint64_t& aState,
                                    const bool& aEnabled) override final;

  virtual bool RecvCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset)
    override final;

  virtual bool RecvTextChangeEvent(const uint64_t& aID, const nsString& aStr,
                                   const int32_t& aStart, const uint32_t& aLen,
                                   const bool& aIsInsert,
                                   const bool& aFromUser) override;

  virtual bool RecvSelectionEvent(const uint64_t& aID,
                                  const uint64_t& aWidgetID,
                                  const uint32_t& aType) override;

  virtual bool RecvRoleChangedEvent(const uint32_t& aRole) override final;

  virtual bool RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID) override;
  void Unbind()
    mParent = nullptr;
    if (DocAccessibleParent* parent = ParentDoc()) {

    mParentDoc = nullptr;

  virtual bool RecvShutdown() override;
  void Destroy();
  virtual void ActorDestroy(ActorDestroyReason aWhy) override
    if (!mShutdown)

   * Return the main processes representation of the parent document (if any)
   * of the document this object represents.
  DocAccessibleParent* ParentDoc() const { return mParentDoc; }

   * Called when a document in a content process notifies the main process of a
   * new child document.
  bool AddChildDoc(DocAccessibleParent* aChildDoc, uint64_t aParentID,
                   bool aCreating = true);

   * Called when the document in the content process this object represents
   * notifies the main process a child document has been removed.
  void RemoveChildDoc(DocAccessibleParent* aChildDoc)
    aChildDoc->mParentDoc = nullptr;
    MOZ_ASSERT(aChildDoc->mChildDocs.Length() == 0);

  void RemoveAccessible(ProxyAccessible* aAccessible)

   * Return the accessible for given id.
  ProxyAccessible* GetAccessible(uintptr_t aID)
    if (!aID)
      return this;

    ProxyEntry* e = mAccessibles.GetEntry(aID);
    return e ? e->mProxy : nullptr;

  const ProxyAccessible* GetAccessible(uintptr_t aID) const
    { return const_cast<DocAccessibleParent*>(this)->GetAccessible(aID); }

  size_t ChildDocCount() const { return mChildDocs.Length(); }
  const DocAccessibleParent* ChildDocAt(size_t aIdx) const
    { return mChildDocs[aIdx]; }

#if defined(XP_WIN)
  virtual bool RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
                            IAccessibleHolder* aParentCOMProxy,
                            uint32_t* aMsaaID) override;


  class ProxyEntry : public PLDHashEntryHdr
    explicit ProxyEntry(const void*) : mProxy(nullptr) {}
    ProxyEntry(ProxyEntry&& aOther) :
      mProxy(aOther.mProxy) { aOther.mProxy = nullptr; }
    ~ProxyEntry() { delete mProxy; }

    typedef uint64_t KeyType;
    typedef const void* KeyTypePointer;

    bool KeyEquals(const void* aKey) const
    { return mProxy->ID() == (uint64_t)aKey; }

    static const void* KeyToPointer(uint64_t aKey) { return (void*)aKey; }

    static PLDHashNumber HashKey(const void* aKey) { return (uint64_t)aKey; }

    enum { ALLOW_MEMMOVE = true };

    ProxyAccessible* mProxy;

  uint32_t AddSubtree(ProxyAccessible* aParent,
                      const nsTArray<AccessibleData>& aNewTree, uint32_t aIdx,
                      uint32_t aIdxInParent
#if defined(XP_WIN)
                      , nsTArray<MsaaMapping>* aNewMsaaIds
#endif // defined(XP_WIN)
  MOZ_MUST_USE bool CheckDocTree() const;
  xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy);

  nsTArray<DocAccessibleParent*> mChildDocs;
  DocAccessibleParent* mParentDoc;

   * Conceptually this is a map from IDs to proxies, but we store the ID in the
   * proxy object so we can't use a real map.
  nsTHashtable<ProxyEntry> mAccessibles;
  bool mTopLevel;
  bool mShutdown;