Remove nsDummyLayoutRequest and use the nsIDocument onload-blocking API

instead.  Bug 294114, r=dbaron, sr=jst
This commit is contained in:
bzbarsky%mit.edu 2005-08-23 01:29:02 +00:00
Родитель 1c09f673ce
Коммит 7c5cfe2f80
7 изменённых файлов: 134 добавлений и 395 удалений

Просмотреть файл

@ -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