LCOV - code coverage report
Current view: top level - accessible/ipc - DocAccessibleParent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 288 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "DocAccessibleParent.h"
       8             : #include "mozilla/a11y/Platform.h"
       9             : #include "mozilla/dom/TabParent.h"
      10             : #include "xpcAccessibleDocument.h"
      11             : #include "xpcAccEvents.h"
      12             : #include "nsAccUtils.h"
      13             : #include "nsCoreUtils.h"
      14             : 
      15             : #if defined(XP_WIN)
      16             : #include "AccessibleWrap.h"
      17             : #include "Compatibility.h"
      18             : #include "nsWinUtils.h"
      19             : #include "RootAccessible.h"
      20             : #endif
      21             : 
      22             : namespace mozilla {
      23             : namespace a11y {
      24             : uint64_t DocAccessibleParent::sMaxDocID = 0;
      25             : 
      26             : mozilla::ipc::IPCResult
      27           0 : DocAccessibleParent::RecvShowEvent(const ShowEventData& aData,
      28             :                                    const bool& aFromUser)
      29             : {
      30           0 :   if (mShutdown)
      31           0 :     return IPC_OK();
      32             : 
      33           0 :   MOZ_ASSERT(CheckDocTree());
      34             : 
      35           0 :   if (aData.NewTree().IsEmpty()) {
      36           0 :     return IPC_FAIL(this, "No children being added");
      37             :   }
      38             : 
      39           0 :   ProxyAccessible* parent = GetAccessible(aData.ID());
      40             : 
      41             :   // XXX This should really never happen, but sometimes we fail to fire the
      42             :   // required show events.
      43           0 :   if (!parent) {
      44           0 :     NS_ERROR("adding child to unknown accessible");
      45             : #ifdef DEBUG
      46           0 :     return IPC_FAIL(this, "unknown parent accessible");
      47             : #else
      48             :     return IPC_OK();
      49             : #endif
      50             :   }
      51             : 
      52           0 :   uint32_t newChildIdx = aData.Idx();
      53           0 :   if (newChildIdx > parent->ChildrenCount()) {
      54           0 :     NS_ERROR("invalid index to add child at");
      55             : #ifdef DEBUG
      56           0 :     return IPC_FAIL(this, "invalid index");
      57             : #else
      58             :     return IPC_OK();
      59             : #endif
      60             :   }
      61             : 
      62           0 :   uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx);
      63           0 :   MOZ_ASSERT(consumed == aData.NewTree().Length());
      64             : 
      65             :   // XXX This shouldn't happen, but if we failed to add children then the below
      66             :   // is pointless and can crash.
      67           0 :   if (!consumed) {
      68           0 :     return IPC_FAIL(this, "failed to add children");
      69             :   }
      70             : 
      71             : #ifdef DEBUG
      72           0 :   for (uint32_t i = 0; i < consumed; i++) {
      73           0 :     uint64_t id = aData.NewTree()[i].ID();
      74           0 :     MOZ_ASSERT(mAccessibles.GetEntry(id));
      75             :   }
      76             : #endif
      77             : 
      78           0 :   MOZ_ASSERT(CheckDocTree());
      79             : 
      80           0 :   ProxyAccessible* target = parent->ChildAt(newChildIdx);
      81           0 :   ProxyShowHideEvent(target, parent, true, aFromUser);
      82             : 
      83           0 :   if (!nsCoreUtils::AccEventObserversExist()) {
      84           0 :     return IPC_OK();
      85             :   }
      86             : 
      87           0 :   uint32_t type = nsIAccessibleEvent::EVENT_SHOW;
      88           0 :   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target);
      89           0 :   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
      90           0 :   nsIDOMNode* node = nullptr;
      91             :   RefPtr<xpcAccEvent> event = new xpcAccEvent(type, xpcAcc, doc, node,
      92           0 :                                               aFromUser);
      93           0 :   nsCoreUtils::DispatchAccEvent(Move(event));
      94             : 
      95           0 :   return IPC_OK();
      96             : }
      97             : 
      98             : uint32_t
      99           0 : DocAccessibleParent::AddSubtree(ProxyAccessible* aParent,
     100             :                                 const nsTArray<a11y::AccessibleData>& aNewTree,
     101             :                                 uint32_t aIdx, uint32_t aIdxInParent)
     102             : {
     103           0 :   if (aNewTree.Length() <= aIdx) {
     104           0 :     NS_ERROR("bad index in serialized tree!");
     105           0 :     return 0;
     106             :   }
     107             : 
     108           0 :   const AccessibleData& newChild = aNewTree[aIdx];
     109           0 :   if (newChild.Role() > roles::LAST_ROLE) {
     110           0 :     NS_ERROR("invalid role");
     111           0 :     return 0;
     112             :   }
     113             : 
     114           0 :   if (mAccessibles.Contains(newChild.ID())) {
     115           0 :     NS_ERROR("ID already in use");
     116           0 :     return 0;
     117             :   }
     118             : 
     119           0 :   auto role = static_cast<a11y::role>(newChild.Role());
     120             : 
     121             :   ProxyAccessible* newProxy =
     122           0 :     new ProxyAccessible(newChild.ID(), aParent, this, role,
     123           0 :                         newChild.Interfaces());
     124             : 
     125           0 :   aParent->AddChildAt(aIdxInParent, newProxy);
     126           0 :   mAccessibles.PutEntry(newChild.ID())->mProxy = newProxy;
     127           0 :   ProxyCreated(newProxy, newChild.Interfaces());
     128             : 
     129             : #if defined(XP_WIN)
     130             :   WrapperFor(newProxy)->SetID(newChild.MsaaID());
     131             : #endif
     132             : 
     133           0 :   uint32_t accessibles = 1;
     134           0 :   uint32_t kids = newChild.ChildrenCount();
     135           0 :   for (uint32_t i = 0; i < kids; i++) {
     136           0 :     uint32_t consumed = AddSubtree(newProxy, aNewTree, aIdx + accessibles, i);
     137           0 :     if (!consumed)
     138           0 :       return 0;
     139             : 
     140           0 :     accessibles += consumed;
     141             :   }
     142             : 
     143           0 :   MOZ_ASSERT(newProxy->ChildrenCount() == kids);
     144             : 
     145           0 :   return accessibles;
     146             : }
     147             : 
     148             : mozilla::ipc::IPCResult
     149           0 : DocAccessibleParent::RecvHideEvent(const uint64_t& aRootID,
     150             :                                    const bool& aFromUser)
     151             : {
     152           0 :   if (mShutdown)
     153           0 :     return IPC_OK();
     154             : 
     155           0 :   MOZ_ASSERT(CheckDocTree());
     156             : 
     157             :   // We shouldn't actually need this because mAccessibles shouldn't have an
     158             :   // entry for the document itself, but it doesn't hurt to be explicit.
     159           0 :   if (!aRootID) {
     160           0 :     return IPC_FAIL(this, "Trying to hide entire document?");
     161             :   }
     162             : 
     163           0 :   ProxyEntry* rootEntry = mAccessibles.GetEntry(aRootID);
     164           0 :   if (!rootEntry) {
     165           0 :     NS_ERROR("invalid root being removed!");
     166           0 :     return IPC_OK();
     167             :   }
     168             : 
     169           0 :   ProxyAccessible* root = rootEntry->mProxy;
     170           0 :   if (!root) {
     171           0 :     NS_ERROR("invalid root being removed!");
     172           0 :     return IPC_OK();
     173             :   }
     174             : 
     175           0 :   ProxyAccessible* parent = root->Parent();
     176           0 :   ProxyShowHideEvent(root, parent, false, aFromUser);
     177             : 
     178           0 :   RefPtr<xpcAccHideEvent> event = nullptr;
     179           0 :   if (nsCoreUtils::AccEventObserversExist()) {
     180           0 :     uint32_t type = nsIAccessibleEvent::EVENT_HIDE;
     181           0 :     xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(root);
     182           0 :     xpcAccessibleGeneric* xpcParent = GetXPCAccessible(parent);
     183           0 :     ProxyAccessible* next = root->NextSibling();
     184           0 :     xpcAccessibleGeneric* xpcNext = next ? GetXPCAccessible(next) : nullptr;
     185           0 :     ProxyAccessible* prev = root->PrevSibling();
     186           0 :     xpcAccessibleGeneric* xpcPrev = prev ? GetXPCAccessible(prev) : nullptr;
     187           0 :     xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
     188           0 :     nsIDOMNode* node = nullptr;
     189           0 :     event = new xpcAccHideEvent(type, xpcAcc, doc, node, aFromUser, xpcParent,
     190           0 :                                 xpcNext, xpcPrev);
     191             :   }
     192             : 
     193           0 :   parent->RemoveChild(root);
     194           0 :   root->Shutdown();
     195             : 
     196           0 :   MOZ_ASSERT(CheckDocTree());
     197             : 
     198           0 :   if (event) {
     199           0 :     nsCoreUtils::DispatchAccEvent(Move(event));
     200             :   }
     201             : 
     202           0 :   return IPC_OK();
     203             : }
     204             : 
     205             : mozilla::ipc::IPCResult
     206           0 : DocAccessibleParent::RecvEvent(const uint64_t& aID, const uint32_t& aEventType)
     207             : {
     208           0 :   if (mShutdown) {
     209           0 :     return IPC_OK();
     210             :   }
     211             : 
     212           0 :   ProxyAccessible* proxy = GetAccessible(aID);
     213           0 :   if (!proxy) {
     214           0 :     NS_ERROR("no proxy for event!");
     215           0 :     return IPC_OK();
     216             :   }
     217             : 
     218           0 :   ProxyEvent(proxy, aEventType);
     219             : 
     220           0 :   if (!nsCoreUtils::AccEventObserversExist()) {
     221           0 :     return IPC_OK();
     222             :   }
     223             : 
     224           0 :   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(proxy);
     225           0 :   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
     226           0 :   nsIDOMNode* node = nullptr;
     227           0 :   bool fromUser = true; // XXX fix me
     228             :   RefPtr<xpcAccEvent> event = new xpcAccEvent(aEventType, xpcAcc, doc, node,
     229           0 :                                               fromUser);
     230           0 :   nsCoreUtils::DispatchAccEvent(Move(event));
     231             : 
     232           0 :   return IPC_OK();
     233             : }
     234             : 
     235             : mozilla::ipc::IPCResult
     236           0 : DocAccessibleParent::RecvStateChangeEvent(const uint64_t& aID,
     237             :                                           const uint64_t& aState,
     238             :                                           const bool& aEnabled)
     239             : {
     240           0 :   if (mShutdown) {
     241           0 :     return IPC_OK();
     242             :   }
     243             : 
     244           0 :   ProxyAccessible* target = GetAccessible(aID);
     245           0 :   if (!target) {
     246           0 :     NS_ERROR("we don't know about the target of a state change event!");
     247           0 :     return IPC_OK();
     248             :   }
     249             : 
     250           0 :   ProxyStateChangeEvent(target, aState, aEnabled);
     251             : 
     252           0 :   if (!nsCoreUtils::AccEventObserversExist()) {
     253           0 :     return IPC_OK();
     254             :   }
     255             : 
     256           0 :   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target);
     257           0 :   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
     258           0 :   uint32_t type = nsIAccessibleEvent::EVENT_STATE_CHANGE;
     259             :   bool extra;
     260           0 :   uint32_t state = nsAccUtils::To32States(aState, &extra);
     261           0 :   bool fromUser = true; // XXX fix this
     262           0 :   nsIDOMNode* node = nullptr; // XXX can we do better?
     263             :   RefPtr<xpcAccStateChangeEvent> event =
     264             :     new xpcAccStateChangeEvent(type, xpcAcc, doc, node, fromUser, state, extra,
     265           0 :                                aEnabled);
     266           0 :   nsCoreUtils::DispatchAccEvent(Move(event));
     267             : 
     268           0 :   return IPC_OK();
     269             : }
     270             : 
     271             : mozilla::ipc::IPCResult
     272           0 : DocAccessibleParent::RecvCaretMoveEvent(const uint64_t& aID,
     273             : #if defined(XP_WIN)
     274             :                                         const LayoutDeviceIntRect& aCaretRect,
     275             : #endif // defined (XP_WIN)
     276             :                                         const int32_t& aOffset)
     277             : {
     278           0 :   if (mShutdown) {
     279           0 :     return IPC_OK();
     280             :   }
     281             : 
     282           0 :   ProxyAccessible* proxy = GetAccessible(aID);
     283           0 :   if (!proxy) {
     284           0 :     NS_ERROR("unknown caret move event target!");
     285           0 :     return IPC_OK();
     286             :   }
     287             : 
     288             : #if defined(XP_WIN)
     289             :   ProxyCaretMoveEvent(proxy, aCaretRect);
     290             : #else
     291           0 :   ProxyCaretMoveEvent(proxy, aOffset);
     292             : #endif
     293             : 
     294           0 :   if (!nsCoreUtils::AccEventObserversExist()) {
     295           0 :     return IPC_OK();
     296             :   }
     297             : 
     298           0 :   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(proxy);
     299           0 :   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
     300           0 :   nsIDOMNode* node = nullptr;
     301           0 :   bool fromUser = true; // XXX fix me
     302           0 :   uint32_t type = nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED;
     303             :   RefPtr<xpcAccCaretMoveEvent> event =
     304           0 :     new xpcAccCaretMoveEvent(type, xpcAcc, doc, node, fromUser, aOffset);
     305           0 :   nsCoreUtils::DispatchAccEvent(Move(event));
     306             : 
     307           0 :   return IPC_OK();
     308             : }
     309             : 
     310             : mozilla::ipc::IPCResult
     311           0 : DocAccessibleParent::RecvTextChangeEvent(const uint64_t& aID,
     312             :                                          const nsString& aStr,
     313             :                                          const int32_t& aStart,
     314             :                                          const uint32_t& aLen,
     315             :                                          const bool& aIsInsert,
     316             :                                          const bool& aFromUser)
     317             : {
     318           0 :   if (mShutdown) {
     319           0 :     return IPC_OK();
     320             :   }
     321             : 
     322           0 :   ProxyAccessible* target = GetAccessible(aID);
     323           0 :   if (!target) {
     324           0 :     NS_ERROR("text change event target is unknown!");
     325           0 :     return IPC_OK();
     326             :   }
     327             : 
     328           0 :   ProxyTextChangeEvent(target, aStr, aStart, aLen, aIsInsert, aFromUser);
     329             : 
     330           0 :   if (!nsCoreUtils::AccEventObserversExist()) {
     331           0 :     return IPC_OK();
     332             :   }
     333             : 
     334           0 :   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target);
     335           0 :   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
     336           0 :   uint32_t type = aIsInsert ? nsIAccessibleEvent::EVENT_TEXT_INSERTED :
     337           0 :                               nsIAccessibleEvent::EVENT_TEXT_REMOVED;
     338           0 :   nsIDOMNode* node = nullptr;
     339             :   RefPtr<xpcAccTextChangeEvent> event =
     340           0 :     new xpcAccTextChangeEvent(type, xpcAcc, doc, node, aFromUser, aStart, aLen,
     341           0 :                               aIsInsert, aStr);
     342           0 :   nsCoreUtils::DispatchAccEvent(Move(event));
     343             : 
     344           0 :   return IPC_OK();
     345             : }
     346             : 
     347             : #if defined(XP_WIN)
     348             : 
     349             : mozilla::ipc::IPCResult
     350             : DocAccessibleParent::RecvSyncTextChangeEvent(const uint64_t& aID,
     351             :                                              const nsString& aStr,
     352             :                                              const int32_t& aStart,
     353             :                                              const uint32_t& aLen,
     354             :                                              const bool& aIsInsert,
     355             :                                              const bool& aFromUser)
     356             : {
     357             :   return RecvTextChangeEvent(aID, aStr, aStart, aLen, aIsInsert, aFromUser);
     358             : }
     359             : 
     360             : #endif // defined(XP_WIN)
     361             : 
     362             : mozilla::ipc::IPCResult
     363           0 : DocAccessibleParent::RecvSelectionEvent(const uint64_t& aID,
     364             :                                         const uint64_t& aWidgetID,
     365             :                                         const uint32_t& aType)
     366             : {
     367           0 :   if (mShutdown) {
     368           0 :     return IPC_OK();
     369             :   }
     370             : 
     371           0 :   ProxyAccessible* target = GetAccessible(aID);
     372           0 :   ProxyAccessible* widget = GetAccessible(aWidgetID);
     373           0 :   if (!target || !widget) {
     374           0 :     NS_ERROR("invalid id in selection event");
     375           0 :     return IPC_OK();
     376             :   }
     377             : 
     378           0 :   ProxySelectionEvent(target, widget, aType);
     379           0 :   if (!nsCoreUtils::AccEventObserversExist()) {
     380           0 :     return IPC_OK();
     381             :   }
     382           0 :   xpcAccessibleGeneric* xpcTarget = GetXPCAccessible(target);
     383           0 :   xpcAccessibleDocument* xpcDoc = GetAccService()->GetXPCDocument(this);
     384             :   RefPtr<xpcAccEvent> event = new xpcAccEvent(aType, xpcTarget, xpcDoc,
     385           0 :                                               nullptr, false);
     386           0 :   nsCoreUtils::DispatchAccEvent(Move(event));
     387             : 
     388           0 :   return IPC_OK();
     389             : }
     390             : 
     391             : mozilla::ipc::IPCResult
     392           0 : DocAccessibleParent::RecvRoleChangedEvent(const uint32_t& aRole)
     393             : {
     394           0 :   if (mShutdown) {
     395           0 :     return IPC_OK();
     396             :   }
     397             : 
     398           0 :  if (aRole > roles::LAST_ROLE) {
     399           0 :    return IPC_FAIL(this, "Child sent bad role in RoleChangedEvent");
     400             :  }
     401             : 
     402           0 :  mRole = static_cast<a11y::role>(aRole);
     403           0 :  return IPC_OK();
     404             : }
     405             : 
     406             : mozilla::ipc::IPCResult
     407           0 : DocAccessibleParent::RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uint64_t& aID)
     408             : {
     409             :   // One document should never directly be the child of another.
     410             :   // We should always have at least an outer doc accessible in between.
     411           0 :   MOZ_ASSERT(aID);
     412           0 :   if (!aID)
     413           0 :     return IPC_FAIL(this, "ID is 0!");
     414             : 
     415           0 :   if (mShutdown) {
     416           0 :     return IPC_OK();
     417             :   }
     418             : 
     419           0 :   MOZ_ASSERT(CheckDocTree());
     420             : 
     421           0 :   auto childDoc = static_cast<DocAccessibleParent*>(aChildDoc);
     422           0 :   childDoc->Unbind();
     423           0 :   ipc::IPCResult result = AddChildDoc(childDoc, aID, false);
     424           0 :   MOZ_ASSERT(result);
     425           0 :   MOZ_ASSERT(CheckDocTree());
     426             : #ifdef DEBUG
     427           0 :   if (!result) {
     428           0 :     return result;
     429             :   }
     430             : #else
     431             :   result = IPC_OK();
     432             : #endif
     433             : 
     434           0 :   return result;
     435             : }
     436             : 
     437             : ipc::IPCResult
     438           0 : DocAccessibleParent::AddChildDoc(DocAccessibleParent* aChildDoc,
     439             :                                  uint64_t aParentID, bool aCreating)
     440             : {
     441             :   // We do not use GetAccessible here because we want to be sure to not get the
     442             :   // document it self.
     443           0 :   ProxyEntry* e = mAccessibles.GetEntry(aParentID);
     444           0 :   if (!e) {
     445           0 :     return IPC_FAIL(this, "binding to nonexistant proxy!");
     446             :   }
     447             : 
     448           0 :   ProxyAccessible* outerDoc = e->mProxy;
     449           0 :   MOZ_ASSERT(outerDoc);
     450             : 
     451             :   // OuterDocAccessibles are expected to only have a document as a child.
     452             :   // However for compatibility we tolerate replacing one document with another
     453             :   // here.
     454           0 :   if (outerDoc->ChildrenCount() > 1 ||
     455           0 :       (outerDoc->ChildrenCount() == 1 && !outerDoc->ChildAt(0)->IsDoc())) {
     456           0 :     return IPC_FAIL(this, "binding to proxy that can't be a outerDoc!");
     457             :   }
     458             : 
     459           0 :   if (outerDoc->ChildrenCount() == 1) {
     460           0 :     MOZ_ASSERT(outerDoc->ChildAt(0)->AsDoc());
     461           0 :     outerDoc->ChildAt(0)->AsDoc()->Unbind();
     462             :   }
     463             : 
     464           0 :   aChildDoc->SetParent(outerDoc);
     465           0 :   outerDoc->SetChildDoc(aChildDoc);
     466           0 :   mChildDocs.AppendElement(aChildDoc->mActorID);
     467           0 :   aChildDoc->mParentDoc = mActorID;
     468             : 
     469           0 :   if (aCreating) {
     470           0 :     ProxyCreated(aChildDoc, Interfaces::DOCUMENT | Interfaces::HYPERTEXT);
     471             :   }
     472             : 
     473           0 :   return IPC_OK();
     474             : }
     475             : 
     476             : mozilla::ipc::IPCResult
     477           0 : DocAccessibleParent::RecvShutdown()
     478             : {
     479           0 :   Destroy();
     480             : 
     481           0 :   auto mgr = static_cast<dom::TabParent*>(Manager());
     482           0 :   if (!mgr->IsDestroyed()) {
     483           0 :     if (!PDocAccessibleParent::Send__delete__(this)) {
     484           0 :       return IPC_FAIL_NO_REASON(mgr);
     485             :     }
     486             :   }
     487             : 
     488           0 :   return IPC_OK();
     489             : }
     490             : 
     491             : void
     492           0 : DocAccessibleParent::Destroy()
     493             : {
     494             :   // If we are already shutdown that is because our containing tab parent is
     495             :   // shutting down in which case we don't need to do anything.
     496           0 :   if (mShutdown) {
     497           0 :     return;
     498             :   }
     499             : 
     500           0 :   mShutdown = true;
     501             : 
     502           0 :   MOZ_DIAGNOSTIC_ASSERT(LiveDocs().Contains(mActorID));
     503           0 :   uint32_t childDocCount = mChildDocs.Length();
     504           0 :   for (uint32_t i = 0; i < childDocCount; i++) {
     505           0 :     for (uint32_t j = i + 1; j < childDocCount; j++) {
     506           0 :       MOZ_DIAGNOSTIC_ASSERT(mChildDocs[i] != mChildDocs[j]);
     507             :     }
     508             :   }
     509             : 
     510             :   // XXX This indirection through the hash map of live documents shouldn't be
     511             :   // needed, but be paranoid for now.
     512           0 :   int32_t actorID = mActorID;
     513           0 :   for (uint32_t i = childDocCount - 1; i < childDocCount; i--) {
     514           0 :     DocAccessibleParent* thisDoc = LiveDocs().Get(actorID);
     515           0 :     MOZ_ASSERT(thisDoc);
     516           0 :     if (!thisDoc) {
     517           0 :       return;
     518             :     }
     519             : 
     520           0 :     thisDoc->ChildDocAt(i)->Destroy();
     521             :   }
     522             : 
     523           0 :   for (auto iter = mAccessibles.Iter(); !iter.Done(); iter.Next()) {
     524           0 :     MOZ_ASSERT(iter.Get()->mProxy != this);
     525           0 :     ProxyDestroyed(iter.Get()->mProxy);
     526           0 :     iter.Remove();
     527             :   }
     528             : 
     529           0 :   DocAccessibleParent* thisDoc = LiveDocs().Get(actorID);
     530           0 :   MOZ_ASSERT(thisDoc);
     531           0 :   if (!thisDoc) {
     532           0 :     return;
     533             :   }
     534             : 
     535             :   // The code above should have already completely cleared these, but to be
     536             :   // extra safe make sure they are cleared here.
     537           0 :   thisDoc->mAccessibles.Clear();
     538           0 :   thisDoc->mChildDocs.Clear();
     539             : 
     540           0 :   DocManager::NotifyOfRemoteDocShutdown(thisDoc);
     541           0 :   thisDoc = LiveDocs().Get(actorID);
     542           0 :   MOZ_ASSERT(thisDoc);
     543           0 :   if (!thisDoc) {
     544           0 :     return;
     545             :   }
     546             : 
     547           0 :   ProxyDestroyed(thisDoc);
     548           0 :   thisDoc = LiveDocs().Get(actorID);
     549           0 :   MOZ_ASSERT(thisDoc);
     550           0 :   if (!thisDoc) {
     551           0 :     return;
     552             :   }
     553             : 
     554           0 :   if (DocAccessibleParent* parentDoc = thisDoc->ParentDoc())
     555           0 :     parentDoc->RemoveChildDoc(thisDoc);
     556           0 :   else if (IsTopLevel())
     557           0 :     GetAccService()->RemoteDocShutdown(this);
     558             : }
     559             : 
     560             : DocAccessibleParent*
     561           0 : DocAccessibleParent::ParentDoc() const
     562             : {
     563           0 :   if (mParentDoc == kNoParentDoc) {
     564           0 :     return nullptr;
     565             :   }
     566             : 
     567           0 :   return LiveDocs().Get(mParentDoc);
     568             : }
     569             : 
     570             : bool
     571           0 : DocAccessibleParent::CheckDocTree() const
     572             : {
     573           0 :   size_t childDocs = mChildDocs.Length();
     574           0 :   for (size_t i = 0; i < childDocs; i++) {
     575           0 :     const DocAccessibleParent* childDoc = ChildDocAt(i);
     576           0 :     if (!childDoc || childDoc->ParentDoc() != this)
     577           0 :       return false;
     578             : 
     579           0 :     if (!childDoc->CheckDocTree()) {
     580           0 :       return false;
     581             :     }
     582             :   }
     583             : 
     584           0 :   return true;
     585             : }
     586             : 
     587             : xpcAccessibleGeneric*
     588           0 : DocAccessibleParent::GetXPCAccessible(ProxyAccessible* aProxy)
     589             : {
     590           0 :   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
     591           0 :   MOZ_ASSERT(doc);
     592             : 
     593           0 :   return doc->GetXPCAccessible(aProxy);
     594             : }
     595             : 
     596             : #if defined(XP_WIN)
     597             : void
     598             : DocAccessibleParent::MaybeInitWindowEmulation()
     599             : {
     600             :   if (!nsWinUtils::IsWindowEmulationStarted()) {
     601             :     return;
     602             :   }
     603             : 
     604             :   // XXX get the bounds from the tabParent instead of poking at accessibles
     605             :   // which might not exist yet.
     606             :   Accessible* outerDoc = OuterDocOfRemoteBrowser();
     607             :   if (!outerDoc) {
     608             :     return;
     609             :   }
     610             : 
     611             :   RootAccessible* rootDocument = outerDoc->RootAccessible();
     612             :   MOZ_ASSERT(rootDocument);
     613             : 
     614             :   bool isActive = true;
     615             :   nsIntRect rect(CW_USEDEFAULT, CW_USEDEFAULT, 0, 0);
     616             :   if (Compatibility::IsDolphin()) {
     617             :     rect = Bounds();
     618             :     nsIntRect rootRect = rootDocument->Bounds();
     619             :     rect.x = rootRect.x - rect.x;
     620             :     rect.y -= rootRect.y;
     621             : 
     622             :     auto tab = static_cast<dom::TabParent*>(Manager());
     623             :     tab->GetDocShellIsActive(&isActive);
     624             :   }
     625             : 
     626             :   IAccessibleHolder hWndAccHolder;
     627             :   HWND parentWnd = reinterpret_cast<HWND>(rootDocument->GetNativeWindow());
     628             :   HWND hWnd = nsWinUtils::CreateNativeWindow(kClassNameTabContent,
     629             :                                              parentWnd, rect.x, rect.y,
     630             :                                              rect.width, rect.height,
     631             :                                              isActive);
     632             :   if (hWnd) {
     633             :     // Attach accessible document to the emulated native window
     634             :     ::SetPropW(hWnd, kPropNameDocAccParent, (HANDLE)this);
     635             :     SetEmulatedWindowHandle(hWnd);
     636             :     IAccessible* rawHWNDAcc = nullptr;
     637             :     if (SUCCEEDED(::AccessibleObjectFromWindow(hWnd, OBJID_WINDOW,
     638             :                                                IID_IAccessible,
     639             :                                                (void**)&rawHWNDAcc))) {
     640             :       hWndAccHolder.Set(IAccessibleHolder::COMPtrType(rawHWNDAcc));
     641             :     }
     642             :   }
     643             : 
     644             :   Unused << SendEmulatedWindow(reinterpret_cast<uintptr_t>(mEmulatedWindowHandle),
     645             :                                hWndAccHolder);
     646             : }
     647             : 
     648             : /**
     649             :  * @param aCOMProxy COM Proxy to the document in the content process.
     650             :  */
     651             : void
     652             : DocAccessibleParent::SendParentCOMProxy()
     653             : {
     654             :   // Make sure that we're not racing with a tab shutdown
     655             :   auto tab = static_cast<dom::TabParent*>(Manager());
     656             :   MOZ_ASSERT(tab);
     657             :   if (tab->IsDestroyed()) {
     658             :     return;
     659             :   }
     660             : 
     661             :   Accessible* outerDoc = OuterDocOfRemoteBrowser();
     662             :   if (!outerDoc) {
     663             :     return;
     664             :   }
     665             : 
     666             :   IAccessible* rawNative = nullptr;
     667             :   outerDoc->GetNativeInterface((void**) &rawNative);
     668             :   MOZ_ASSERT(rawNative);
     669             : 
     670             :   IAccessibleHolder::COMPtrType ptr(rawNative);
     671             :   IAccessibleHolder holder(Move(ptr));
     672             :   Unused << PDocAccessibleParent::SendParentCOMProxy(holder);
     673             : }
     674             : 
     675             : void
     676             : DocAccessibleParent::SetEmulatedWindowHandle(HWND aWindowHandle)
     677             : {
     678             :   if (!aWindowHandle && mEmulatedWindowHandle && IsTopLevel()) {
     679             :     ::DestroyWindow(mEmulatedWindowHandle);
     680             :   }
     681             :   mEmulatedWindowHandle = aWindowHandle;
     682             : }
     683             : 
     684             : mozilla::ipc::IPCResult
     685             : DocAccessibleParent::RecvGetWindowedPluginIAccessible(
     686             :       const WindowsHandle& aHwnd, IAccessibleHolder* aPluginCOMProxy)
     687             : {
     688             : #if defined(MOZ_CONTENT_SANDBOX)
     689             :   // We don't actually want the accessible object for aHwnd, but rather the
     690             :   // one that belongs to its child (see HTMLWin32ObjectAccessible).
     691             :   HWND childWnd = ::GetWindow(reinterpret_cast<HWND>(aHwnd), GW_CHILD);
     692             :   if (!childWnd) {
     693             :     // We're seeing this in the wild - the plugin is windowed but we no longer
     694             :     // have a window.
     695             :     return IPC_OK();
     696             :   }
     697             : 
     698             :   IAccessible* rawAccPlugin = nullptr;
     699             :   HRESULT hr = ::AccessibleObjectFromWindow(childWnd, OBJID_WINDOW,
     700             :                                             IID_IAccessible,
     701             :                                             (void**)&rawAccPlugin);
     702             :   if (FAILED(hr)) {
     703             :     // This might happen if the plugin doesn't handle WM_GETOBJECT properly.
     704             :     // We should not consider that a failure.
     705             :     return IPC_OK();
     706             :   }
     707             : 
     708             :   aPluginCOMProxy->Set(IAccessibleHolder::COMPtrType(rawAccPlugin));
     709             : 
     710             :   return IPC_OK();
     711             : #else
     712             :   return IPC_FAIL(this, "Message unsupported in this build configuration");
     713             : #endif
     714             : }
     715             : 
     716             : mozilla::ipc::IPCResult
     717             : DocAccessibleParent::RecvFocusEvent(const uint64_t& aID,
     718             :                                     const LayoutDeviceIntRect& aCaretRect)
     719             : {
     720             :   if (mShutdown) {
     721             :     return IPC_OK();
     722             :   }
     723             : 
     724             :   ProxyAccessible* proxy = GetAccessible(aID);
     725             :   if (!proxy) {
     726             :     NS_ERROR("no proxy for event!");
     727             :     return IPC_OK();
     728             :   }
     729             : 
     730             :   ProxyFocusEvent(proxy, aCaretRect);
     731             : 
     732             :   if (!nsCoreUtils::AccEventObserversExist()) {
     733             :     return IPC_OK();
     734             :   }
     735             : 
     736             :   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(proxy);
     737             :   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
     738             :   nsIDOMNode* node = nullptr;
     739             :   bool fromUser = true; // XXX fix me
     740             :   RefPtr<xpcAccEvent> event = new xpcAccEvent(nsIAccessibleEvent::EVENT_FOCUS,
     741             :                                               xpcAcc, doc, node, fromUser);
     742             :   nsCoreUtils::DispatchAccEvent(Move(event));
     743             : 
     744             :   return IPC_OK();
     745             : }
     746             : 
     747             : #endif // defined(XP_WIN)
     748             : 
     749             : } // a11y
     750             : } // mozilla

Generated by: LCOV version 1.13