зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1318506 - Label HttpChannelChild actors with DocGroup/TabGroup (r=jduell)
This patch tries to figure out which DocGroup or TabGroup a network request belongs to and then assign the IPC actor to that group. A DocGroup roughly corresponds to a document and a TabGroup to a tab. Once the assignment is made, all incoming IPC messages will be labeled with that DocGroup/TabGroup. MozReview-Commit-ID: EzGCeGdREHl
This commit is contained in:
Родитель
86da1e11a4
Коммит
2113b3347b
|
@ -94,5 +94,20 @@ ChannelEventQueue::RetargetDeliveryTo(nsIEventTarget* aTargetThread)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ChannelEventQueue::ResetDeliveryTarget()
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
MOZ_RELEASE_ASSERT(mEventQueue.IsEmpty());
|
||||
MOZ_RELEASE_ASSERT(mSuspendCount == 0);
|
||||
MOZ_RELEASE_ASSERT(!mSuspended);
|
||||
MOZ_RELEASE_ASSERT(!mForced);
|
||||
MOZ_RELEASE_ASSERT(!mFlushing);
|
||||
mTargetThread = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -77,6 +77,11 @@ class ChannelEventQueue final
|
|||
// Retargets delivery of events to the target thread specified.
|
||||
nsresult RetargetDeliveryTo(nsIEventTarget* aTargetThread);
|
||||
|
||||
// Nulls out the delivery target so events are delivered to the main
|
||||
// thread. Should only be called when the queue is known to be empty.
|
||||
// Useful if the queue will be re-used.
|
||||
nsresult ResetDeliveryTarget();
|
||||
|
||||
private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~ChannelEventQueue()
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
#include "nsICacheEntry.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/dom/TabGroup.h"
|
||||
#include "mozilla/ipc/FileDescriptorSetChild.h"
|
||||
#include "mozilla/ipc/IPCStreamUtils.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
|
@ -20,6 +22,7 @@
|
|||
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsChannelClassifier.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsStringStream.h"
|
||||
#include "nsHttpHandler.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
@ -1212,6 +1215,10 @@ HttpChannelChild::RecvFinishInterceptedRedirect()
|
|||
RefPtr<HttpChannelChild> self(this);
|
||||
Send__delete__(this);
|
||||
|
||||
// Reset the event target to which queued messages are delivered. Otherwise
|
||||
// we'll get an assertion when we re-use the channel later on.
|
||||
mEventQ->ResetDeliveryTarget();
|
||||
|
||||
// The IPDL connection was torn down by a interception logic in
|
||||
// CompleteRedirectSetup, and we need to call FinishInterceptedRedirect.
|
||||
NS_DispatchToMainThread(NewRunnableMethod(this, &HttpChannelChild::FinishInterceptedRedirect));
|
||||
|
@ -1621,6 +1628,11 @@ HttpChannelChild::ConnectParent(uint32_t registrarId)
|
|||
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
|
||||
AddIPDLReference();
|
||||
|
||||
// This must happen before the constructor message is sent. Otherwise messages
|
||||
// from the parent could arrive quickly and be delivered to the wrong event
|
||||
// target.
|
||||
SetEventTarget();
|
||||
|
||||
HttpChannelConnectArgs connectArgs(registrarId, mShouldParentIntercept);
|
||||
PBrowserOrId browser = static_cast<ContentChild*>(gNeckoChild->Manager())
|
||||
->GetBrowserOrId(tabChild);
|
||||
|
@ -2020,6 +2032,55 @@ HttpChannelChild::AsyncOpen2(nsIStreamListener *aListener)
|
|||
return AsyncOpen(listener, nullptr);
|
||||
}
|
||||
|
||||
// Assigns an nsIEventTarget to our IPDL actor so that IPC messages are sent to
|
||||
// the correct DocGroup/TabGroup.
|
||||
void
|
||||
HttpChannelChild::SetEventTarget()
|
||||
{
|
||||
nsCOMPtr<nsILoadInfo> loadInfo;
|
||||
GetLoadInfo(getter_AddRefs(loadInfo));
|
||||
if (!loadInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
loadInfo->GetLoadingDocument(getter_AddRefs(domDoc));
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
||||
RefPtr<Dispatcher> dispatcher;
|
||||
if (doc) {
|
||||
dispatcher = doc->GetDocGroup();
|
||||
} else {
|
||||
// There's no document yet, but this might be a top-level load where we can
|
||||
// find a TabGroup.
|
||||
uint64_t outerWindowId;
|
||||
if (NS_FAILED(loadInfo->GetOuterWindowID(&outerWindowId))) {
|
||||
// No window. This might be an add-on XHR, a service worker request, or
|
||||
// something else.
|
||||
return;
|
||||
}
|
||||
RefPtr<nsGlobalWindow> window = nsGlobalWindow::GetOuterWindowWithId(outerWindowId);
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// We have a TabGroup. This must be a top-level load.
|
||||
bool isMainDocumentChannel;
|
||||
GetIsMainDocumentChannel(&isMainDocumentChannel);
|
||||
MOZ_ASSERT(isMainDocumentChannel);
|
||||
#endif
|
||||
|
||||
dispatcher = window->TabGroup();
|
||||
}
|
||||
|
||||
if (dispatcher) {
|
||||
nsCOMPtr<nsIEventTarget> target =
|
||||
dispatcher->EventTargetFor(TaskCategory::Network);
|
||||
gNeckoChild->SetEventTargetForActor(this, target);
|
||||
mEventQ->RetargetDeliveryTo(target);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
HttpChannelChild::ContinueAsyncOpen()
|
||||
{
|
||||
|
@ -2170,6 +2231,11 @@ HttpChannelChild::ContinueAsyncOpen()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// This must happen before the constructor message is sent. Otherwise messages
|
||||
// from the parent could arrive quickly and be delivered to the wrong event
|
||||
// target.
|
||||
SetEventTarget();
|
||||
|
||||
// The socket transport in the chrome process now holds a logical ref to us
|
||||
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
|
||||
AddIPDLReference();
|
||||
|
|
|
@ -182,6 +182,12 @@ private:
|
|||
nsAutoPtr<nsHttpResponseHead> mHead;
|
||||
};
|
||||
|
||||
// Sets the event target for future IPC messages. Messages will either be
|
||||
// directed to the TabGroup or DocGroup, depending on the LoadInfo associated
|
||||
// with the channel. Should be called when a new channel is being set up,
|
||||
// before the constructor message is sent to the parent.
|
||||
void SetEventTarget();
|
||||
|
||||
nsresult ContinueAsyncOpen();
|
||||
|
||||
void DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext);
|
||||
|
|
Загрузка…
Ссылка в новой задаче