From 7c5cfe2f800939f0ade2235e3e880f06f68d4be7 Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Tue, 23 Aug 2005 01:29:02 +0000 Subject: [PATCH] Remove nsDummyLayoutRequest and use the nsIDocument onload-blocking API instead. Bug 294114, r=dbaron, sr=jst --- content/base/public/nsIDocument.h | 9 +- content/base/src/nsDocument.cpp | 90 +++++- content/base/src/nsDocument.h | 16 ++ content/base/src/nsImageLoadingContent.cpp | 1 - layout/base/nsFrameManager.cpp | 1 - layout/base/nsPresShell.cpp | 304 ++------------------- layout/generic/nsDummyLayoutRequest.h | 108 -------- 7 files changed, 134 insertions(+), 395 deletions(-) delete mode 100644 layout/generic/nsDummyLayoutRequest.h diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index caa25c7fc5f0..3f56121707e4 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -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; diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index cc634560f8ba..ab1103937399 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -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 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 eventQService = + do_GetService("@mozilla.org/event-queue-service;1"); + if (!eventQService) { + return; + } + + nsCOMPtr 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 loadGroup = GetDocumentLoadGroup(); if (loadGroup) { loadGroup->RemoveRequest(mOnloadBlocker, nsnull, NS_OK); } - } + } } void diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 4442fb12b64b..7da607a76046 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -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); diff --git a/content/base/src/nsImageLoadingContent.cpp b/content/base/src/nsImageLoadingContent.cpp index 85ce86bdb733..8e794a277d43 100644 --- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -59,7 +59,6 @@ #include "nsPresContext.h" #include "nsIPresShell.h" #include "nsGUIEvent.h" -#include "nsDummyLayoutRequest.h" #include "nsIChannel.h" #include "nsIStreamListener.h" diff --git a/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index b46ccad961a8..4d808c5994d4 100644 --- a/layout/base/nsFrameManager.cpp +++ b/layout/base/nsFrameManager.cpp @@ -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" diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 9233918232c9..64f96a690f91 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -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 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 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 mEventQueueService; nsCOMPtr mReflowEventQueue; @@ -1442,24 +1381,6 @@ protected: StackArena* mStackArena; nsCOMPtr 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 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 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 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 request = mDummyLayoutRequest; - mDummyLayoutRequest = nsnull; - - nsIDocument *doc = OurPresShell()->GetDocument(); - if (!doc) { - return; - } - - nsCOMPtr 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 = 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 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 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 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 diff --git a/layout/generic/nsDummyLayoutRequest.h b/layout/generic/nsDummyLayoutRequest.h deleted file mode 100644 index b9b5e34ba79b..000000000000 --- a/layout/generic/nsDummyLayoutRequest.h +++ /dev/null @@ -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 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