bug 1212906 - don't handle windows messages while waiting for a sync a11y ipc message r=billm

Windows messages can trigger sync ipc messages to the child process.  That
means if we handle windows messages while waiting for the response to a sync
a11y ipc message we can end up reentering the code to send ipc messages which
is bad.  Try and avoid this situation by not handling windows messages while
waiting for a sync a11y message.
This commit is contained in:
Trevor Saunders 2015-10-07 17:38:08 -04:00
parent e8d8cb32c6
commit dda4730c3c
6 changed files with 33 additions and 7 deletions

View File

@ -24,6 +24,7 @@
#include <set>
#include "mozilla/a11y/PDocAccessible.h"
#include "AppProcessChecker.h"
#include "AudioChannelService.h"
#include "BlobParent.h"
@ -5476,3 +5477,19 @@ ParentIdleListener::Observe(nsISupports*, const char* aTopic, const char16_t* aD
nsDependentString(aData));
return NS_OK;
}
bool
ContentParent::HandleWindowsMessages(const Message& aMsg) const
{
MOZ_ASSERT(aMsg.is_sync());
// a11y messages can be triggered by windows messages, which means if we
// allow handling windows messages while we wait for the response to a sync
// a11y message we can reenter the ipc message sending code.
if (a11y::PDocAccessible::PDocAccessibleStart < aMsg.type() &&
a11y::PDocAccessible::PDocAccessibleEnd > aMsg.type()) {
return false;
}
return true;
}

View File

@ -427,6 +427,8 @@ public:
virtual bool
DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor) override;
virtual bool HandleWindowsMessages(const Message& aMsg) const override;
bool HasGamepadListener() const { return mHasGamepadListener; }
void SetNuwaParent(NuwaParent* aNuwaParent) { mNuwaParent = aNuwaParent; }

View File

@ -922,6 +922,7 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
return false;
}
bool handleWindowsMessages = mListener->HandleWindowsMessages(*aMsg);
mLink->SendMessage(msg.forget());
while (true) {
@ -942,7 +943,7 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
MOZ_ASSERT(!mTimedOutMessageSeqno);
bool maybeTimedOut = !WaitForSyncNotify();
bool maybeTimedOut = !WaitForSyncNotify(handleWindowsMessages);
if (!Connected()) {
ReportConnectionError("MessageChannel::SendAndWait");
@ -1576,7 +1577,7 @@ MessageChannel::WaitResponse(bool aWaitTimedOut)
#ifndef OS_WIN
bool
MessageChannel::WaitForSyncNotify()
MessageChannel::WaitForSyncNotify(bool /* aHandleWindowsMessages */)
{
PRIntervalTime timeout = (kNoTimeout == mTimeoutMs) ?
PR_INTERVAL_NO_TIMEOUT :
@ -1594,7 +1595,7 @@ MessageChannel::WaitForSyncNotify()
bool
MessageChannel::WaitForInterruptNotify()
{
return WaitForSyncNotify();
return WaitForSyncNotify(true);
}
void

View File

@ -278,7 +278,7 @@ class MessageChannel : HasResultCodes
//
// So in sum: true is a meaningful return value; false isn't,
// necessarily.
bool WaitForSyncNotify();
bool WaitForSyncNotify(bool aHandleWindowsMessages);
bool WaitForInterruptNotify();
bool WaitResponse(bool aWaitTimedOut);

View File

@ -98,6 +98,12 @@ class MessageListener
return RIPChildWins;
}
/**
* Return true if windows messages can be handled while waiting for a reply
* to a sync IPDL message.
*/
virtual bool HandleWindowsMessages(const Message& aMsg) const { return true; }
virtual void OnEnteredSyncSend() {
}
virtual void OnExitedSyncSend() {

View File

@ -944,7 +944,7 @@ DeneuteredWindowRegion::~DeneuteredWindowRegion()
}
bool
MessageChannel::WaitForSyncNotify()
MessageChannel::WaitForSyncNotify(bool aHandleWindowsMessages)
{
mMonitor->AssertCurrentThreadOwns();
@ -952,7 +952,7 @@ MessageChannel::WaitForSyncNotify()
// Use a blocking wait if this channel does not require
// Windows message deferral behavior.
if (!(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION)) {
if (!(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION) || !aHandleWindowsMessages) {
PRIntervalTime timeout = (kNoTimeout == mTimeoutMs) ?
PR_INTERVAL_NO_TIMEOUT :
PR_MillisecondsToInterval(mTimeoutMs);
@ -1088,7 +1088,7 @@ MessageChannel::WaitForInterruptNotify()
// Re-use sync notification wait code if this channel does not require
// Windows message deferral behavior.
if (!(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION)) {
return WaitForSyncNotify();
return WaitForSyncNotify(true);
}
if (!InterruptStackDepth() && !AwaitingIncomingMessage()) {