Bug 1314707: Replace PDocAccessible::SendCOMProxy with new parameter to PDocAccessibleConstructor; r=tbsaunde
MozReview-Commit-ID: 9xgSLor3OgB
--- a/accessible/base/DocManager.cpp
+++ b/accessible/base/DocManager.cpp
@@ -509,29 +509,29 @@ DocManager::CreateDocOrRootAccessible(ns
// XXX We may need to handle the case that we don't have a tab child
// differently. It may be that this will cause us to fail to notify
// the parent process about important accessible documents.
if (tabChild) {
DocAccessibleChild* ipcDoc = new DocAccessibleChild(docAcc);
docAcc->SetIPCDoc(ipcDoc);
+#if defined(XP_WIN)
+ IAccessibleHolder holder(CreateHolderFromAccessible(docAcc));
+#endif
+
static_cast<TabChild*>(tabChild.get())->
SendPDocAccessibleConstructor(ipcDoc, nullptr, 0,
#if defined(XP_WIN)
- AccessibleWrap::GetChildIDFor(docAcc)
+ AccessibleWrap::GetChildIDFor(docAcc),
+ holder
#else
- 0
+ 0, 0
#endif
);
-
-#if defined(XP_WIN)
- IAccessibleHolder holder(CreateHolderFromAccessible(docAcc));
- ipcDoc->SendCOMProxy(holder);
-#endif
}
}
}
} else {
parentDocAcc->BindChildDocument(docAcc);
}
#ifdef A11Y_LOG
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -421,19 +421,20 @@ NotificationController::WillRefresh(mozi
childDoc->SetIPCDoc(ipcDoc);
nsCOMPtr<nsITabChild> tabChild =
do_GetInterface(mDocument->DocumentNode()->GetDocShell());
if (tabChild) {
MOZ_ASSERT(parentIPCDoc);
static_cast<TabChild*>(tabChild.get())->
SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id,
#if defined(XP_WIN)
- AccessibleWrap::GetChildIDFor(childDoc)
+ AccessibleWrap::GetChildIDFor(childDoc),
+ IAccessibleHolder()
#else
- 0
+ 0, 0
#endif
);
}
}
}
mObservingState = eRefreshObserving;
if (!mDocument)
--- a/accessible/generic/DocAccessible-inl.h
+++ b/accessible/generic/DocAccessible-inl.h
@@ -3,16 +3,17 @@
/* 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/. */
#ifndef mozilla_a11y_DocAccessible_inl_h_
#define mozilla_a11y_DocAccessible_inl_h_
#include "DocAccessible.h"
+#include "mozilla/a11y/DocAccessibleChild.h"
#include "nsAccessibilityService.h"
#include "nsAccessiblePivot.h"
#include "NotificationController.h"
#include "States.h"
#include "nsIScrollableFrame.h"
#include "nsIDocumentInlines.h"
#ifdef A11Y_LOG
@@ -115,16 +116,23 @@ DocAccessible::RemoveScrollListener()
nsIScrollableFrame* sf = mPresShell->GetRootScrollFrameAsScrollable();
if (sf)
sf->RemoveScrollPositionListener(this);
}
inline void
DocAccessible::NotifyOfLoad(uint32_t aLoadEventType)
{
+ // If this document is an e10s content document, we should not consider
+ // ourselves to be loaded until mIPCDoc is ready.
+ if (mIPCDoc && !mIPCDoc->IsReadyForNotifyOfLoad()) {
+ mIPCDoc->NotifyOfLoadWhenReady(aLoadEventType);
+ return;
+ }
+
mLoadState |= eDOMLoaded;
mLoadEventType = aLoadEventType;
// If the document is loaded completely then network activity was presumingly
// caused by file loading. Fire busy state change event.
if (HasLoadState(eCompletelyLoaded) && IsLoadEventTarget()) {
RefPtr<AccEvent> stateEvent =
new AccStateChangeEvent(this, states::BUSY, false);
--- a/accessible/generic/DocAccessible.h
+++ b/accessible/generic/DocAccessible.h
@@ -392,16 +392,17 @@ protected:
virtual nsresult RemoveEventListeners();
/**
* Marks this document as loaded or loading.
*/
void NotifyOfLoad(uint32_t aLoadEventType);
void NotifyOfLoading(bool aIsReloading);
+ friend class DocAccessibleChild;
friend class DocManager;
friend class ApplicationAccessible;
/**
* Perform initial update (create accessible tree).
* Can be overridden by wrappers to prepare initialization work.
*/
virtual void DoInitialUpdate();
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -456,32 +456,31 @@ DocAccessibleParent::GetXPCAccessible(Pr
MOZ_ASSERT(doc);
return doc->GetXPCAccessible(aProxy);
}
#if defined(XP_WIN)
/**
* @param aCOMProxy COM Proxy to the document in the content process.
- * @param aParentCOMProxy COM Proxy to the OuterDocAccessible that is
- * the parent of the document. The content process will use this
- * proxy when traversing up across the content/chrome boundary.
*/
-bool
-DocAccessibleParent::RecvCOMProxy(const IAccessibleHolder& aCOMProxy,
- IAccessibleHolder* aParentCOMProxy)
+void
+DocAccessibleParent::SetCOMInterface(const RefPtr<IAccessible>& aCOMProxy)
{
- RefPtr<IAccessible> ptr(aCOMProxy.Get());
- SetCOMInterface(ptr);
+ ProxyAccessible::SetCOMInterface(aCOMProxy);
Accessible* outerDoc = OuterDocOfRemoteBrowser();
+ MOZ_ASSERT(outerDoc);
+
IAccessible* rawNative = nullptr;
if (outerDoc) {
outerDoc->GetNativeInterface((void**) &rawNative);
+ MOZ_ASSERT(rawNative);
}
- aParentCOMProxy->Set(IAccessibleHolder::COMPtrType(rawNative));
- return true;
+ IAccessibleHolder::COMPtrType ptr(rawNative);
+ IAccessibleHolder holder(Move(ptr));
+ Unused << SendParentCOMProxy(holder);
}
#endif // defined(XP_WIN)
} // a11y
} // mozilla
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -139,18 +139,17 @@ public:
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) override;
+ void SetCOMInterface(const RefPtr<IAccessible>& aCOMProxy);
#endif
private:
class ProxyEntry : public PLDHashEntryHdr
{
public:
explicit ProxyEntry(const void*) : mProxy(nullptr) {}
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/IPCTypes.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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/. */
+
+#ifndef mozilla_a11y_IPCTypes_h
+#define mozilla_a11y_IPCTypes_h
+
+/**
+ * Since IPDL does not support preprocessing, this header file allows us to
+ * define types used by PDocAccessible differently depending on platform.
+ */
+
+#if defined(XP_WIN) && defined(ACCESSIBILITY)
+
+// So that we don't include a bunch of other Windows junk.
+#if !defined(COM_NO_WINDOWS_H)
+#define COM_NO_WINDOWS_H
+#endif // !defined(COM_NO_WINDOWS_H)
+
+// COM headers pull in MSXML which conflicts with our own XMLDocument class.
+// This define excludes those conflicting definitions.
+#if !defined(__XMLDocument_FWD_DEFINED__)
+#define __XMLDocument_FWD_DEFINED__
+#endif // !defined(__XMLDocument_FWD_DEFINED__)
+
+#include "mozilla/a11y/COMPtrTypes.h"
+
+// This define in rpcndr.h messes up our code, so we must undefine it after
+// COMPtrTypes.h has been included.
+#if defined(small)
+#undef small
+#endif // defined(small)
+
+#else
+
+namespace mozilla {
+namespace a11y {
+
+typedef uint32_t IAccessibleHolder;
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif // defined(XP_WIN) && defined(ACCESSIBILITY)
+
+#endif // mozilla_a11y_IPCTypes_h
+
--- a/accessible/ipc/moz.build
+++ b/accessible/ipc/moz.build
@@ -24,16 +24,20 @@ else:
LOCAL_INCLUDES += [
'/accessible/mac',
]
else:
LOCAL_INCLUDES += [
'/accessible/other',
]
+EXPORTS.mozilla.a11y += [
+ 'IPCTypes.h',
+]
+
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wno-error=shadow']
if CONFIG['ACCESSIBILITY']:
EXPORTS.mozilla.a11y += [
'DocAccessibleChildBase.h',
'DocAccessibleParent.h',
'ProxyAccessibleBase.h',
--- a/accessible/ipc/other/DocAccessibleChild.h
+++ b/accessible/ipc/other/DocAccessibleChild.h
@@ -32,16 +32,24 @@ public:
MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
}
~DocAccessibleChild()
{
MOZ_COUNT_DTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
}
+ /**
+ * DocAccessible::NotifyOfLoad will not proceed unless this function returns
+ * true. If it returns false, DocAccessibleChild::NotifyOfLoadWhenReady will
+ * be called to defer the notification.
+ */
+ bool IsReadyForNotifyOfLoad() const { return true; }
+ void NotifyOfLoadWhenReady(uint32_t) {}
+
/*
* Return the state for the accessible with given ID.
*/
virtual bool RecvState(const uint64_t& aID, uint64_t* aState) override;
/*
* Return the native state for the accessible with given ID.
*/
--- a/accessible/ipc/win/DocAccessibleChild.cpp
+++ b/accessible/ipc/win/DocAccessibleChild.cpp
@@ -12,32 +12,43 @@
namespace mozilla {
namespace a11y {
static StaticAutoPtr<PlatformChild> sPlatformChild;
DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc)
: DocAccessibleChildBase(aDoc)
+ , mDeferredLoadEventType(0)
{
MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
if (!sPlatformChild) {
sPlatformChild = new PlatformChild();
ClearOnShutdown(&sPlatformChild, ShutdownPhase::Shutdown);
}
}
DocAccessibleChild::~DocAccessibleChild()
{
MOZ_COUNT_DTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
}
-void
-DocAccessibleChild::SendCOMProxy(const IAccessibleHolder& aProxy)
+bool
+DocAccessibleChild::RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy)
{
- IAccessibleHolder parentProxy;
- PDocAccessibleChild::SendCOMProxy(aProxy, &parentProxy);
- mParentProxy.reset(parentProxy.Release());
+ MOZ_ASSERT(!aParentCOMProxy.IsNull());
+ mParentProxy.reset(aParentCOMProxy.Release());
+ if (mDeferredLoadEventType) {
+ mDoc->NotifyOfLoad(mDeferredLoadEventType);
+ }
+ return true;
+}
+
+void
+DocAccessibleChild::NotifyOfLoadWhenReady(uint32_t aLoadEventType)
+{
+ MOZ_ASSERT(!mParentProxy && !mDeferredLoadEventType);
+ mDeferredLoadEventType = aLoadEventType;
}
} // namespace a11y
} // namespace mozilla
--- a/accessible/ipc/win/DocAccessibleChild.h
+++ b/accessible/ipc/win/DocAccessibleChild.h
@@ -19,19 +19,29 @@ namespace a11y {
* and their lifetime is the same as the document they represent.
*/
class DocAccessibleChild : public DocAccessibleChildBase
{
public:
explicit DocAccessibleChild(DocAccessible* aDoc);
~DocAccessibleChild();
- void SendCOMProxy(const IAccessibleHolder& aProxy);
+ bool RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy) override;
+
IAccessible* GetParentIAccessible() const { return mParentProxy.get(); }
+ /**
+ * DocAccessible::NotifyOfLoad will not proceed unless this function returns
+ * true. If it returns false, DocAccessibleChild::NotifyOfLoadWhenReady will
+ * be called to defer the notification.
+ */
+ bool IsReadyForNotifyOfLoad() const { return !!mParentProxy; }
+ void NotifyOfLoadWhenReady(uint32_t aLoadEventType);
+
private:
mscom::ProxyUniquePtr<IAccessible> mParentProxy;
+ uint32_t mDeferredLoadEventType;
};
} // namespace a11y
} // namespace mozilla
#endif // mozilla_a11y_DocAccessibleChild_h
--- a/accessible/ipc/win/PDocAccessible.ipdl
+++ b/accessible/ipc/win/PDocAccessible.ipdl
@@ -56,19 +56,16 @@ parent:
async RoleChangedEvent(uint32_t aRole);
/*
* Tell the parent document to bind the existing document as a new child
* document.
*/
async BindChildDoc(PDocAccessible aChildDoc, uint64_t aID);
- // For now we'll add the command to send the proxy here. This might move to
- // PDocAccessible constructor in PBrowser.
- sync COMProxy(IAccessibleHolder aDocCOMProxy)
- returns(IAccessibleHolder aParentCOMProxy);
+child:
+ async ParentCOMProxy(IAccessibleHolder aParentCOMProxy);
-child:
async __delete__();
};
}
}
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -71,16 +71,17 @@ using class mozilla::dom::MessagePort fr
using class mozilla::dom::ipc::StructuredCloneData from "mozilla/dom/ipc/StructuredCloneData.h";
using mozilla::EventMessage from "mozilla/EventForwards.h";
using nsEventStatus from "mozilla/EventForwards.h";
using mozilla::Modifiers from "mozilla/EventForwards.h";
using nsSizeMode from "nsIWidgetListener.h";
using mozilla::widget::CandidateWindowPosition from "ipc/nsGUIEventIPC.h";
using class mozilla::NativeEventData from "ipc/nsGUIEventIPC.h";
using mozilla::FontRange from "ipc/nsGUIEventIPC.h";
+using mozilla::a11y::IAccessibleHolder from "mozilla/a11y/IPCTypes.h";
namespace mozilla {
namespace dom {
struct NativeKeyBinding
{
CommandInt[] singleLineCommands;
CommandInt[] multiLineCommands;
@@ -135,20 +136,21 @@ both:
async PRenderFrame();
parent:
/**
* Tell the parent process a new accessible document has been created.
* aParentDoc is the accessible document it was created in if any, and
* aParentAcc is the id of the accessible in that document the new document
* is a child of. aMsaaID is the MSAA id for this content process, and
- * is only valid on Windows. Set to 0 on other platforms.
+ * is only valid on Windows. Set to 0 on other platforms. aDocCOMProxy
+ * is also Windows-specific and should be set to 0 on other platforms.
*/
async PDocAccessible(nullable PDocAccessible aParentDoc, uint64_t aParentAcc,
- uint32_t aMsaaID);
+ uint32_t aMsaaID, IAccessibleHolder aDocCOMProxy);
/*
* Creates a new remoted nsIWidget connection for windowed plugins
* in e10s mode. This is always initiated from the child in response
* to windowed plugin creation.
*/
sync PPluginWidget();
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1976,17 +1976,17 @@ TabChild::RecvPasteTransferable(const IP
ourDocShell->DoCommandWithParams("cmd_pasteTransferable", params);
return true;
}
a11y::PDocAccessibleChild*
TabChild::AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&,
- const uint32_t&)
+ const uint32_t&, const IAccessibleHolder&)
{
MOZ_ASSERT(false, "should never call this!");
return nullptr;
}
bool
TabChild::DeallocPDocAccessibleChild(a11y::PDocAccessibleChild* aChild)
{
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -436,17 +436,17 @@ public:
const IPC::Principal& aPrincipal,
const ClonedMessageData& aData) override;
virtual bool
RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext) override;
virtual PDocAccessibleChild*
AllocPDocAccessibleChild(PDocAccessibleChild*, const uint64_t&,
- const uint32_t&) override;
+ const uint32_t&, const IAccessibleHolder&) override;
virtual bool DeallocPDocAccessibleChild(PDocAccessibleChild*) override;
virtual PDocumentRendererChild*
AllocPDocumentRendererChild(const nsRect& aDocumentRect,
const gfx::Matrix& aTransform,
const nsString& aBggcolor,
const uint32_t& aRenderFlags,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -895,17 +895,18 @@ TabParent::SetDocShell(nsIDocShell *aDoc
{
NS_ENSURE_ARG(aDocShell);
NS_WARNING("No mDocShell member in TabParent so there is no docShell to set");
return NS_OK;
}
a11y::PDocAccessibleParent*
TabParent::AllocPDocAccessibleParent(PDocAccessibleParent* aParent,
- const uint64_t&, const uint32_t&)
+ const uint64_t&, const uint32_t&,
+ const IAccessibleHolder&)
{
#ifdef ACCESSIBILITY
return new a11y::DocAccessibleParent();
#else
return nullptr;
#endif
}
@@ -917,32 +918,34 @@ TabParent::DeallocPDocAccessibleParent(P
#endif
return true;
}
bool
TabParent::RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc,
PDocAccessibleParent* aParentDoc,
const uint64_t& aParentID,
- const uint32_t& aMsaaID)
+ const uint32_t& aMsaaID,
+ const IAccessibleHolder& aDocCOMProxy)
{
#ifdef ACCESSIBILITY
auto doc = static_cast<a11y::DocAccessibleParent*>(aDoc);
if (aParentDoc) {
// A document should never directly be the parent of another document.
// There should always be an outer doc accessible child of the outer
// document containing the child.
MOZ_ASSERT(aParentID);
if (!aParentID) {
return false;
}
auto parentDoc = static_cast<a11y::DocAccessibleParent*>(aParentDoc);
bool added = parentDoc->AddChildDoc(doc, aParentID);
#ifdef XP_WIN
+ MOZ_ASSERT(aDocCOMProxy.IsNull());
if (added) {
a11y::WrapperFor(doc)->SetID(aMsaaID);
}
#endif
return added;
} else {
// null aParentDoc means this document is at the top level in the child
// process. That means it makes no sense to get an id for an accessible
@@ -951,16 +954,19 @@ TabParent::RecvPDocAccessibleConstructor
if (aParentID) {
return false;
}
doc->SetTopLevel();
a11y::DocManager::RemoteDocAdded(doc);
#ifdef XP_WIN
a11y::WrapperFor(doc)->SetID(aMsaaID);
+ MOZ_ASSERT(!aDocCOMProxy.IsNull());
+ RefPtr<IAccessible> proxy(aDocCOMProxy.Get());
+ doc->SetCOMInterface(proxy);
#endif
}
#endif
return true;
}
a11y::DocAccessibleParent*
TabParent::GetTopLevelDocAccessible() const
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -352,25 +352,26 @@ public:
DeallocPColorPickerParent(PColorPickerParent* aColorPicker) override;
virtual PDatePickerParent*
AllocPDatePickerParent(const nsString& aTitle, const nsString& aInitialDate) override;
virtual bool DeallocPDatePickerParent(PDatePickerParent* aDatePicker) override;
virtual PDocAccessibleParent*
AllocPDocAccessibleParent(PDocAccessibleParent*, const uint64_t&,
- const uint32_t&) override;
+ const uint32_t&, const IAccessibleHolder&) override;
virtual bool DeallocPDocAccessibleParent(PDocAccessibleParent*) override;
virtual bool
RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc,
PDocAccessibleParent* aParentDoc,
const uint64_t& aParentID,
- const uint32_t& aMsaaID) override;
+ const uint32_t& aMsaaID,
+ const IAccessibleHolder& aDocCOMProxy) override;
/**
* Return the top level doc accessible parent for this tab.
*/
a11y::DocAccessibleParent* GetTopLevelDocAccessible() const;
void LoadURL(nsIURI* aURI);
--- a/ipc/mscom/COMPtrHolder.h
+++ b/ipc/mscom/COMPtrHolder.h
@@ -33,17 +33,17 @@ public:
{
}
Interface* Get() const
{
return mPtr.get();
}
- MOZ_MUST_USE Interface* Release()
+ MOZ_MUST_USE Interface* Release() const
{
return mPtr.release();
}
void Set(COMPtrType&& aPtr)
{
mPtr = Forward<COMPtrType>(aPtr);
}