LCOV - code coverage report
Current view: directory - content/base/src - nsImageLoadingContent.h (source / functions) Found Hit Coverage
Test: app.info Lines: 19 9 47.4 %
Date: 2012-06-02 Functions: 6 2 33.3 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : // vim: ft=cpp tw=78 sw=2 et ts=2
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Boris Zbarsky <bzbarsky@mit.edu>.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2003
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : /*
      40                 :  * A base class which implements nsIImageLoadingContent and can be
      41                 :  * subclassed by various content nodes that want to provide image
      42                 :  * loading functionality (eg <img>, <object>, etc).
      43                 :  */
      44                 : 
      45                 : #ifndef nsImageLoadingContent_h__
      46                 : #define nsImageLoadingContent_h__
      47                 : 
      48                 : #include "nsIImageLoadingContent.h"
      49                 : #include "nsINode.h"
      50                 : #include "imgIRequest.h"
      51                 : #include "prtypes.h"
      52                 : #include "nsCOMPtr.h"
      53                 : #include "nsContentUtils.h" // NS_CONTENT_DELETE_LIST_MEMBER
      54                 : #include "nsString.h"
      55                 : #include "nsEventStates.h"
      56                 : #include "nsGenericHTMLElement.h"
      57                 : #include "mozilla/CORSMode.h"
      58                 : 
      59                 : class nsIURI;
      60                 : class nsIDocument;
      61                 : class imgILoader;
      62                 : class nsIIOService;
      63                 : 
      64                 : class nsImageLoadingContent : public nsIImageLoadingContent
      65                 : {
      66                 :   /* METHODS */
      67                 : public:
      68                 :   nsImageLoadingContent();
      69                 :   virtual ~nsImageLoadingContent();
      70                 : 
      71                 :   NS_DECL_IMGICONTAINEROBSERVER
      72                 :   NS_DECL_IMGIDECODEROBSERVER
      73                 :   NS_DECL_NSIIMAGELOADINGCONTENT
      74                 : 
      75                 : protected:
      76                 :   /**
      77                 :    * LoadImage is called by subclasses when the appropriate
      78                 :    * attributes (eg 'src' for <img> tags) change.  The string passed
      79                 :    * in is the new uri string; this consolidates the code for getting
      80                 :    * the charset, constructing URI objects, and any other incidentals
      81                 :    * into this superclass.   
      82                 :    *
      83                 :    * @param aNewURI the URI spec to be loaded (may be a relative URI)
      84                 :    * @param aForce If true, make sure to load the URI.  If false, only
      85                 :    *        load if the URI is different from the currently loaded URI.
      86                 :    * @param aNotify If true, nsIDocumentObserver state change notifications
      87                 :    *                will be sent as needed.
      88                 :    */
      89                 :   nsresult LoadImage(const nsAString& aNewURI, bool aForce,
      90                 :                      bool aNotify);
      91                 : 
      92                 :   /**
      93                 :    * ImageState is called by subclasses that are computing their content state.
      94                 :    * The return value will have the NS_EVENT_STATE_BROKEN,
      95                 :    * NS_EVENT_STATE_USERDISABLED, and NS_EVENT_STATE_SUPPRESSED bits set as
      96                 :    * needed.  Note that this state assumes that this node is "trying" to be an
      97                 :    * image (so for example complete lack of attempt to load an image will lead
      98                 :    * to NS_EVENT_STATE_BROKEN being set).  Subclasses that are not "trying" to
      99                 :    * be an image (eg an HTML <input> of type other than "image") should just
     100                 :    * not call this method when computing their intrinsic state.
     101                 :    */
     102                 :   nsEventStates ImageState() const;
     103                 : 
     104                 :   /**
     105                 :    * LoadImage is called by subclasses when the appropriate
     106                 :    * attributes (eg 'src' for <img> tags) change. If callers have an
     107                 :    * URI object already available, they should use this method.
     108                 :    *
     109                 :    * @param aNewURI the URI to be loaded
     110                 :    * @param aForce If true, make sure to load the URI.  If false, only
     111                 :    *        load if the URI is different from the currently loaded URI.
     112                 :    * @param aNotify If true, nsIDocumentObserver state change notifications
     113                 :    *                will be sent as needed.
     114                 :    * @param aDocument Optional parameter giving the document this node is in.
     115                 :    *        This is purely a performance optimization.
     116                 :    * @param aLoadFlags Optional parameter specifying load flags to use for
     117                 :    *        the image load
     118                 :    */
     119                 :   nsresult LoadImage(nsIURI* aNewURI, bool aForce, bool aNotify,
     120                 :                      nsIDocument* aDocument = nsnull,
     121                 :                      nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL);
     122                 : 
     123                 :   /**
     124                 :    * helper to get the document for this content (from the nodeinfo
     125                 :    * and such).  Not named GetDocument to prevent ambiguous method
     126                 :    * names in subclasses
     127                 :    *
     128                 :    * @return the document we belong to
     129                 :    */
     130                 :   nsIDocument* GetOurDocument();
     131                 : 
     132                 :   /**
     133                 :    * Helper function to get the frame associated with this content. Not named
     134                 :    * GetPrimaryFrame to prevent ambiguous method names in subclasses.
     135                 :    *
     136                 :    * @return The frame which we belong to, or nsnull if it doesn't exist.
     137                 :    */
     138                 :   nsIFrame* GetOurPrimaryFrame();
     139                 : 
     140                 :   /**
     141                 :    * Helper function to get the PresContext associated with this content's
     142                 :    * frame. Not named GetPresContext to prevent ambiguous method names in
     143                 :    * subclasses.
     144                 :    *
     145                 :    * @return The nsPresContext associated with our frame, or nsnull if either
     146                 :    *         the frame doesn't exist, or the frame's prescontext doesn't exist.
     147                 :    */
     148                 :   nsPresContext* GetFramePresContext();
     149                 : 
     150                 :   /**
     151                 :    * CancelImageRequests is called by subclasses when they want to
     152                 :    * cancel all image requests (for example when the subclass is
     153                 :    * somehow not an image anymore).
     154                 :    */
     155                 :   void CancelImageRequests(bool aNotify);
     156                 : 
     157                 :   /**
     158                 :    * UseAsPrimaryRequest is called by subclasses when they have an existing
     159                 :    * imgIRequest that they want this nsImageLoadingContent to use.  This may
     160                 :    * effectively be called instead of LoadImage or LoadImageWithChannel.
     161                 :    * If aNotify is true, this method will notify on state changes.
     162                 :    */
     163                 :   nsresult UseAsPrimaryRequest(imgIRequest* aRequest, bool aNotify);
     164                 : 
     165                 :   /**
     166                 :    * Derived classes of nsImageLoadingContent MUST call
     167                 :    * DestroyImageLoadingContent from their destructor, or earlier.  It
     168                 :    * does things that cannot be done in ~nsImageLoadingContent because
     169                 :    * they rely on being able to QueryInterface to other derived classes,
     170                 :    * which cannot happen once the derived class destructor has started
     171                 :    * calling the base class destructors.
     172                 :    */
     173                 :   void DestroyImageLoadingContent();
     174                 : 
     175               0 :   void ClearBrokenState() { mBroken = false; }
     176                 : 
     177               0 :   bool LoadingEnabled() { return mLoadingEnabled; }
     178                 : 
     179                 :   // Sets blocking state only if the desired state is different from the
     180                 :   // current one. See the comment for mBlockingOnload for more information.
     181                 :   void SetBlockingOnload(bool aBlocking);
     182                 : 
     183                 :   /**
     184                 :    * Returns the CORS mode that will be used for all future image loads. The
     185                 :    * default implementation returns CORS_NONE unconditionally.
     186                 :    */
     187                 :   virtual mozilla::CORSMode GetCORSMode();
     188                 : 
     189                 : private:
     190                 :   /**
     191                 :    * Struct used to manage the image observers.
     192                 :    */
     193                 :   struct ImageObserver {
     194               1 :     ImageObserver(imgIDecoderObserver* aObserver) :
     195                 :       mObserver(aObserver),
     196               1 :       mNext(nsnull)
     197                 :     {
     198               1 :       MOZ_COUNT_CTOR(ImageObserver);
     199               1 :     }
     200               1 :     ~ImageObserver()
     201               1 :     {
     202               1 :       MOZ_COUNT_DTOR(ImageObserver);
     203               1 :       NS_CONTENT_DELETE_LIST_MEMBER(ImageObserver, this, mNext);
     204               1 :     }
     205                 : 
     206                 :     nsCOMPtr<imgIDecoderObserver> mObserver;
     207                 :     ImageObserver* mNext;
     208                 :   };
     209                 : 
     210                 :   /**
     211                 :    * Struct to report state changes
     212                 :    */
     213                 :   struct AutoStateChanger {
     214               0 :     AutoStateChanger(nsImageLoadingContent* aImageContent,
     215                 :                      bool aNotify) :
     216                 :       mImageContent(aImageContent),
     217               0 :       mNotify(aNotify)
     218                 :     {
     219               0 :       mImageContent->mStateChangerDepth++;
     220               0 :     }
     221               0 :     ~AutoStateChanger()
     222                 :     {
     223               0 :       mImageContent->mStateChangerDepth--;
     224               0 :       mImageContent->UpdateImageState(mNotify);
     225               0 :     }
     226                 : 
     227                 :     nsImageLoadingContent* mImageContent;
     228                 :     bool mNotify;
     229                 :   };
     230                 : 
     231                 :   friend struct AutoStateChanger;
     232                 : 
     233                 :   /**
     234                 :    * UpdateImageState recomputes the current state of this image loading
     235                 :    * content and updates what ImageState() returns accordingly.  It will also
     236                 :    * fire a ContentStatesChanged() notification as needed if aNotify is true.
     237                 :    */
     238                 :   void UpdateImageState(bool aNotify);
     239                 : 
     240                 :   /**
     241                 :    * CancelImageRequests can be called when we want to cancel the
     242                 :    * image requests, generally due to our src changing and us wanting
     243                 :    * to start a new load.  The "current" request will be canceled only
     244                 :    * if it has not progressed far enough to know the image size yet
     245                 :    * unless aEvenIfSizeAvailable is true.
     246                 :    *
     247                 :    * @param aReason the reason the requests are being canceled
     248                 :    * @param aEvenIfSizeAvailable cancels the current load even if its size is
     249                 :    *                             available
     250                 :    * @param aNewImageStatus the nsIContentPolicy status of the new image load
     251                 :    */
     252                 :   void CancelImageRequests(nsresult aReason, bool aEvenIfSizeAvailable,
     253                 :                            PRInt16 aNewImageStatus);
     254                 : 
     255                 :   /**
     256                 :    * Method to fire an event once we know what's going on with the image load.
     257                 :    *
     258                 :    * @param aEventType "load" or "error" depending on how things went
     259                 :    */
     260                 :   nsresult FireEvent(const nsAString& aEventType);
     261                 : protected:
     262                 :   /**
     263                 :    * Method to create an nsIURI object from the given string (will
     264                 :    * handle getting the right charset, base, etc).  You MUST pass in a
     265                 :    * non-null document to this function.
     266                 :    *
     267                 :    * @param aSpec the string spec (from an HTML attribute, eg)
     268                 :    * @param aDocument the document we belong to
     269                 :    * @return the URI we want to be loading
     270                 :    */
     271                 :   nsresult StringToURI(const nsAString& aSpec, nsIDocument* aDocument,
     272                 :                        nsIURI** aURI);
     273                 : 
     274                 :   void CreateStaticImageClone(nsImageLoadingContent* aDest) const;
     275                 : 
     276                 :   /**
     277                 :    * Prepare and returns a reference to the "next request". If there's already
     278                 :    * a _usable_ current request (one with SIZE_AVAILABLE), this request is
     279                 :    * "pending" until it becomes usable. Otherwise, this becomes the current
     280                 :    * request.
     281                 :    */
     282                 :    nsCOMPtr<imgIRequest>& PrepareNextRequest();
     283                 : 
     284                 :   /**
     285                 :    * Called when we would normally call PrepareNextRequest(), but the request was
     286                 :    * blocked.
     287                 :    */
     288                 :   void SetBlockedRequest(nsIURI* aURI, PRInt16 aContentDecision);
     289                 : 
     290                 :   /**
     291                 :    * Returns a COMPtr reference to the current/pending image requests, cleaning
     292                 :    * up and canceling anything that was there before. Note that if you just want
     293                 :    * to get rid of one of the requests, you should call
     294                 :    * Clear*Request(NS_BINDING_ABORTED) instead, since it passes a more appropriate
     295                 :    * aReason than Prepare*Request() does (NS_ERROR_IMAGE_SRC_CHANGED).
     296                 :    */
     297                 :   nsCOMPtr<imgIRequest>& PrepareCurrentRequest();
     298                 :   nsCOMPtr<imgIRequest>& PreparePendingRequest();
     299                 : 
     300                 :   /**
     301                 :    * Cancels and nulls-out the "current" and "pending" requests if they exist.
     302                 :    */
     303                 :   void ClearCurrentRequest(nsresult aReason);
     304                 :   void ClearPendingRequest(nsresult aReason);
     305                 : 
     306                 :   /**
     307                 :    * Retrieve a pointer to the 'registered with the refresh driver' flag for
     308                 :    * which a particular image request corresponds.
     309                 :    *
     310                 :    * @returns A pointer to the boolean flag for a given image request, or
     311                 :    *          |nsnull| if the request is not either |mPendingRequest| or
     312                 :    *          |mCurrentRequest|.
     313                 :    */
     314                 :   bool* GetRegisteredFlagForRequest(imgIRequest* aRequest);
     315                 : 
     316                 :   /**
     317                 :    * Static helper method to tell us if we have the size of a request. The
     318                 :    * image may be null.
     319                 :    */
     320                 :   static bool HaveSize(imgIRequest *aImage);
     321                 : 
     322                 :   /**
     323                 :    * Adds/Removes a given imgIRequest from our document's tracker.
     324                 :    *
     325                 :    * No-op if aImage is null.
     326                 :    */
     327                 :   nsresult TrackImage(imgIRequest* aImage);
     328                 :   nsresult UntrackImage(imgIRequest* aImage);
     329                 : 
     330                 :   /* MEMBERS */
     331                 :   nsCOMPtr<imgIRequest> mCurrentRequest;
     332                 :   nsCOMPtr<imgIRequest> mPendingRequest;
     333                 : 
     334                 :   // If the image was blocked or if there was an error loading, it's nice to
     335                 :   // still keep track of what the URI was despite not having an imgIRequest.
     336                 :   // We only maintain this in those situations (in the common case, this is
     337                 :   // always null).
     338                 :   nsCOMPtr<nsIURI>      mCurrentURI;
     339                 : 
     340                 : private:
     341                 :   /**
     342                 :    * Typically we will have only one observer (our frame in the screen
     343                 :    * prescontext), so we want to only make space for one and to
     344                 :    * heap-allocate anything past that (saves memory and malloc churn
     345                 :    * in the common case).  The storage is a linked list, we just
     346                 :    * happen to actually hold the first observer instead of a pointer
     347                 :    * to it.
     348                 :    */
     349                 :   ImageObserver mObserverList;
     350                 : 
     351                 :   /**
     352                 :    * When mIsImageStateForced is true, this holds the ImageState that we'll
     353                 :    * return in ImageState().
     354                 :    */
     355                 :   nsEventStates mForcedImageState;
     356                 : 
     357                 :   PRInt16 mImageBlockingStatus;
     358                 :   bool mLoadingEnabled : 1;
     359                 : 
     360                 :   /**
     361                 :    * When true, we return mForcedImageState from ImageState().
     362                 :    */
     363                 :   bool mIsImageStateForced : 1;
     364                 : 
     365                 :   /**
     366                 :    * The state we had the last time we checked whether we needed to notify the
     367                 :    * document of a state change.  These are maintained by UpdateImageState.
     368                 :    */
     369                 :   bool mLoading : 1;
     370                 :   bool mBroken : 1;
     371                 :   bool mUserDisabled : 1;
     372                 :   bool mSuppressed : 1;
     373                 : 
     374                 :   /**
     375                 :    * Whether we're currently blocking document load.
     376                 :    */
     377                 :   bool mBlockingOnload : 1;
     378                 : 
     379                 : protected:
     380                 :   /**
     381                 :    * A hack to get animations to reset, see bug 594771. On requests
     382                 :    * that originate from setting .src, we mark them for needing their animation
     383                 :    * reset when they are ready. mNewRequestsWillNeedAnimationReset is set to
     384                 :    * true while preparing such requests (as a hack around needing to change an
     385                 :    * interface), and the other two booleans store which of the current
     386                 :    * and pending requests are of the sort that need their animation restarted.
     387                 :    */
     388                 :   bool mNewRequestsWillNeedAnimationReset : 1;
     389                 : 
     390                 : private:
     391                 :   bool mPendingRequestNeedsResetAnimation : 1;
     392                 :   bool mCurrentRequestNeedsResetAnimation : 1;
     393                 : 
     394                 :   /* The number of nested AutoStateChangers currently tracking our state. */
     395                 :   PRUint8 mStateChangerDepth;
     396                 : 
     397                 :   // Flags to indicate whether each of the current and pending requests are
     398                 :   // registered with the refresh driver.
     399                 :   bool mCurrentRequestRegistered;
     400                 :   bool mPendingRequestRegistered;
     401                 : };
     402                 : 
     403                 : #endif // nsImageLoadingContent_h__

Generated by: LCOV version 1.7