зеркало из https://github.com/mozilla/gecko-dev.git
Remove nsDummyLayoutRequest and use the nsIDocument onload-blocking API
instead. Bug 294114, r=dbaron, sr=jst
This commit is contained in:
Родитель
1c09f673ce
Коммит
7c5cfe2f80
|
@ -93,8 +93,8 @@ class nsILayoutHistoryState;
|
|||
|
||||
// IID for the nsIDocument interface
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0xd7c47f55, 0x480b, 0x4a60, \
|
||||
{ 0x9a, 0xdf, 0xca, 0x49, 0x87, 0x3c, 0x71, 0xe2 } }
|
||||
{ 0xd0128d9f, 0x8d36, 0x4944, \
|
||||
{ 0xb2, 0x4b, 0x05, 0xba, 0xc2, 0x73, 0x1c, 0x66 } }
|
||||
|
||||
// The base value for the content ID counter.
|
||||
// This counter is used by the document to
|
||||
|
@ -727,8 +727,9 @@ public:
|
|||
* should block onload is posted. onload is guaranteed to not fire until
|
||||
* either all calls to BlockOnload() have been matched by calls to
|
||||
* UnblockOnload() or the load has been stopped altogether (by the user
|
||||
* pressing the Stop button, say). onload may fire synchronously from inside
|
||||
* the UnblockOnload() call.
|
||||
* pressing the Stop button, say). onload will fire asynchronously after all
|
||||
* onload blocks have been removed. It will NOT fire from inside
|
||||
* UnblockOnload.
|
||||
*/
|
||||
virtual void BlockOnload() = 0;
|
||||
virtual void UnblockOnload() = 0;
|
||||
|
|
|
@ -127,6 +127,9 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
|
|||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsILink.h"
|
||||
#include "plevent.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIEventQueue.h"
|
||||
|
||||
#include "nsICharsetAlias.h"
|
||||
#include "nsIParser.h"
|
||||
|
@ -5052,7 +5055,9 @@ nsDocument::GetLayoutHistoryState() const
|
|||
void
|
||||
nsDocument::BlockOnload()
|
||||
{
|
||||
if (mOnloadBlockCount == 0) {
|
||||
// If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup
|
||||
// -- it's not ours.
|
||||
if (mOnloadBlockCount == 0 && mScriptGlobalObject) {
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
|
||||
if (loadGroup) {
|
||||
loadGroup->AddRequest(mOnloadBlocker, nsnull);
|
||||
|
@ -5065,17 +5070,96 @@ void
|
|||
nsDocument::UnblockOnload()
|
||||
{
|
||||
if (mOnloadBlockCount == 0) {
|
||||
NS_NOTREACHED("More UnblockOnload() calls than BlockOnload() calls; dropping call");
|
||||
return;
|
||||
}
|
||||
|
||||
--mOnloadBlockCount;
|
||||
|
||||
if (mOnloadBlockCount == 0) {
|
||||
// If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup
|
||||
// -- it's not ours.
|
||||
if (mOnloadBlockCount == 0 && mScriptGlobalObject) {
|
||||
PostUnblockOnloadEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::PostUnblockOnloadEvent()
|
||||
{
|
||||
nsCOMPtr<nsIEventQueueService> eventQService =
|
||||
do_GetService("@mozilla.org/event-queue-service;1");
|
||||
if (!eventQService) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEventQueue> eventQ;
|
||||
eventQService->GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE,
|
||||
getter_AddRefs(eventQ));
|
||||
if (!eventQ) {
|
||||
return;
|
||||
}
|
||||
|
||||
PLEvent* evt = new PLEvent();
|
||||
if (!evt) {
|
||||
return;
|
||||
}
|
||||
|
||||
PL_InitEvent(evt, this, nsDocument::HandleOnloadBlockerEvent,
|
||||
nsDocument::DestroyOnloadBlockerEvent);
|
||||
|
||||
// After this point, event destruction will release |this|
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
nsresult rv = eventQ->PostEvent(evt);
|
||||
if (NS_FAILED(rv)) {
|
||||
PL_DestroyEvent(evt);
|
||||
} else {
|
||||
// Stabilize block count so we don't post more events while this one is up
|
||||
++mOnloadBlockCount;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void* PR_CALLBACK
|
||||
nsDocument::HandleOnloadBlockerEvent(PLEvent* aEvent)
|
||||
{
|
||||
nsDocument* doc = NS_STATIC_CAST(nsDocument*, aEvent->owner);
|
||||
doc->DoUnblockOnload();
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// static
|
||||
void PR_CALLBACK
|
||||
nsDocument::DestroyOnloadBlockerEvent(PLEvent* aEvent)
|
||||
{
|
||||
nsDocument* doc = NS_STATIC_CAST(nsDocument*, aEvent->owner);
|
||||
NS_RELEASE(doc);
|
||||
delete aEvent;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::DoUnblockOnload()
|
||||
{
|
||||
NS_ASSERTION(mOnloadBlockCount != 0,
|
||||
"Shouldn't have a count of zero here, since we stabilized in "
|
||||
"PostUnblockOnloadEvent");
|
||||
|
||||
--mOnloadBlockCount;
|
||||
|
||||
if (mOnloadBlockCount != 0) {
|
||||
// We blocked again after the last unblock. Nothing to do here. We'll
|
||||
// post a new event when we unblock again.
|
||||
return;
|
||||
}
|
||||
|
||||
// If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup
|
||||
// -- it's not ours.
|
||||
if (mScriptGlobalObject) {
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
|
||||
if (loadGroup) {
|
||||
loadGroup->RemoveRequest(mOnloadBlocker, nsnull, NS_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -108,6 +108,17 @@ class nsIRadioVisitor;
|
|||
class nsIFormControl;
|
||||
struct nsRadioGroupStruct;
|
||||
class nsOnloadBlocker;
|
||||
struct PLEvent;
|
||||
|
||||
PR_BEGIN_EXTERN_C
|
||||
/* Note that these typedefs declare functions, not pointer to
|
||||
functions. That's the only way in which they differ from
|
||||
PLHandleEventProc and PLDestroyEventProc. */
|
||||
typedef void*
|
||||
(PR_CALLBACK EventHandlerFunc)(PLEvent* self);
|
||||
typedef void
|
||||
(PR_CALLBACK EventDestructorFunc)(PLEvent* self);
|
||||
PR_END_EXTERN_C
|
||||
|
||||
/**
|
||||
* Hashentry using a PRUint32 key and a cheap set of nsIContent* owning
|
||||
|
@ -742,6 +753,11 @@ protected:
|
|||
private:
|
||||
nsresult IsAllowedAsChild(PRUint16 aNodeType, nsIContent* aRefContent);
|
||||
|
||||
void PostUnblockOnloadEvent();
|
||||
static EventHandlerFunc HandleOnloadBlockerEvent;
|
||||
static EventDestructorFunc DestroyOnloadBlockerEvent;
|
||||
void DoUnblockOnload();
|
||||
|
||||
// These are not implemented and not supported.
|
||||
nsDocument(const nsDocument& aOther);
|
||||
nsDocument& operator=(const nsDocument& aOther);
|
||||
|
|
|
@ -59,7 +59,6 @@
|
|||
#include "nsPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsDummyLayoutRequest.h"
|
||||
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
|
|
@ -85,7 +85,6 @@
|
|||
#include "nsReadableUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsDummyLayoutRequest.h"
|
||||
#include "nsLayoutErrors.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
|
|
@ -189,9 +189,6 @@
|
|||
#endif
|
||||
#include "nsPlaceholderFrame.h"
|
||||
|
||||
// Dummy layout request
|
||||
#include "nsDummyLayoutRequest.h"
|
||||
|
||||
// Content viewer interfaces
|
||||
#include "nsIContentViewer.h"
|
||||
|
||||
|
@ -765,57 +762,6 @@ struct nsCallbackEventRequest
|
|||
};
|
||||
|
||||
|
||||
PRInt32 nsDummyLayoutRequest::gRefCnt;
|
||||
nsIURI* nsDummyLayoutRequest::gURI;
|
||||
|
||||
NS_IMPL_ADDREF(nsDummyLayoutRequest)
|
||||
NS_IMPL_RELEASE(nsDummyLayoutRequest)
|
||||
NS_IMPL_QUERY_INTERFACE2(nsDummyLayoutRequest, nsIRequest, nsIChannel)
|
||||
|
||||
nsresult
|
||||
nsDummyLayoutRequest::Create(nsIRequest** aResult, nsIPresShell* aPresShell)
|
||||
{
|
||||
*aResult = new nsDummyLayoutRequest(aPresShell);
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsDummyLayoutRequest::nsDummyLayoutRequest(nsIPresShell* aPresShell)
|
||||
{
|
||||
if (gRefCnt++ == 0) {
|
||||
nsresult rv;
|
||||
rv = NS_NewURI(&gURI, "about:layout-dummy-request", nsnull);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create about:layout-dummy-request");
|
||||
}
|
||||
|
||||
mPresShell = do_GetWeakReference(aPresShell);
|
||||
}
|
||||
|
||||
|
||||
nsDummyLayoutRequest::~nsDummyLayoutRequest()
|
||||
{
|
||||
if (--gRefCnt == 0) {
|
||||
NS_IF_RELEASE(gURI);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDummyLayoutRequest::Cancel(nsresult status)
|
||||
{
|
||||
// Cancel layout
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell);
|
||||
if (presShell) {
|
||||
rv = presShell->CancelAllReflowCommands();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
@ -1121,9 +1067,8 @@ public:
|
|||
nsIAtom* aChildListName);
|
||||
NS_IMETHOD CancelReflowCommand(nsIFrame* aTargetFrame,
|
||||
nsReflowType* aCmdType);
|
||||
NS_IMETHOD CancelReflowCommandInternal(nsIFrame* aTargetFrame,
|
||||
nsReflowType* aCmdType,
|
||||
PRBool aProcessDummyLayoutRequest = PR_TRUE);
|
||||
void CancelReflowCommandInternal(nsIFrame* aTargetFrame,
|
||||
nsReflowType* aCmdType);
|
||||
NS_IMETHOD CancelAllReflowCommands();
|
||||
NS_IMETHOD IsSafeToFlush(PRBool& aIsSafeToFlush);
|
||||
NS_IMETHOD FlushPendingNotifications(mozFlushType aType);
|
||||
|
@ -1334,17 +1279,13 @@ protected:
|
|||
nsresult ReflowCommandAdded(nsHTMLReflowCommand* aRC);
|
||||
nsresult ReflowCommandRemoved(nsHTMLReflowCommand* aRC);
|
||||
|
||||
// This method should be called after a reflow commands have been
|
||||
// This method should be called after reflow commands have been
|
||||
// removed from the queue, but after the state in the presshell is
|
||||
// such that it's safe to flush (i.e. mIsReflowing == PR_FALSE)
|
||||
// If we are not reflowing and there are no load-crated reflow commands, then
|
||||
// the dummyLayoutRequest is removed
|
||||
// If there are no load-created reflow commands and we blocked
|
||||
// onload on the document, we'll unblock it.
|
||||
void DoneRemovingReflowCommands();
|
||||
|
||||
friend struct DummyLayoutRequestEvent;
|
||||
nsresult AddDummyLayoutRequest(void);
|
||||
nsresult RemoveDummyLayoutRequest();
|
||||
|
||||
friend struct CantRenderReplacedElementEvent;
|
||||
NS_HIDDEN_(void) DequeuePostedEventFor(nsIFrame* aFrame);
|
||||
NS_HIDDEN_(CantRenderReplacedElementEvent**)
|
||||
|
@ -1405,6 +1346,7 @@ protected:
|
|||
PLDHashTable mReflowCommandTable;
|
||||
|
||||
PRPackedBool mDocumentLoading;
|
||||
PRPackedBool mDocumentOnloadBlocked;
|
||||
PRPackedBool mIsReflowing;
|
||||
PRPackedBool mIsDestroying;
|
||||
PRPackedBool mIsReleasingAnonymousContent;
|
||||
|
@ -1432,9 +1374,6 @@ protected:
|
|||
nsCOMPtr<nsICaret> mCaret;
|
||||
PRInt16 mSelectionFlags;
|
||||
PRPackedBool mBatchReflows; // When set to true, the pres shell batches reflow commands.
|
||||
// When mDummyLayoutRequestEventPosted is true, we have an event
|
||||
// posted that will call RemoveDummyLayoutRequest when it fires.
|
||||
PRPackedBool mDummyLayoutRequestEventPosted;
|
||||
PresShellViewEventListener *mViewEventListener;
|
||||
nsCOMPtr<nsIEventQueueService> mEventQueueService;
|
||||
nsCOMPtr<nsIEventQueue> mReflowEventQueue;
|
||||
|
@ -1442,24 +1381,6 @@ protected:
|
|||
StackArena* mStackArena;
|
||||
nsCOMPtr<nsIDragService> mDragService;
|
||||
PRInt32 mRCCreatedDuringLoad; // Counter to keep track of reflow commands created during doc
|
||||
// The dummy layout request is used to prevent onload from firing
|
||||
// until after all the reflows that were posted during document load
|
||||
// have been processed. The control flow here is the following:
|
||||
// 1) Any time a reflow command is added while the document is loading, if
|
||||
// we do not already have a dummy layout request we go ahead and create
|
||||
// one.
|
||||
// 2) Any time we've removed all reflow commands that were added during
|
||||
// document load and have a mDummyLayoutRequest we post an event to
|
||||
// remove this request. The one exception is when we're destroying the
|
||||
// presshell; then we don't post an event (see item #4).
|
||||
// 3) While the event to remove the request is posted,
|
||||
// mDummyLayoutRequestEventPosted is set to true. It's set to false when
|
||||
// the event fires, before removing the request. While this boolean is
|
||||
// set, additional events are _not_ posted.
|
||||
// 4) Destroy() guarantees that the dummy layout request is removed by
|
||||
// calling RemoveDummyLayoutRequest(), since we may already have no
|
||||
// reflow commands around and we revoke our events.
|
||||
nsCOMPtr<nsIRequest> mDummyLayoutRequest;
|
||||
|
||||
CantRenderReplacedElementEvent* mPostedReplaces;
|
||||
|
||||
|
@ -1992,8 +1913,9 @@ PresShell::Destroy()
|
|||
|
||||
CancelAllReflowCommands();
|
||||
|
||||
RemoveDummyLayoutRequest();
|
||||
|
||||
NS_ASSERTION(!mDocumentOnloadBlocked,
|
||||
"CancelAllReflowCommands() didn't unblock onload?");
|
||||
|
||||
KillResizeEventTimer();
|
||||
|
||||
// Now that mReflowCommandTable won't be accessed anymore, finish it
|
||||
|
@ -3771,10 +3693,9 @@ PresShell::GetViewToScroll(nsLayoutUtils::Direction aDirection)
|
|||
return scrollView;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
PresShell::CancelReflowCommandInternal(nsIFrame* aTargetFrame,
|
||||
nsReflowType* aCmdType,
|
||||
PRBool aProcessDummyLayoutRequest)
|
||||
nsReflowType* aCmdType)
|
||||
{
|
||||
PRInt32 i, n = mReflowCommands.Count();
|
||||
for (i = 0; i < n; i++) {
|
||||
|
@ -3796,18 +3717,15 @@ PresShell::CancelReflowCommandInternal(nsIFrame* aTargetFrame,
|
|||
}
|
||||
}
|
||||
|
||||
if (aProcessDummyLayoutRequest) {
|
||||
DoneRemovingReflowCommands();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
DoneRemovingReflowCommands();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::CancelReflowCommand(nsIFrame* aTargetFrame,
|
||||
nsReflowType* aCmdType)
|
||||
{
|
||||
return CancelReflowCommandInternal(aTargetFrame, aCmdType);
|
||||
CancelReflowCommandInternal(aTargetFrame, aCmdType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3923,15 +3841,9 @@ struct CantRenderReplacedElementEvent : public PLEvent {
|
|||
CantRenderReplacedElementEvent(PresShell* aPresShell,
|
||||
nsIFrame* aFrame) NS_HIDDEN;
|
||||
~CantRenderReplacedElementEvent() {
|
||||
RemoveLoadGroupRequest();
|
||||
OurPresShell()->GetDocument()->UnblockOnload();
|
||||
}
|
||||
|
||||
// XXXldb Should the pres shell maintain a reference count on a single
|
||||
// dummy layout request instead of doing creation of a separate one
|
||||
// here (and per-event!)?
|
||||
// XXXbz absolutely! Should be a per-document counter, actually....
|
||||
NS_HIDDEN_(void) AddLoadGroupRequest();
|
||||
NS_HIDDEN_(void) RemoveLoadGroupRequest();
|
||||
NS_HIDDEN_(PresShell*) OurPresShell() {
|
||||
return NS_STATIC_CAST(PresShell*, owner);
|
||||
}
|
||||
|
@ -3940,7 +3852,6 @@ struct CantRenderReplacedElementEvent : public PLEvent {
|
|||
|
||||
nsIFrame* mFrame; // the frame that can't be rendered
|
||||
CantRenderReplacedElementEvent* mNext; // next event in the list
|
||||
nsCOMPtr<nsIRequest> mDummyLayoutRequest; // load group request
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(void*)
|
||||
|
@ -3969,10 +3880,7 @@ CantRenderReplacedElementEvent::CantRenderReplacedElementEvent(PresShell* aPresS
|
|||
::HandleCantRenderReplacedElementEvent,
|
||||
::DestroyCantRenderReplacedElementEvent);
|
||||
|
||||
// XXXbz why only for object frames?
|
||||
if (nsLayoutAtoms::objectFrame == aFrame->GetType()) {
|
||||
AddLoadGroupRequest();
|
||||
}
|
||||
aPresShell->GetDocument()->BlockOnload();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -4013,57 +3921,6 @@ PresShell::DequeuePostedEventFor(nsIFrame* aFrame)
|
|||
}
|
||||
}
|
||||
|
||||
// Add a load group request in order to delay the onLoad handler when we have
|
||||
// pending replacements
|
||||
void
|
||||
CantRenderReplacedElementEvent::AddLoadGroupRequest()
|
||||
{
|
||||
PresShell* presShell = OurPresShell();
|
||||
nsIDocument *doc = presShell->GetDocument();
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsDummyLayoutRequest::Create(getter_AddRefs(mDummyLayoutRequest), presShell);
|
||||
if (!mDummyLayoutRequest) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
|
||||
if (!loadGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = mDummyLayoutRequest->SetLoadGroup(loadGroup);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadGroup->AddRequest(mDummyLayoutRequest, nsnull);
|
||||
}
|
||||
|
||||
// Remove the load group request added above
|
||||
void
|
||||
CantRenderReplacedElementEvent::RemoveLoadGroupRequest()
|
||||
{
|
||||
if (mDummyLayoutRequest) {
|
||||
nsCOMPtr<nsIRequest> request = mDummyLayoutRequest;
|
||||
mDummyLayoutRequest = nsnull;
|
||||
|
||||
nsIDocument *doc = OurPresShell()->GetDocument();
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
|
||||
if (!loadGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
loadGroup->RemoveRequest(request, nsnull, NS_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CantRenderReplacedElementEvent::HandleEvent()
|
||||
{
|
||||
|
@ -6907,7 +6764,7 @@ PresShell::ProcessReflowCommands(PRBool aInterruptible)
|
|||
#endif
|
||||
|
||||
// If there are no more reflow commands in the queue, we'll want
|
||||
// to remove the ``dummy request''.
|
||||
// to unblock onload.
|
||||
DoneRemovingReflowCommands();
|
||||
|
||||
DidDoReflow();
|
||||
|
@ -6963,8 +6820,9 @@ PresShell::ReflowCommandAdded(nsHTMLReflowCommand* aRC)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!mDummyLayoutRequest) {
|
||||
AddDummyLayoutRequest();
|
||||
if (!mDocumentOnloadBlocked) {
|
||||
mDocument->BlockOnload();
|
||||
mDocumentOnloadBlocked = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6991,128 +6849,18 @@ PresShell::ReflowCommandRemoved(nsHTMLReflowCommand* aRC)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
struct DummyLayoutRequestEvent : public PLEvent {
|
||||
DummyLayoutRequestEvent(PresShell* aPresShell) NS_HIDDEN;
|
||||
~DummyLayoutRequestEvent() { }
|
||||
|
||||
void HandleEvent() {
|
||||
// Hold a ref here, just in case, since we can trigger DOM event dispatch
|
||||
nsRefPtr<PresShell> presShell = NS_STATIC_CAST(PresShell*, owner);
|
||||
presShell->mDummyLayoutRequestEventPosted = PR_FALSE;
|
||||
presShell->RemoveDummyLayoutRequest();
|
||||
}
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(void*)
|
||||
HandleDummyLayoutRequestPLEvent(PLEvent* aEvent)
|
||||
{
|
||||
DummyLayoutRequestEvent* evt = NS_STATIC_CAST(DummyLayoutRequestEvent*,
|
||||
aEvent);
|
||||
evt->HandleEvent();
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(void)
|
||||
DestroyDummyLayoutRequestPLEvent(PLEvent* aEvent)
|
||||
{
|
||||
DummyLayoutRequestEvent* evt = NS_STATIC_CAST(DummyLayoutRequestEvent*,
|
||||
aEvent);
|
||||
|
||||
delete evt;
|
||||
}
|
||||
|
||||
DummyLayoutRequestEvent::DummyLayoutRequestEvent(PresShell* aPresShell)
|
||||
{
|
||||
NS_PRECONDITION(aPresShell, "Must have a presshell");
|
||||
NS_PRECONDITION(aPresShell->mDummyLayoutRequest, "No layout request?");
|
||||
|
||||
PL_InitEvent(this, aPresShell, ::HandleDummyLayoutRequestPLEvent,
|
||||
::DestroyDummyLayoutRequestPLEvent);
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::DoneRemovingReflowCommands()
|
||||
{
|
||||
if (mRCCreatedDuringLoad == 0 && mDummyLayoutRequest && !mIsReflowing &&
|
||||
!mIsDestroying && !mDummyLayoutRequestEventPosted) {
|
||||
// Post an event to remove mDummyLayoutRequest from the loadgroup
|
||||
nsCOMPtr<nsIEventQueue> eventQueue;
|
||||
mEventQueueService->
|
||||
GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE,
|
||||
getter_AddRefs(eventQueue));
|
||||
if (!eventQueue) {
|
||||
NS_WARNING("onload won't fire, due to failure to get event queue.");
|
||||
return;
|
||||
}
|
||||
|
||||
DummyLayoutRequestEvent* evt = new DummyLayoutRequestEvent(this);
|
||||
if (!evt) {
|
||||
NS_WARNING("onload won't fire, due to failure to create event.");
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = eventQueue->PostEvent(evt);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("onload won't fire, due to failure to post dummy layout "
|
||||
"request event");
|
||||
PL_DestroyEvent(evt);
|
||||
return;
|
||||
}
|
||||
|
||||
mDummyLayoutRequestEventPosted = PR_TRUE;
|
||||
// We want to unblock here even if we're destroying, since onload
|
||||
// can well fire with no presentation in sight. So just check
|
||||
// whether we actually blocked onload.
|
||||
if (mRCCreatedDuringLoad == 0 && mDocumentOnloadBlocked) {
|
||||
mDocument->UnblockOnload();
|
||||
mDocumentOnloadBlocked = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
PresShell::AddDummyLayoutRequest(void)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (gAsyncReflowDuringDocLoad && !mIsReflowing) {
|
||||
rv = nsDummyLayoutRequest::Create(getter_AddRefs(mDummyLayoutRequest), this);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
if (mDocument)
|
||||
loadGroup = mDocument->GetDocumentLoadGroup();
|
||||
|
||||
if (loadGroup) {
|
||||
rv = mDummyLayoutRequest->SetLoadGroup(loadGroup);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = loadGroup->AddRequest(mDummyLayoutRequest, nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
("presshell=%p, Added dummy layout request %p", this, mDummyLayoutRequest.get()));
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PresShell::RemoveDummyLayoutRequest()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (gAsyncReflowDuringDocLoad) {
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
if (mDocument)
|
||||
loadGroup = mDocument->GetDocumentLoadGroup();
|
||||
|
||||
if (loadGroup && mDummyLayoutRequest) {
|
||||
rv = loadGroup->RemoveRequest(mDummyLayoutRequest, nsnull, NS_OK);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PR_LOG(gLog, PR_LOG_ALWAYS,
|
||||
("presshell=%p, Removed dummy layout request %p", this,
|
||||
mDummyLayoutRequest.get()));
|
||||
|
||||
mDummyLayoutRequest = nsnull;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
/*
|
||||
* It's better to add stuff to the |DidSetStyleContext| method of the
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsDummyLayoutRequest_h__
|
||||
#define nsDummyLayoutRequest_h__
|
||||
|
||||
#include "nsIChannel.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsWeakPtr.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// DummyLayoutRequest
|
||||
//
|
||||
// This is a dummy request implementation that we add to the document's load
|
||||
// group. It ensures that EndDocumentLoad() in the docshell doesn't fire
|
||||
// before we've finished all of layout.
|
||||
//
|
||||
|
||||
class nsDummyLayoutRequest : public nsIChannel
|
||||
{
|
||||
protected:
|
||||
nsDummyLayoutRequest(nsIPresShell* aPresShell);
|
||||
virtual ~nsDummyLayoutRequest();
|
||||
|
||||
static PRInt32 gRefCnt;
|
||||
static nsIURI* gURI;
|
||||
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsWeakPtr mPresShell;
|
||||
|
||||
public:
|
||||
static nsresult
|
||||
Create(nsIRequest** aResult, nsIPresShell* aPresShell);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRequest
|
||||
NS_IMETHOD GetName(nsACString &result) {
|
||||
result.AssignLiteral("about:layout-dummy-request");
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHOD IsPending(PRBool *_retval) { *_retval = PR_TRUE; return NS_OK; }
|
||||
NS_IMETHOD GetStatus(nsresult *status) { *status = NS_OK; return NS_OK; }
|
||||
NS_IMETHOD Cancel(nsresult status);
|
||||
NS_IMETHOD Suspend(void) { return NS_OK; }
|
||||
NS_IMETHOD Resume(void) { return NS_OK; }
|
||||
NS_IMETHOD GetLoadGroup(nsILoadGroup * *aLoadGroup) { *aLoadGroup = mLoadGroup; NS_IF_ADDREF(*aLoadGroup); return NS_OK; }
|
||||
NS_IMETHOD SetLoadGroup(nsILoadGroup * aLoadGroup) { mLoadGroup = aLoadGroup; return NS_OK; }
|
||||
NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags) { *aLoadFlags = nsIRequest::LOAD_NORMAL; return NS_OK; }
|
||||
NS_IMETHOD SetLoadFlags(nsLoadFlags aLoadFlags) { return NS_OK; }
|
||||
|
||||
// nsIChannel
|
||||
NS_IMETHOD GetOriginalURI(nsIURI* *aOriginalURI) { *aOriginalURI = gURI; NS_ADDREF(*aOriginalURI); return NS_OK; }
|
||||
NS_IMETHOD SetOriginalURI(nsIURI* aOriginalURI) { gURI = aOriginalURI; NS_ADDREF(gURI); return NS_OK; }
|
||||
NS_IMETHOD GetURI(nsIURI* *aURI) { *aURI = gURI; NS_ADDREF(*aURI); return NS_OK; }
|
||||
NS_IMETHOD SetURI(nsIURI* aURI) { gURI = aURI; NS_ADDREF(gURI); return NS_OK; }
|
||||
NS_IMETHOD Open(nsIInputStream **_retval) { *_retval = nsnull; return NS_OK; }
|
||||
NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) { return NS_OK; }
|
||||
NS_IMETHOD GetOwner(nsISupports * *aOwner) { *aOwner = nsnull; return NS_OK; }
|
||||
NS_IMETHOD SetOwner(nsISupports * aOwner) { return NS_OK; }
|
||||
NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor * *aNotificationCallbacks) { *aNotificationCallbacks = nsnull; return NS_OK; }
|
||||
NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor * aNotificationCallbacks) { return NS_OK; }
|
||||
NS_IMETHOD GetSecurityInfo(nsISupports * *aSecurityInfo) { *aSecurityInfo = nsnull; return NS_OK; }
|
||||
NS_IMETHOD GetContentType(nsACString &aContentType) { aContentType.Truncate(); return NS_OK; }
|
||||
NS_IMETHOD SetContentType(const nsACString &aContentType) { return NS_OK; }
|
||||
NS_IMETHOD GetContentCharset(nsACString &aContentCharset) { aContentCharset.Truncate(); return NS_OK; }
|
||||
NS_IMETHOD SetContentCharset(const nsACString &aContentCharset) { return NS_OK; }
|
||||
NS_IMETHOD GetContentLength(PRInt32 *aContentLength) { return NS_OK; }
|
||||
NS_IMETHOD SetContentLength(PRInt32 aContentLength) { return NS_OK; }
|
||||
};
|
||||
|
||||
#endif
|
Загрузка…
Ссылка в новой задаче