mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 12:25:53 +00:00
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:
parent
d0f7b1b700
commit
a655254f45
@ -9,7 +9,8 @@
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
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 mozilla
|
||||
|
@ -86,6 +86,8 @@ class ChannelEventQueue final {
|
||||
mSuspended(false),
|
||||
mForcedCount(0),
|
||||
mFlushing(false),
|
||||
mHasCheckedForXMLHttpRequest(false),
|
||||
mForXMLHttpRequest(false),
|
||||
mOwner(owner),
|
||||
mMutex("ChannelEventQueue::mMutex"),
|
||||
mRunningMutex("ChannelEventQueue::mRunningMutex") {}
|
||||
@ -126,6 +128,8 @@ class ChannelEventQueue final {
|
||||
void SuspendInternal();
|
||||
void ResumeInternal();
|
||||
|
||||
bool MaybeSuspendIfEventsAreSuppressed();
|
||||
|
||||
inline void MaybeFlushQueue();
|
||||
void FlushQueue();
|
||||
inline void CompleteResume();
|
||||
@ -139,6 +143,11 @@ class ChannelEventQueue final {
|
||||
uint32_t mForcedCount; // Support ForcedQueueing on multiple thread.
|
||||
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.
|
||||
nsISupports* mOwner;
|
||||
|
||||
@ -172,7 +181,8 @@ inline void ChannelEventQueue::RunOrEnqueue(ChannelEvent* aCallback,
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
bool enqueue =
|
||||
!!mForcedCount || mSuspended || mFlushing || !mEventQueue.IsEmpty();
|
||||
!!mForcedCount || mSuspended || mFlushing || !mEventQueue.IsEmpty() ||
|
||||
MaybeSuspendIfEventsAreSuppressed();
|
||||
|
||||
if (enqueue) {
|
||||
mEventQueue.AppendElement(std::move(event));
|
||||
@ -292,7 +302,8 @@ inline void ChannelEventQueue::MaybeFlushQueue() {
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
flushQueue =
|
||||
!mForcedCount && !mFlushing && !mSuspended && !mEventQueue.IsEmpty();
|
||||
!mForcedCount && !mFlushing && !mSuspended && !mEventQueue.IsEmpty() &&
|
||||
!MaybeSuspendIfEventsAreSuppressed();
|
||||
|
||||
// Only one thread is allowed to run FlushQueue at a time.
|
||||
if (flushQueue) {
|
||||
|
Loading…
Reference in New Issue
Block a user