Back to index

lightning-sunbird  0.9+nobinonly
Classes | Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | Friends
nsImageLoadingContent Class Reference

#include <nsImageLoadingContent.h>

Inheritance diagram for nsImageLoadingContent:
Inheritance graph
[legend]
Collaboration diagram for nsImageLoadingContent:
Collaboration graph
[legend]

List of all members.

Classes

class  Event
 Struct used to dispatch events. More...
struct  ImageObserver
 Struct used to manage the image observers. More...

Public Member Functions

 nsImageLoadingContent ()
virtual ~nsImageLoadingContent ()
 NS_IMETHOD_ (nsrefcnt) AddRef(void)=0
 NS_IMETHOD_ (nsrefcnt) Release(void)=0
void addObserver (in imgIDecoderObserver aObserver)
 Used to register an image decoder observer.
void removeObserver (in imgIDecoderObserver aObserver)
 Used to unregister an image decoder observer.
imgIRequest getRequest (in long aRequestType)
 Accessor to get the image requests.
long getRequestType (in imgIRequest aRequest)
 Used to find out what type of request one is dealing with (eg which request got passed through to the imgIDecoderObserver interface of an observer)
nsIStreamListener loadImageWithChannel (in nsIChannel aChannel)
 loadImageWithChannel allows data from an existing channel to be used as the image data for this content node.
void imageURIChanged (in AString aNewURI)
 ImageURIChanged is called when the appropriate attributes (eg 'src' for.
void onStartDecode (in imgIRequest aRequest)
 called as soon as the image begins getting decoded
void onStartContainer (in imgIRequest aRequest, in imgIContainer aContainer)
 called once the image has been inited and therefore has a width and height
void onStartFrame (in imgIRequest aRequest, in gfxIImageFrame aFrame)
 called when each frame is created
void onDataAvailable (in imgIRequest aRequest, in gfxIImageFrame aFrame,[const ] in nsIntRect aRect)
 called when some part of the frame has new data in it
void onStopFrame (in imgIRequest aRequest, in gfxIImageFrame aFrame)
 called when a frame is finished decoding
void onStopContainer (in imgIRequest aRequest, in imgIContainer aContainer)
 probably not needed.
void onStopDecode (in imgIRequest aRequest, in nsresult status, in wstring statusArg)
 called when the decoder is dying off
void frameChanged (in imgIContainer aContainer, in gfxIImageFrame aFrame, in nsIntRect aDirtyRect)
void onStartRequest (in imgIRequest aRequest)
 called at the same time that nsIRequestObserver::onStartRequest would be (used only for observers of imgIRequest objects, which are nsIRequests, not imgIDecoder objects)
void onStopRequest (in imgIRequest aRequest, in boolean aIsLastPart)
 called at the same time that nsIRequestObserver::onStopRequest would be (used only for observers of imgIRequest objects, which are nsIRequests, not imgIDecoder objects)

Public Attributes

const long UNKNOWN_REQUEST = -1
 Request types.
const long CURRENT_REQUEST = 0
const long PENDING_REQUEST = 1
attribute boolean loadingEnabled
 loadingEnabled is used to enable and disable loading in situations where loading images is unwanted.
readonly attribute short imageBlockingStatus
 Returns the image blocking status (.
readonly attribute nsIURI currentURI
 Gets the URI of the current request, if available.

Protected Member Functions

nsresult ImageURIChanged (const nsAString &aNewURI, PRBool aForce)
 ImageURIChanged is called by subclasses when the appropriate attributes (eg 'src' for.
void CancelImageRequests ()
 CancelImageRequests is called by subclasses when they want to cancel all image requests (for example when the subclass is somehow not an image anymore).
void DestroyImageLoadingContent ()
 Derived classes of nsImageLoadingContent MUST call DestroyImageLoadingContent from their destructor, or earlier.
void PreserveLoadHandlers ()
 Manage the rooting and un-rooting in nsDOMClassInfo of the content node, so that things reachable from the node are protected from garbage collection while the onload or onerror handlers (which can make it reachable again) could fire.
void UnpreserveLoadHandlers ()

Protected Attributes

nsCOMPtr< imgIRequestmCurrentRequest
nsCOMPtr< imgIRequestmPendingRequest
nsCOMPtr< nsIURImCurrentURI

Private Member Functions

void CancelImageRequests (nsresult aReason, PRBool aEvenIfSizeAvailable, PRInt16 aNewImageStatus)
 CancelImageRequests can be called when we want to cancel the image requests, generally due to our src changing and us wanting to start a new load.
nsIDocumentGetOurDocument ()
 helper to get the document for this content (from the nodeinfo and such).
nsresult StringToURI (const nsAString &aSpec, nsIDocument *aDocument, nsIURI **aURI)
 Method to create an nsIURI object from the given string (will handle getting the right charset, base, etc).
nsresult FireEvent (const nsAString &aEventType)
 Method to fire an event once we know what's going on with the image load.

Private Attributes

ImageObserver mObserverList
 Typically we will have only one observer (our frame in the screen prescontext), so we want to only make space for one and to heap-allocate anything past that (saves memory and malloc churn in the common case).
PRInt16 mImageBlockingStatus
PRUint8 mRootRefCount
PRPackedBool mLoadingEnabled

Friends

class Event

Detailed Description

Definition at line 60 of file nsImageLoadingContent.h.


Constructor & Destructor Documentation

Definition at line 135 of file nsImageLoadingContent.cpp.

{
  NS_ASSERTION(!mCurrentRequest && !mPendingRequest,
               "DestroyImageLoadingContent not called");
  NS_ASSERTION(!mObserverList.mObserver && !mObserverList.mNext,
               "Observers still registered?");
}

Member Function Documentation

Used to register an image decoder observer.

Typically, this will be a proxy for a frame that wants to paint the image. Notifications from ongoing image loads will be passed to all registered observers. Notifications for all request types, current and pending, will be passed through.

Parameters:
aObserverthe observer to register
Exceptions:
NS_ERROR_OUT_OF_MEMORY

CancelImageRequests is called by subclasses when they want to cancel all image requests (for example when the subclass is somehow not an image anymore).

Definition at line 586 of file nsImageLoadingContent.cpp.

{
  // Make sure to null out mCurrentURI here, so we no longer look like an image
  mCurrentURI = nsnull;
  CancelImageRequests(NS_BINDING_ABORTED, PR_TRUE, nsIContentPolicy::ACCEPT);
}

Here is the caller graph for this function:

void nsImageLoadingContent::CancelImageRequests ( nsresult  aReason,
PRBool  aEvenIfSizeAvailable,
PRInt16  aNewImageStatus 
) [private]

CancelImageRequests can be called when we want to cancel the image requests, generally due to our src changing and us wanting to start a new load.

The "current" request will be canceled only if it has not progressed far enough to know the image size yet unless aEvenIfSizeAvailable is true.

Parameters:
aReasonthe reason the requests are being canceled
aEvenIfSizeAvailablecancels the current load even if its size is available
aNewImageStatusthe nsIContentPolicy status of the new image load

Definition at line 594 of file nsImageLoadingContent.cpp.

{
  // Cancel the pending request, if any
  if (mPendingRequest) {
    mPendingRequest->Cancel(aReason);
    mPendingRequest = nsnull;
  }

  // Cancel the current request if it has not progressed enough to
  // have a size yet
  if (mCurrentRequest) {
    PRUint32 loadStatus = imgIRequest::STATUS_ERROR;
    mCurrentRequest->GetImageStatus(&loadStatus);

    NS_ASSERTION(NS_CP_ACCEPTED(mImageBlockingStatus),
                 "Have current request but blocked image?");
    
    if (aEvenIfSizeAvailable ||
        !(loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE)) {
      // The new image is going to become the current request.  Make sure to
      // set mImageBlockingStatus _before_ we cancel the request... if we set
      // it after, things that are watching the mCurrentRequest will get wrong
      // data.
      mImageBlockingStatus = aNewImageStatus;
      mCurrentRequest->Cancel(aReason);
      mCurrentRequest = nsnull;
    }
  } else {
    // No current request so the new image status will become the
    // status of the current request
    mImageBlockingStatus = aNewImageStatus;
  }

  // Note that the only way we could have avoided setting the image blocking
  // status above is if we have a current request and have kept it as the
  // current request.  In that case, we want to leave our old status, since the
  // status corresponds to the current request.  Even if we plan to do a
  // pending request load, having an mCurrentRequest means that our current
  // status is not a REJECT_* status, and doing the load shouldn't change that.
  // XXXbz there is an issue here if different ACCEPT statuses are used, but...
}

Derived classes of nsImageLoadingContent MUST call DestroyImageLoadingContent from their destructor, or earlier.

It does things that cannot be done in ~nsImageLoadingContent because they rely on being able to QueryInterface to other derived classes, which cannot happen once the derived class destructor has started calling the base class destructors.

Definition at line 109 of file nsImageLoadingContent.cpp.

{
  // Cancel our requests so they won't hold stale refs to us
  if (mCurrentRequest) {
    mCurrentRequest->Cancel(NS_ERROR_FAILURE);
    mCurrentRequest = nsnull;
  }
  if (mPendingRequest) {
    mPendingRequest->Cancel(NS_ERROR_FAILURE);
    mPendingRequest = nsnull;
  }

  // This can actually fire for multipart/x-mixed-replace, since if the
  // load is canceled between parts (e.g., by cancelling the load
  // group), we won't get any notification.  See bug 321054 comment 31
  // and bug 339610.  *If* that multipart/x-mixed-replace image has
  // event handlers, we won't even get to this warning; we'll leak
  // instead.
  NS_WARN_IF_FALSE(mRootRefCount == 0,
                   "unbalanced handler preservation refcount");
  if (mRootRefCount != 0) {
    mRootRefCount = 1;
    UnpreserveLoadHandlers();
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsImageLoadingContent::FireEvent ( const nsAString &  aEventType) [private]

Method to fire an event once we know what's going on with the image load.

Parameters:
aEventType"load" or "error" depending on how things went

Definition at line 741 of file nsImageLoadingContent.cpp.

{
  // We have to fire the event asynchronously so that we won't go into infinite
  // loops in cases when onLoad handlers reset the src and the new src is in
  // cache.

  nsCOMPtr<nsIDocument> document = GetOurDocument();
  if (!document) {
    // no use to fire events if there is no document....
    return NS_OK;
  }                                                                             
  nsresult rv;
  nsCOMPtr<nsIEventQueueService> eventQService =
    do_GetService("@mozilla.org/event-queue-service;1", &rv);
  NS_ENSURE_TRUE(eventQService, rv);

  nsCOMPtr<nsIEventQueue> eventQ;
  // Use the UI thread event queue (though we should not be getting called from
  // off the UI thread in any case....)
  rv = eventQService->GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE,
                                           getter_AddRefs(eventQ));
  NS_ENSURE_TRUE(eventQ, rv);

  nsIPresShell *shell = document->GetShellAt(0);
  NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);

  nsPresContext *presContext = shell->GetPresContext();
  NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);

  nsImageLoadingContent::Event* evt =
    new Event(presContext, this, aEventType, document);
  NS_ENSURE_TRUE(evt, NS_ERROR_OUT_OF_MEMORY);

  // Block onload for our event.  Since we unblock in the event destructor, we
  // want to block now, even if posting will fail.
  document->BlockOnload();
  PreserveLoadHandlers();
  
  rv = eventQ->PostEvent(evt);

  if (NS_FAILED(rv)) {
    PL_DestroyEvent(evt);
  }

  return rv;
}

Here is the call graph for this function:

void imgIContainerObserver::frameChanged ( in imgIContainer  aContainer,
in gfxIImageFrame  aFrame,
in nsIntRect  aDirtyRect 
) [inherited]

helper to get the document for this content (from the nodeinfo and such).

Not named GetDocument to prevent ambiguous method names in subclasses (though why this private method leads to ambiguity is not clear to me....).

Returns:
the document we belong to

Definition at line 639 of file nsImageLoadingContent.cpp.

{
  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(NS_STATIC_CAST(nsIImageLoadingContent*, this));
  NS_ENSURE_TRUE(thisContent, nsnull);

  return thisContent->GetOwnerDoc();
}

Here is the call graph for this function:

Here is the caller graph for this function:

imgIRequest nsIImageLoadingContent::getRequest ( in long  aRequestType) [inherited]

Accessor to get the image requests.

Parameters:
aRequestTypea value saying which request is wanted
Returns:
the imgIRequest object (may be null, even when no error is thrown)
Exceptions:
NS_ERROR_UNEXPECTEDif the request type requested is not known

Used to find out what type of request one is dealing with (eg which request got passed through to the imgIDecoderObserver interface of an observer)

Parameters:
aRequestthe request whose type we want to know
Returns:
an enum value saying what type this request is
Exceptions:
NS_ERROR_UNEXPECTEDif aRequest is not known
nsresult nsImageLoadingContent::ImageURIChanged ( const nsAString &  aNewURI,
PRBool  aForce 
) [protected]

ImageURIChanged is called by subclasses when the appropriate attributes (eg 'src' for.

tags) change. The string passed in is the new uri string; this consolidates the code for getting the charset, constructing URI objects, and any other incidentals into this superclass.

Note that this is different from the ImageURIChanged(AString) declared in nsIImageLoadingContent.idl -- because it allows control over whether loading is to be forced.

Parameters:
aNewURIthe URI spec to be loaded (may be a relative URI)
aForceIf true, make sure to load the URI. If false, only load if the URI is different from the currently loaded URI.

Definition at line 443 of file nsImageLoadingContent.cpp.

                                                               {
  return ImageURIChanged(aNewURI, PR_TRUE);
}

Here is the caller graph for this function:

void nsIImageLoadingContent::imageURIChanged ( in AString  aNewURI) [inherited]

ImageURIChanged is called when the appropriate attributes (eg 'src' for.

tags) change. The string passed in is the new uri string.

loadImageWithChannel allows data from an existing channel to be used as the image data for this content node.

Parameters:
aChannelthe channel that will deliver the data
Returns:
a stream listener to pump the image data into
See also:
imgILoader::loadImageWithChannel
Exceptions:
NS_ERROR_NULL_POINTERif aChannel is null
void imgIDecoderObserver::onDataAvailable ( in imgIRequest  aRequest,
in gfxIImageFrame  aFrame,
[const ] in nsIntRect  aRect 
) [inherited]

called when some part of the frame has new data in it

void imgIDecoderObserver::onStartContainer ( in imgIRequest  aRequest,
in imgIContainer  aContainer 
) [inherited]

called once the image has been inited and therefore has a width and height

Here is the caller graph for this function:

called as soon as the image begins getting decoded

Here is the caller graph for this function:

void imgIDecoderObserver::onStartFrame ( in imgIRequest  aRequest,
in gfxIImageFrame  aFrame 
) [inherited]

called when each frame is created

called at the same time that nsIRequestObserver::onStartRequest would be (used only for observers of imgIRequest objects, which are nsIRequests, not imgIDecoder objects)

Unlike nsIRequestObserver::onStartRequest, this can be called synchronously.

void imgIDecoderObserver::onStopContainer ( in imgIRequest  aRequest,
in imgIContainer  aContainer 
) [inherited]

probably not needed.

called right before onStopDecode

Here is the caller graph for this function:

void imgIDecoderObserver::onStopDecode ( in imgIRequest  aRequest,
in nsresult  status,
in wstring  statusArg 
) [inherited]

called when the decoder is dying off

Here is the caller graph for this function:

void imgIDecoderObserver::onStopFrame ( in imgIRequest  aRequest,
in gfxIImageFrame  aFrame 
) [inherited]

called when a frame is finished decoding

called at the same time that nsIRequestObserver::onStopRequest would be (used only for observers of imgIRequest objects, which are nsIRequests, not imgIDecoder objects)

Unlike nsIRequestObserver::onStartRequest, this can be called synchronously.

Manage the rooting and un-rooting in nsDOMClassInfo of the content node, so that things reachable from the node are protected from garbage collection while the onload or onerror handlers (which can make it reachable again) could fire.

Definition at line 789 of file nsImageLoadingContent.cpp.

{
  ++mRootRefCount;
  NS_LOG_ADDREF(&mRootRefCount, mRootRefCount,
                "nsImageLoadingContent::mRootRefCount", sizeof(mRootRefCount));
  if (mRootRefCount == 1) {
    nsCOMPtr<nsIDOMGCParticipant> part = do_QueryInterface(NS_STATIC_CAST(nsIImageLoadingContent*, this));
    nsresult rv = nsDOMClassInfo::SetExternallyReferenced(part);
    // The worst that will happen if we ignore this failure is that
    // onload or onerror will fail to fire.  I suppose we could fire
    // onerror now as a result of that, but the only reason it would
    // actually fail is out-of-memory, and it seems silly to bother and
    // unlikely to work in that case.
    NS_ASSERTION(NS_SUCCEEDED(rv), "ignoring failure to root participant");
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Used to unregister an image decoder observer.

Parameters:
aObserverthe observer to unregister
nsresult nsImageLoadingContent::StringToURI ( const nsAString &  aSpec,
nsIDocument aDocument,
nsIURI **  aURI 
) [private]

Method to create an nsIURI object from the given string (will handle getting the right charset, base, etc).

You MUST pass in a non-null document to this function.

Parameters:
aSpecthe string spec (from an HTML attribute, eg)
aDocumentthe document we belong to
Returns:
the URI we want to be loading

Definition at line 648 of file nsImageLoadingContent.cpp.

{
  NS_PRECONDITION(aDocument, "Must have a document");
  NS_PRECONDITION(aURI, "Null out param");

  // (1) Get the base URI
  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(NS_STATIC_CAST(nsIImageLoadingContent*, this));
  NS_ASSERTION(thisContent, "An image loading content must be an nsIContent");
  nsCOMPtr<nsIURI> baseURL = thisContent->GetBaseURI();

  // (2) Get the charset
  const nsACString &charset = aDocument->GetDocumentCharacterSet();

  // (3) Construct the silly thing
  return NS_NewURI(aURI,
                   aSpec,
                   charset.IsEmpty() ? nsnull : PromiseFlatCString(charset).get(),
                   baseURL,
                   nsContentUtils::GetIOServiceWeakRef());
}

Here is the call graph for this function:

Definition at line 807 of file nsImageLoadingContent.cpp.

{
  NS_ASSERTION(mRootRefCount != 0,
               "load handler preservation refcount underflow");
  --mRootRefCount;
  NS_LOG_RELEASE(&mRootRefCount, mRootRefCount,
                 "nsImageLoadingContent::mRootRefCount");
  if (mRootRefCount == 0) {
    nsCOMPtr<nsIDOMGCParticipant> part = do_QueryInterface(NS_STATIC_CAST(nsIImageLoadingContent*, this));
    nsDOMClassInfo::UnsetExternallyReferenced(part);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Friends And Related Function Documentation

friend class Event [friend]

Definition at line 178 of file nsImageLoadingContent.h.


Member Data Documentation

Definition at line 82 of file nsIImageLoadingContent.idl.

Gets the URI of the current request, if available.

Otherwise, returns the last URI that this content tried to load, or null if there haven't been any such attempts.

Definition at line 151 of file nsIImageLoadingContent.idl.

Returns the image blocking status (.

See also:
nsIContentPolicy). This will always be an nsIContentPolicy REJECT_* status for cases when the image was blocked. This status always refers to the CURRENT_REQUEST load.

Definition at line 98 of file nsIImageLoadingContent.idl.

loadingEnabled is used to enable and disable loading in situations where loading images is unwanted.

Note that enabling loading will not automatically trigger an image load.

Definition at line 90 of file nsIImageLoadingContent.idl.

Definition at line 193 of file nsImageLoadingContent.h.

Definition at line 195 of file nsImageLoadingContent.h.

Definition at line 208 of file nsImageLoadingContent.h.

Definition at line 215 of file nsImageLoadingContent.h.

Typically we will have only one observer (our frame in the screen prescontext), so we want to only make space for one and to heap-allocate anything past that (saves memory and malloc churn in the common case).

The storage is a linked list, we just happen to actually hold the first observer instead of a pointer to it.

Definition at line 206 of file nsImageLoadingContent.h.

Definition at line 194 of file nsImageLoadingContent.h.

Definition at line 214 of file nsImageLoadingContent.h.

Definition at line 83 of file nsIImageLoadingContent.idl.

Request types.

Image loading content nodes attempt to do atomic image changes when the image url is changed. This means that when the url changes the new image load will start, but the old image will remain the "current" request until the new image is fully loaded. At that point, the old "current" request will be discarded and the "pending" request will become "current".

Definition at line 81 of file nsIImageLoadingContent.idl.


The documentation for this class was generated from the following files: