diff options
Diffstat (limited to 'accessible/ipc/win/DocAccessibleChild.cpp')
-rw-r--r-- | accessible/ipc/win/DocAccessibleChild.cpp | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/accessible/ipc/win/DocAccessibleChild.cpp b/accessible/ipc/win/DocAccessibleChild.cpp new file mode 100644 index 0000000000..6663256fba --- /dev/null +++ b/accessible/ipc/win/DocAccessibleChild.cpp @@ -0,0 +1,320 @@ +/* -*- 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 http://mozilla.org/MPL/2.0/. */ + +#include "DocAccessibleChild.h" + +#include "nsAccessibilityService.h" +#include "Accessible-inl.h" +#include "mozilla/a11y/PlatformChild.h" +#include "mozilla/ClearOnShutdown.h" +#include "RootAccessible.h" + +namespace mozilla { +namespace a11y { + +static StaticAutoPtr<PlatformChild> sPlatformChild; + +DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc, IProtocol* aManager) + : DocAccessibleChildBase(aDoc), mEmulatedWindowHandle(nullptr) { + MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase); + if (!sPlatformChild) { + sPlatformChild = new PlatformChild(); + ClearOnShutdown(&sPlatformChild, ShutdownPhase::Shutdown); + } + + SetManager(aManager); +} + +DocAccessibleChild::~DocAccessibleChild() { + MOZ_COUNT_DTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase); +} + +void DocAccessibleChild::Shutdown() { + if (IsConstructedInParentProcess()) { + DocAccessibleChildBase::Shutdown(); + return; + } + + PushDeferredEvent(MakeUnique<SerializedShutdown>(this)); + DetachDocument(); +} + +ipc::IPCResult DocAccessibleChild::RecvParentCOMProxy( + const IDispatchHolder& aParentCOMProxy) { + MOZ_ASSERT(!aParentCOMProxy.IsNull()); + mParentProxy.reset(const_cast<IDispatchHolder&>(aParentCOMProxy).Release()); + SetConstructedInParentProcess(); + + for (uint32_t i = 0, l = mDeferredEvents.Length(); i < l; ++i) { + mDeferredEvents[i]->Dispatch(); + } + + mDeferredEvents.Clear(); + + return IPC_OK(); +} + +ipc::IPCResult DocAccessibleChild::RecvEmulatedWindow( + const WindowsHandle& aEmulatedWindowHandle, + const IDispatchHolder& aEmulatedWindowCOMProxy) { + mEmulatedWindowHandle = reinterpret_cast<HWND>(aEmulatedWindowHandle); + if (!aEmulatedWindowCOMProxy.IsNull()) { + MOZ_ASSERT(!mEmulatedWindowProxy); + mEmulatedWindowProxy.reset( + const_cast<IDispatchHolder&>(aEmulatedWindowCOMProxy).Release()); + } + + return IPC_OK(); +} + +ipc::IPCResult DocAccessibleChild::RecvTopLevelDocCOMProxy( + const IAccessibleHolder& aCOMProxy) { + MOZ_ASSERT(!aCOMProxy.IsNull()); + mTopLevelDocProxy.reset(const_cast<IAccessibleHolder&>(aCOMProxy).Release()); + return IPC_OK(); +} + +HWND DocAccessibleChild::GetNativeWindowHandle() const { + if (mEmulatedWindowHandle) { + return mEmulatedWindowHandle; + } + + auto browser = static_cast<dom::BrowserChild*>(Manager()); + MOZ_ASSERT(browser); + // Iframe documents use the same window handle as their top level document. + auto topDoc = static_cast<DocAccessibleChild*>( + browser->GetTopLevelDocAccessibleChild()); + MOZ_ASSERT(topDoc); + if (topDoc != this && topDoc->mEmulatedWindowHandle) { + return topDoc->mEmulatedWindowHandle; + } + + return reinterpret_cast<HWND>(browser->GetNativeWindowHandle()); +} + +void DocAccessibleChild::PushDeferredEvent(UniquePtr<DeferredEvent> aEvent) { + DocAccessibleChild* topLevelIPCDoc = nullptr; + + if (mDoc && mDoc->IsRoot()) { + topLevelIPCDoc = this; + } else { + auto browserChild = static_cast<dom::BrowserChild*>(Manager()); + if (!browserChild) { + return; + } + + topLevelIPCDoc = static_cast<DocAccessibleChild*>( + browserChild->GetTopLevelDocAccessibleChild()); + } + + if (topLevelIPCDoc) { + topLevelIPCDoc->mDeferredEvents.AppendElement(std::move(aEvent)); + } +} + +bool DocAccessibleChild::SendEvent(const uint64_t& aID, const uint32_t& aType) { + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendEvent(aID, aType); + } + + PushDeferredEvent(MakeUnique<SerializedEvent>(this, aID, aType)); + return false; +} + +void DocAccessibleChild::MaybeSendShowEvent(ShowEventData& aData, + bool aFromUser) { + if (IsConstructedInParentProcess()) { + Unused << SendShowEvent(aData, aFromUser); + return; + } + + PushDeferredEvent(MakeUnique<SerializedShow>(this, aData, aFromUser)); +} + +bool DocAccessibleChild::SendHideEvent(const uint64_t& aRootID, + const bool& aFromUser) { + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendHideEvent(aRootID, aFromUser); + } + + PushDeferredEvent(MakeUnique<SerializedHide>(this, aRootID, aFromUser)); + return true; +} + +bool DocAccessibleChild::SendStateChangeEvent(const uint64_t& aID, + const uint64_t& aState, + const bool& aEnabled) { + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendStateChangeEvent(aID, aState, aEnabled); + } + + PushDeferredEvent( + MakeUnique<SerializedStateChange>(this, aID, aState, aEnabled)); + return true; +} + +LayoutDeviceIntRect DocAccessibleChild::GetCaretRectFor(const uint64_t& aID) { + Accessible* target; + + if (aID) { + target = reinterpret_cast<Accessible*>(aID); + } else { + target = mDoc; + } + + MOZ_ASSERT(target); + + HyperTextAccessible* text = target->AsHyperText(); + if (!text) { + return LayoutDeviceIntRect(); + } + + nsIWidget* widget = nullptr; + return text->GetCaretRect(&widget); +} + +bool DocAccessibleChild::SendFocusEvent(const uint64_t& aID) { + return SendFocusEvent(aID, GetCaretRectFor(aID)); +} + +bool DocAccessibleChild::SendFocusEvent(const uint64_t& aID, + const LayoutDeviceIntRect& aCaretRect) { + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendFocusEvent(aID, aCaretRect); + } + + PushDeferredEvent(MakeUnique<SerializedFocus>(this, aID, aCaretRect)); + return true; +} + +bool DocAccessibleChild::SendCaretMoveEvent(const uint64_t& aID, + const int32_t& aOffset, + const bool& aIsSelectionCollapsed) { + return SendCaretMoveEvent(aID, GetCaretRectFor(aID), aOffset, + aIsSelectionCollapsed); +} + +bool DocAccessibleChild::SendCaretMoveEvent( + const uint64_t& aID, const LayoutDeviceIntRect& aCaretRect, + const int32_t& aOffset, const bool& aIsSelectionCollapsed) { + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendCaretMoveEvent(aID, aCaretRect, aOffset, + aIsSelectionCollapsed); + } + + PushDeferredEvent(MakeUnique<SerializedCaretMove>( + this, aID, aCaretRect, aOffset, aIsSelectionCollapsed)); + return true; +} + +bool DocAccessibleChild::SendTextChangeEvent( + const uint64_t& aID, const nsString& aStr, const int32_t& aStart, + const uint32_t& aLen, const bool& aIsInsert, const bool& aFromUser, + const bool aDoSync) { + if (IsConstructedInParentProcess()) { + if (aDoSync) { + // The AT is going to need to reenter content while the event is being + // dispatched synchronously. + return PDocAccessibleChild::SendSyncTextChangeEvent( + aID, aStr, aStart, aLen, aIsInsert, aFromUser); + } + return PDocAccessibleChild::SendTextChangeEvent(aID, aStr, aStart, aLen, + aIsInsert, aFromUser); + } + + PushDeferredEvent(MakeUnique<SerializedTextChange>( + this, aID, aStr, aStart, aLen, aIsInsert, aFromUser)); + return true; +} + +bool DocAccessibleChild::SendSelectionEvent(const uint64_t& aID, + const uint64_t& aWidgetID, + const uint32_t& aType) { + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendSelectionEvent(aID, aWidgetID, aType); + } + + PushDeferredEvent( + MakeUnique<SerializedSelection>(this, aID, aWidgetID, aType)); + return true; +} + +bool DocAccessibleChild::SendRoleChangedEvent(const a11y::role& aRole) { + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendRoleChangedEvent(aRole); + } + + PushDeferredEvent(MakeUnique<SerializedRoleChanged>(this, aRole)); + return true; +} + +bool DocAccessibleChild::SendScrollingEvent(const uint64_t& aID, + const uint64_t& aType, + const uint32_t& aScrollX, + const uint32_t& aScrollY, + const uint32_t& aMaxScrollX, + const uint32_t& aMaxScrollY) { + if (IsConstructedInParentProcess()) { + return PDocAccessibleChild::SendScrollingEvent( + aID, aType, aScrollX, aScrollY, aMaxScrollX, aMaxScrollY); + } + + PushDeferredEvent(MakeUnique<SerializedScrolling>( + this, aID, aType, aScrollX, aScrollY, aMaxScrollX, aMaxScrollY)); + return true; +} + +bool DocAccessibleChild::ConstructChildDocInParentProcess( + DocAccessibleChild* aNewChildDoc, uint64_t aUniqueID, uint32_t aMsaaID) { + if (IsConstructedInParentProcess()) { + // We may send the constructor immediately + auto browserChild = static_cast<dom::BrowserChild*>(Manager()); + MOZ_ASSERT(browserChild); + bool result = browserChild->SendPDocAccessibleConstructor( + aNewChildDoc, this, aUniqueID, aMsaaID, IAccessibleHolder()); + if (result) { + aNewChildDoc->SetConstructedInParentProcess(); + } + return result; + } + + PushDeferredEvent(MakeUnique<SerializedChildDocConstructor>( + aNewChildDoc, this, aUniqueID, aMsaaID)); + return true; +} + +bool DocAccessibleChild::SendBindChildDoc(DocAccessibleChild* aChildDoc, + const uint64_t& aNewParentID) { + if (IsConstructedInParentProcess()) { + return DocAccessibleChildBase::SendBindChildDoc(aChildDoc, aNewParentID); + } + + PushDeferredEvent( + MakeUnique<SerializedBindChildDoc>(this, aChildDoc, aNewParentID)); + return true; +} + +ipc::IPCResult DocAccessibleChild::RecvRestoreFocus() { + FocusMgr()->ForceFocusEvent(); + return IPC_OK(); +} + +void DocAccessibleChild::SetEmbedderOnBridge(dom::BrowserBridgeChild* aBridge, + uint64_t aID) { + if (CanSend()) { + aBridge->SendSetEmbedderAccessible(this, aID); + } else { + // This DocAccessibleChild hasn't sent the constructor to the parent + // process yet. This happens if the top level document hasn't received its + // parent COM proxy yet, in which case sending constructors for child + // documents gets deferred. We must also defer sending this as an embedder. + MOZ_ASSERT(!IsConstructedInParentProcess()); + PushDeferredEvent(MakeUnique<SerializedSetEmbedder>(aBridge, this, aID)); + } +} + +} // namespace a11y +} // namespace mozilla |