import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 622657 - catch invalid bookmark items and delete them when syncing bookmarks. r=rnewman (bd91e14c9a)
- Bug 1166853 - Sync "hangs" when trying to apply a livemark to a reconciled folder. r=rnewman (94a6a19753)
- Bug 1012597 - Part 1: provide a way to invalidate the Places GUIDs cache. r=rnewman (66f43cb831)
- Bug 1012597 - Part 2: ensure Sync invalidates the Places GUIDs cache when needed. r=rnewman (2a67b0dfa8)
- Bug 1182366 - avoid an invalid bookmark from preventing all bookmarks syncing. r=rnewman (df895d4c35)
- let -> var (e9c382c761)
- Bug 1188170 - log the url string when the Sync bookmarks engine fails to get a URI. r=rnewman (424e5405f7)
- Bug 1195603 - prevent Sync from blocking app shutdown. r=rnewman (94c3091f9c)
- Bug 1183934 - only log an error saving JSON if an error actually occurred. r=rnewman (6b4358035c)
- Bug 1198385 - Use MFBT guard macros in the editor guard objects; r=froydnj (72e5e9f66f)
- Bug 1198385 follow-up: Fix the build bustage on a CLOSED TREE (d626e56e92)
- Bug 1177013 - Use CancelCurrentTransaction to avoid crashes (r=dvander) (362e5fc343)
- Bug 1154990 - Better error messages when IPC send fails (r=bent) (b311fb94aa)
- Bug 1177013 - Avoid memory leaks when returning errors from IPC Send (r=dvander) (f453a8feb5)
- Bug 1176096 - Ensure we don't do self-moves in move assignment (r=bent) (31aca4ad89)
- Bug 1177013 - Crash in IPC situations where we don't know what to do (r=dvander) (0e86cc437e)
- Bug 1185639 - Allow deferred message processing to happen between consecutive IPC message dispatches. r=jimm (7782c9caaf)
This commit is contained in:
2022-02-10 11:05:08 +08:00
parent 8e0043d5bc
commit d7ccda56e2
25 changed files with 609 additions and 198 deletions
+91 -82
View File
@@ -8,6 +8,7 @@
#include "mozilla/DebugOnly.h"
#include "WindowsMessageLoop.h"
#include "Neutering.h"
#include "MessageChannel.h"
#include "nsAutoPtr.h"
@@ -862,6 +863,81 @@ IsTimeoutExpired(PRIntervalTime aStart, PRIntervalTime aTimeout)
(aTimeout <= (PR_IntervalNow() - aStart));
}
static HHOOK gWindowHook;
static inline void
StartNeutering()
{
MOZ_ASSERT(gUIThreadId);
MOZ_ASSERT(!gWindowHook);
NS_ASSERTION(!MessageChannel::IsPumpingMessages(),
"Shouldn't be pumping already!");
MessageChannel::SetIsPumpingMessages(true);
gWindowHook = ::SetWindowsHookEx(WH_CALLWNDPROC, CallWindowProcedureHook,
nullptr, gUIThreadId);
NS_ASSERTION(gWindowHook, "Failed to set hook!");
}
static void
StopNeutering()
{
MOZ_ASSERT(MessageChannel::IsPumpingMessages());
::UnhookWindowsHookEx(gWindowHook);
gWindowHook = NULL;
::UnhookNeuteredWindows();
// Before returning we need to set a hook to run any deferred messages that
// we received during the IPC call. The hook will unset itself as soon as
// someone else calls GetMessage, PeekMessage, or runs code that generates
// a "nonqueued" message.
::ScheduleDeferredMessageRun();
MessageChannel::SetIsPumpingMessages(false);
}
NeuteredWindowRegion::NeuteredWindowRegion(bool aDoNeuter MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
: mNeuteredByThis(!gWindowHook)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (aDoNeuter && mNeuteredByThis) {
StartNeutering();
}
}
NeuteredWindowRegion::~NeuteredWindowRegion()
{
if (gWindowHook && mNeuteredByThis) {
StopNeutering();
}
}
void
NeuteredWindowRegion::PumpOnce()
{
MSG msg = {0};
// Pump any COM messages so that we don't hang due to STA marshaling.
if (gCOMWindow && ::PeekMessageW(&msg, gCOMWindow, 0, 0, PM_REMOVE)) {
::TranslateMessage(&msg);
::DispatchMessageW(&msg);
}
// Expunge any nonqueued messages on the current thread.
::PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE);
}
DeneuteredWindowRegion::DeneuteredWindowRegion(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
: mReneuter(gWindowHook != NULL)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (mReneuter) {
StopNeutering();
}
}
DeneuteredWindowRegion::~DeneuteredWindowRegion()
{
if (mReneuter) {
StartNeutering();
}
}
bool
MessageChannel::WaitForSyncNotify()
{
@@ -916,15 +992,6 @@ MessageChannel::WaitForSyncNotify()
NS_ASSERTION(timerId, "SetTimer failed!");
}
// Setup deferred processing of native events while we wait for a response.
NS_ASSERTION(!MessageChannel::IsPumpingMessages(),
"Shouldn't be pumping already!");
MessageChannel::SetIsPumpingMessages(true);
HHOOK windowHook = SetWindowsHookEx(WH_CALLWNDPROC, CallWindowProcedureHook,
nullptr, gUIThreadId);
NS_ASSERTION(windowHook, "Failed to set hook!");
{
while (1) {
MSG msg = { 0 };
@@ -998,25 +1065,11 @@ MessageChannel::WaitForSyncNotify()
}
}
// Unhook the neutered window procedure hook.
UnhookWindowsHookEx(windowHook);
// Unhook any neutered windows procedures so messages can be delivered
// normally.
UnhookNeuteredWindows();
// Before returning we need to set a hook to run any deferred messages that
// we received during the IPC call. The hook will unset itself as soon as
// someone else calls GetMessage, PeekMessage, or runs code that generates
// a "nonqueued" message.
ScheduleDeferredMessageRun();
if (timerId) {
KillTimer(nullptr, timerId);
timerId = 0;
}
MessageChannel::SetIsPumpingMessages(false);
return WaitResponse(timedout);
}
@@ -1050,56 +1103,28 @@ MessageChannel::WaitForInterruptNotify()
UINT_PTR timerId = 0;
TimeoutData timeoutData = { 0 };
// windowHook is used as a flag variable for the loop below: if it is set
// gWindowHook is used as a flag variable for the loop below: if it is set
// and we start to spin a nested event loop, we need to clear the hook and
// process deferred/pending messages.
// If windowHook is nullptr, MessageChannel::IsPumpingMessages should be false.
HHOOK windowHook = nullptr;
while (1) {
NS_ASSERTION((!!windowHook) == MessageChannel::IsPumpingMessages(),
"windowHook out of sync with reality");
NS_ASSERTION((!!gWindowHook) == MessageChannel::IsPumpingMessages(),
"gWindowHook out of sync with reality");
if (mTopFrame->mSpinNestedEvents) {
if (windowHook) {
UnhookWindowsHookEx(windowHook);
windowHook = nullptr;
if (timerId) {
KillTimer(nullptr, timerId);
timerId = 0;
}
// Used by widget to assert on incoming native events
MessageChannel::SetIsPumpingMessages(false);
// Unhook any neutered windows procedures so messages can be delievered
// normally.
UnhookNeuteredWindows();
// Send all deferred "nonqueued" message to the intended receiver.
// We're dropping into SpinInternalEventLoop so we should be fairly
// certain these will get delivered soohn.
ScheduleDeferredMessageRun();
if (gWindowHook && timerId) {
KillTimer(nullptr, timerId);
timerId = 0;
}
DeneuteredWindowRegion deneuteredRgn;
SpinInternalEventLoop();
ResetEvent(mEvent);
return true;
}
if (!windowHook) {
MessageChannel::SetIsPumpingMessages(true);
windowHook = SetWindowsHookEx(WH_CALLWNDPROC, CallWindowProcedureHook,
nullptr, gUIThreadId);
NS_ASSERTION(windowHook, "Failed to set hook!");
NS_ASSERTION(!timerId, "Timer already initialized?");
if (mTimeoutMs != kNoTimeout) {
InitTimeoutData(&timeoutData, mTimeoutMs);
timerId = SetTimer(nullptr, 0, mTimeoutMs, nullptr);
NS_ASSERTION(timerId, "SetTimer failed!");
}
if (mTimeoutMs != kNoTimeout && !timerId) {
InitTimeoutData(&timeoutData, mTimeoutMs);
timerId = SetTimer(nullptr, 0, mTimeoutMs, nullptr);
NS_ASSERTION(timerId, "SetTimer failed!");
}
MSG msg = { 0 };
@@ -1151,27 +1176,11 @@ MessageChannel::WaitForInterruptNotify()
}
}
if (windowHook) {
// Unhook the neutered window procedure hook.
UnhookWindowsHookEx(windowHook);
// Unhook any neutered windows procedures so messages can be delivered
// normally.
UnhookNeuteredWindows();
// Before returning we need to set a hook to run any deferred messages that
// we received during the IPC call. The hook will unset itself as soon as
// someone else calls GetMessage, PeekMessage, or runs code that generates
// a "nonqueued" message.
ScheduleDeferredMessageRun();
if (timerId) {
KillTimer(nullptr, timerId);
}
if (timerId) {
KillTimer(nullptr, timerId);
timerId = 0;
}
MessageChannel::SetIsPumpingMessages(false);
return WaitResponse(timedout);
}