зеркало из https://github.com/mozilla/gecko-dev.git
Bug 801304 Part 2 - Check if event queues should be suspended before processing their events, r=mayhemer,smaug.
--HG-- extra : rebase_source : e1828ffdaaaa7ab48f956c22a93109f80a765d43
This commit is contained in:
Родитель
d0f7b1b700
Коммит
a655254f45
|
@ -9,7 +9,8 @@
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
#include "nsISupports.h"
|
#include "nsIChannel.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -167,5 +168,57 @@ void ChannelEventQueue::ResumeInternal() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ChannelEventQueue::MaybeSuspendIfEventsAreSuppressed() {
|
||||||
|
// We only ever need to suppress events on the main thread, since this is
|
||||||
|
// where content scripts can run.
|
||||||
|
if (!NS_IsMainThread()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only suppress events for queues associated with XHRs, as these can cause
|
||||||
|
// content scripts to run.
|
||||||
|
if (mHasCheckedForXMLHttpRequest && !mForXMLHttpRequest) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIChannel> channel(do_QueryInterface(mOwner));
|
||||||
|
if (!channel) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
||||||
|
if (!loadInfo) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out if this is for an XHR, if we haven't done so already.
|
||||||
|
if (!mHasCheckedForXMLHttpRequest) {
|
||||||
|
nsContentPolicyType contentType = loadInfo->InternalContentPolicyType();
|
||||||
|
mForXMLHttpRequest =
|
||||||
|
(contentType == nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST);
|
||||||
|
mHasCheckedForXMLHttpRequest = true;
|
||||||
|
|
||||||
|
if (!mForXMLHttpRequest) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suspend the queue if the associated document has suppressed event handling,
|
||||||
|
// *and* it is not in the middle of a synchronous operation that might require
|
||||||
|
// XHR events to be processed (such as a synchronous XHR).
|
||||||
|
nsCOMPtr<nsIDocument> document;
|
||||||
|
loadInfo->GetLoadingDocument(getter_AddRefs(document));
|
||||||
|
if (document &&
|
||||||
|
document->EventHandlingSuppressed() &&
|
||||||
|
!document->IsInSyncOperation()) {
|
||||||
|
document->AddSuspendedChannelEventQueue(this);
|
||||||
|
SuspendInternal();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace net
|
} // namespace net
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -86,6 +86,8 @@ class ChannelEventQueue final {
|
||||||
mSuspended(false),
|
mSuspended(false),
|
||||||
mForcedCount(0),
|
mForcedCount(0),
|
||||||
mFlushing(false),
|
mFlushing(false),
|
||||||
|
mHasCheckedForXMLHttpRequest(false),
|
||||||
|
mForXMLHttpRequest(false),
|
||||||
mOwner(owner),
|
mOwner(owner),
|
||||||
mMutex("ChannelEventQueue::mMutex"),
|
mMutex("ChannelEventQueue::mMutex"),
|
||||||
mRunningMutex("ChannelEventQueue::mRunningMutex") {}
|
mRunningMutex("ChannelEventQueue::mRunningMutex") {}
|
||||||
|
@ -126,6 +128,8 @@ class ChannelEventQueue final {
|
||||||
void SuspendInternal();
|
void SuspendInternal();
|
||||||
void ResumeInternal();
|
void ResumeInternal();
|
||||||
|
|
||||||
|
bool MaybeSuspendIfEventsAreSuppressed();
|
||||||
|
|
||||||
inline void MaybeFlushQueue();
|
inline void MaybeFlushQueue();
|
||||||
void FlushQueue();
|
void FlushQueue();
|
||||||
inline void CompleteResume();
|
inline void CompleteResume();
|
||||||
|
@ -139,6 +143,11 @@ class ChannelEventQueue final {
|
||||||
uint32_t mForcedCount; // Support ForcedQueueing on multiple thread.
|
uint32_t mForcedCount; // Support ForcedQueueing on multiple thread.
|
||||||
bool mFlushing;
|
bool mFlushing;
|
||||||
|
|
||||||
|
// Whether the queue is associated with an XHR. This is lazily instantiated
|
||||||
|
// the first time it is needed.
|
||||||
|
bool mHasCheckedForXMLHttpRequest;
|
||||||
|
bool mForXMLHttpRequest;
|
||||||
|
|
||||||
// Keep ptr to avoid refcount cycle: only grab ref during flushing.
|
// Keep ptr to avoid refcount cycle: only grab ref during flushing.
|
||||||
nsISupports* mOwner;
|
nsISupports* mOwner;
|
||||||
|
|
||||||
|
@ -172,7 +181,8 @@ inline void ChannelEventQueue::RunOrEnqueue(ChannelEvent* aCallback,
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
|
|
||||||
bool enqueue =
|
bool enqueue =
|
||||||
!!mForcedCount || mSuspended || mFlushing || !mEventQueue.IsEmpty();
|
!!mForcedCount || mSuspended || mFlushing || !mEventQueue.IsEmpty() ||
|
||||||
|
MaybeSuspendIfEventsAreSuppressed();
|
||||||
|
|
||||||
if (enqueue) {
|
if (enqueue) {
|
||||||
mEventQueue.AppendElement(std::move(event));
|
mEventQueue.AppendElement(std::move(event));
|
||||||
|
@ -292,7 +302,8 @@ inline void ChannelEventQueue::MaybeFlushQueue() {
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MutexAutoLock lock(mMutex);
|
||||||
flushQueue =
|
flushQueue =
|
||||||
!mForcedCount && !mFlushing && !mSuspended && !mEventQueue.IsEmpty();
|
!mForcedCount && !mFlushing && !mSuspended && !mEventQueue.IsEmpty() &&
|
||||||
|
!MaybeSuspendIfEventsAreSuppressed();
|
||||||
|
|
||||||
// Only one thread is allowed to run FlushQueue at a time.
|
// Only one thread is allowed to run FlushQueue at a time.
|
||||||
if (flushQueue) {
|
if (flushQueue) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче