Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | // vim: ft=cpp tw=78 sw=2 et ts=2 |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | /* |
michael@0 | 8 | * A base class which implements nsIImageLoadingContent and can be |
michael@0 | 9 | * subclassed by various content nodes that want to provide image |
michael@0 | 10 | * loading functionality (eg <img>, <object>, etc). |
michael@0 | 11 | */ |
michael@0 | 12 | |
michael@0 | 13 | #ifndef nsImageLoadingContent_h__ |
michael@0 | 14 | #define nsImageLoadingContent_h__ |
michael@0 | 15 | |
michael@0 | 16 | #include "imgINotificationObserver.h" |
michael@0 | 17 | #include "imgIOnloadBlocker.h" |
michael@0 | 18 | #include "mozilla/CORSMode.h" |
michael@0 | 19 | #include "mozilla/EventStates.h" |
michael@0 | 20 | #include "nsCOMPtr.h" |
michael@0 | 21 | #include "nsIImageLoadingContent.h" |
michael@0 | 22 | #include "nsIRequest.h" |
michael@0 | 23 | #include "mozilla/ErrorResult.h" |
michael@0 | 24 | #include "nsAutoPtr.h" |
michael@0 | 25 | |
michael@0 | 26 | class nsIURI; |
michael@0 | 27 | class nsIDocument; |
michael@0 | 28 | class imgILoader; |
michael@0 | 29 | class nsIIOService; |
michael@0 | 30 | class nsPresContext; |
michael@0 | 31 | class nsIContent; |
michael@0 | 32 | class imgRequestProxy; |
michael@0 | 33 | |
michael@0 | 34 | #ifdef LoadImage |
michael@0 | 35 | // Undefine LoadImage to prevent naming conflict with Windows. |
michael@0 | 36 | #undef LoadImage |
michael@0 | 37 | #endif |
michael@0 | 38 | |
michael@0 | 39 | class nsImageLoadingContent : public nsIImageLoadingContent, |
michael@0 | 40 | public imgIOnloadBlocker |
michael@0 | 41 | { |
michael@0 | 42 | /* METHODS */ |
michael@0 | 43 | public: |
michael@0 | 44 | nsImageLoadingContent(); |
michael@0 | 45 | virtual ~nsImageLoadingContent(); |
michael@0 | 46 | |
michael@0 | 47 | NS_DECL_IMGINOTIFICATIONOBSERVER |
michael@0 | 48 | NS_DECL_NSIIMAGELOADINGCONTENT |
michael@0 | 49 | NS_DECL_IMGIONLOADBLOCKER |
michael@0 | 50 | |
michael@0 | 51 | // Web IDL binding methods. |
michael@0 | 52 | // Note that the XPCOM SetLoadingEnabled, AddObserver, RemoveObserver, |
michael@0 | 53 | // ForceImageState methods are OK for Web IDL bindings to use as well, |
michael@0 | 54 | // since none of them throw when called via the Web IDL bindings. |
michael@0 | 55 | |
michael@0 | 56 | bool LoadingEnabled() const { return mLoadingEnabled; } |
michael@0 | 57 | int16_t ImageBlockingStatus() const |
michael@0 | 58 | { |
michael@0 | 59 | return mImageBlockingStatus; |
michael@0 | 60 | } |
michael@0 | 61 | already_AddRefed<imgIRequest> |
michael@0 | 62 | GetRequest(int32_t aRequestType, mozilla::ErrorResult& aError); |
michael@0 | 63 | int32_t |
michael@0 | 64 | GetRequestType(imgIRequest* aRequest, mozilla::ErrorResult& aError); |
michael@0 | 65 | already_AddRefed<nsIURI> GetCurrentURI(mozilla::ErrorResult& aError); |
michael@0 | 66 | already_AddRefed<nsIStreamListener> |
michael@0 | 67 | LoadImageWithChannel(nsIChannel* aChannel, mozilla::ErrorResult& aError); |
michael@0 | 68 | void ForceReload(mozilla::ErrorResult& aError); |
michael@0 | 69 | |
michael@0 | 70 | |
michael@0 | 71 | |
michael@0 | 72 | protected: |
michael@0 | 73 | /** |
michael@0 | 74 | * LoadImage is called by subclasses when the appropriate |
michael@0 | 75 | * attributes (eg 'src' for <img> tags) change. The string passed |
michael@0 | 76 | * in is the new uri string; this consolidates the code for getting |
michael@0 | 77 | * the charset, constructing URI objects, and any other incidentals |
michael@0 | 78 | * into this superclass. |
michael@0 | 79 | * |
michael@0 | 80 | * @param aNewURI the URI spec to be loaded (may be a relative URI) |
michael@0 | 81 | * @param aForce If true, make sure to load the URI. If false, only |
michael@0 | 82 | * load if the URI is different from the currently loaded URI. |
michael@0 | 83 | * @param aNotify If true, nsIDocumentObserver state change notifications |
michael@0 | 84 | * will be sent as needed. |
michael@0 | 85 | */ |
michael@0 | 86 | nsresult LoadImage(const nsAString& aNewURI, bool aForce, |
michael@0 | 87 | bool aNotify); |
michael@0 | 88 | |
michael@0 | 89 | /** |
michael@0 | 90 | * ImageState is called by subclasses that are computing their content state. |
michael@0 | 91 | * The return value will have the NS_EVENT_STATE_BROKEN, |
michael@0 | 92 | * NS_EVENT_STATE_USERDISABLED, and NS_EVENT_STATE_SUPPRESSED bits set as |
michael@0 | 93 | * needed. Note that this state assumes that this node is "trying" to be an |
michael@0 | 94 | * image (so for example complete lack of attempt to load an image will lead |
michael@0 | 95 | * to NS_EVENT_STATE_BROKEN being set). Subclasses that are not "trying" to |
michael@0 | 96 | * be an image (eg an HTML <input> of type other than "image") should just |
michael@0 | 97 | * not call this method when computing their intrinsic state. |
michael@0 | 98 | */ |
michael@0 | 99 | mozilla::EventStates ImageState() const; |
michael@0 | 100 | |
michael@0 | 101 | /** |
michael@0 | 102 | * LoadImage is called by subclasses when the appropriate |
michael@0 | 103 | * attributes (eg 'src' for <img> tags) change. If callers have an |
michael@0 | 104 | * URI object already available, they should use this method. |
michael@0 | 105 | * |
michael@0 | 106 | * @param aNewURI the URI to be loaded |
michael@0 | 107 | * @param aForce If true, make sure to load the URI. If false, only |
michael@0 | 108 | * load if the URI is different from the currently loaded URI. |
michael@0 | 109 | * @param aNotify If true, nsIDocumentObserver state change notifications |
michael@0 | 110 | * will be sent as needed. |
michael@0 | 111 | * @param aDocument Optional parameter giving the document this node is in. |
michael@0 | 112 | * This is purely a performance optimization. |
michael@0 | 113 | * @param aLoadFlags Optional parameter specifying load flags to use for |
michael@0 | 114 | * the image load |
michael@0 | 115 | */ |
michael@0 | 116 | nsresult LoadImage(nsIURI* aNewURI, bool aForce, bool aNotify, |
michael@0 | 117 | nsIDocument* aDocument = nullptr, |
michael@0 | 118 | nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL); |
michael@0 | 119 | |
michael@0 | 120 | /** |
michael@0 | 121 | * helpers to get the document for this content (from the nodeinfo |
michael@0 | 122 | * and such). Not named GetOwnerDoc/GetCurrentDoc to prevent ambiguous |
michael@0 | 123 | * method names in subclasses |
michael@0 | 124 | * |
michael@0 | 125 | * @return the document we belong to |
michael@0 | 126 | */ |
michael@0 | 127 | nsIDocument* GetOurOwnerDoc(); |
michael@0 | 128 | nsIDocument* GetOurCurrentDoc(); |
michael@0 | 129 | |
michael@0 | 130 | /** |
michael@0 | 131 | * Helper function to get the frame associated with this content. Not named |
michael@0 | 132 | * GetPrimaryFrame to prevent ambiguous method names in subclasses. |
michael@0 | 133 | * |
michael@0 | 134 | * @return The frame which we belong to, or nullptr if it doesn't exist. |
michael@0 | 135 | */ |
michael@0 | 136 | nsIFrame* GetOurPrimaryFrame(); |
michael@0 | 137 | |
michael@0 | 138 | /** |
michael@0 | 139 | * Helper function to get the PresContext associated with this content's |
michael@0 | 140 | * frame. Not named GetPresContext to prevent ambiguous method names in |
michael@0 | 141 | * subclasses. |
michael@0 | 142 | * |
michael@0 | 143 | * @return The nsPresContext associated with our frame, or nullptr if either |
michael@0 | 144 | * the frame doesn't exist, or the frame's prescontext doesn't exist. |
michael@0 | 145 | */ |
michael@0 | 146 | nsPresContext* GetFramePresContext(); |
michael@0 | 147 | |
michael@0 | 148 | /** |
michael@0 | 149 | * CancelImageRequests is called by subclasses when they want to |
michael@0 | 150 | * cancel all image requests (for example when the subclass is |
michael@0 | 151 | * somehow not an image anymore). |
michael@0 | 152 | */ |
michael@0 | 153 | void CancelImageRequests(bool aNotify); |
michael@0 | 154 | |
michael@0 | 155 | /** |
michael@0 | 156 | * UseAsPrimaryRequest is called by subclasses when they have an existing |
michael@0 | 157 | * imgRequestProxy that they want this nsImageLoadingContent to use. This may |
michael@0 | 158 | * effectively be called instead of LoadImage or LoadImageWithChannel. |
michael@0 | 159 | * If aNotify is true, this method will notify on state changes. |
michael@0 | 160 | */ |
michael@0 | 161 | nsresult UseAsPrimaryRequest(imgRequestProxy* aRequest, bool aNotify); |
michael@0 | 162 | |
michael@0 | 163 | /** |
michael@0 | 164 | * Derived classes of nsImageLoadingContent MUST call |
michael@0 | 165 | * DestroyImageLoadingContent from their destructor, or earlier. It |
michael@0 | 166 | * does things that cannot be done in ~nsImageLoadingContent because |
michael@0 | 167 | * they rely on being able to QueryInterface to other derived classes, |
michael@0 | 168 | * which cannot happen once the derived class destructor has started |
michael@0 | 169 | * calling the base class destructors. |
michael@0 | 170 | */ |
michael@0 | 171 | void DestroyImageLoadingContent(); |
michael@0 | 172 | |
michael@0 | 173 | void ClearBrokenState() { mBroken = false; } |
michael@0 | 174 | |
michael@0 | 175 | // Sets blocking state only if the desired state is different from the |
michael@0 | 176 | // current one. See the comment for mBlockingOnload for more information. |
michael@0 | 177 | void SetBlockingOnload(bool aBlocking); |
michael@0 | 178 | |
michael@0 | 179 | /** |
michael@0 | 180 | * Returns the CORS mode that will be used for all future image loads. The |
michael@0 | 181 | * default implementation returns CORS_NONE unconditionally. |
michael@0 | 182 | */ |
michael@0 | 183 | virtual mozilla::CORSMode GetCORSMode(); |
michael@0 | 184 | |
michael@0 | 185 | // Subclasses are *required* to call BindToTree/UnbindFromTree. |
michael@0 | 186 | void BindToTree(nsIDocument* aDocument, nsIContent* aParent, |
michael@0 | 187 | nsIContent* aBindingParent, bool aCompileEventHandlers); |
michael@0 | 188 | void UnbindFromTree(bool aDeep, bool aNullParent); |
michael@0 | 189 | |
michael@0 | 190 | nsresult OnStopRequest(imgIRequest* aRequest, nsresult aStatus); |
michael@0 | 191 | void OnUnlockedDraw(); |
michael@0 | 192 | nsresult OnImageIsAnimated(imgIRequest *aRequest); |
michael@0 | 193 | |
michael@0 | 194 | private: |
michael@0 | 195 | /** |
michael@0 | 196 | * Struct used to manage the image observers. |
michael@0 | 197 | */ |
michael@0 | 198 | struct ImageObserver { |
michael@0 | 199 | ImageObserver(imgINotificationObserver* aObserver); |
michael@0 | 200 | ~ImageObserver(); |
michael@0 | 201 | |
michael@0 | 202 | nsCOMPtr<imgINotificationObserver> mObserver; |
michael@0 | 203 | ImageObserver* mNext; |
michael@0 | 204 | }; |
michael@0 | 205 | |
michael@0 | 206 | /** |
michael@0 | 207 | * Struct to report state changes |
michael@0 | 208 | */ |
michael@0 | 209 | struct AutoStateChanger { |
michael@0 | 210 | AutoStateChanger(nsImageLoadingContent* aImageContent, |
michael@0 | 211 | bool aNotify) : |
michael@0 | 212 | mImageContent(aImageContent), |
michael@0 | 213 | mNotify(aNotify) |
michael@0 | 214 | { |
michael@0 | 215 | mImageContent->mStateChangerDepth++; |
michael@0 | 216 | } |
michael@0 | 217 | ~AutoStateChanger() |
michael@0 | 218 | { |
michael@0 | 219 | mImageContent->mStateChangerDepth--; |
michael@0 | 220 | mImageContent->UpdateImageState(mNotify); |
michael@0 | 221 | } |
michael@0 | 222 | |
michael@0 | 223 | nsImageLoadingContent* mImageContent; |
michael@0 | 224 | bool mNotify; |
michael@0 | 225 | }; |
michael@0 | 226 | |
michael@0 | 227 | friend struct AutoStateChanger; |
michael@0 | 228 | |
michael@0 | 229 | /** |
michael@0 | 230 | * UpdateImageState recomputes the current state of this image loading |
michael@0 | 231 | * content and updates what ImageState() returns accordingly. It will also |
michael@0 | 232 | * fire a ContentStatesChanged() notification as needed if aNotify is true. |
michael@0 | 233 | */ |
michael@0 | 234 | void UpdateImageState(bool aNotify); |
michael@0 | 235 | |
michael@0 | 236 | /** |
michael@0 | 237 | * Method to fire an event once we know what's going on with the image load. |
michael@0 | 238 | * |
michael@0 | 239 | * @param aEventType "load" or "error" depending on how things went |
michael@0 | 240 | */ |
michael@0 | 241 | nsresult FireEvent(const nsAString& aEventType); |
michael@0 | 242 | |
michael@0 | 243 | protected: |
michael@0 | 244 | /** |
michael@0 | 245 | * Method to create an nsIURI object from the given string (will |
michael@0 | 246 | * handle getting the right charset, base, etc). You MUST pass in a |
michael@0 | 247 | * non-null document to this function. |
michael@0 | 248 | * |
michael@0 | 249 | * @param aSpec the string spec (from an HTML attribute, eg) |
michael@0 | 250 | * @param aDocument the document we belong to |
michael@0 | 251 | * @return the URI we want to be loading |
michael@0 | 252 | */ |
michael@0 | 253 | nsresult StringToURI(const nsAString& aSpec, nsIDocument* aDocument, |
michael@0 | 254 | nsIURI** aURI); |
michael@0 | 255 | |
michael@0 | 256 | void CreateStaticImageClone(nsImageLoadingContent* aDest) const; |
michael@0 | 257 | |
michael@0 | 258 | /** |
michael@0 | 259 | * Prepare and returns a reference to the "next request". If there's already |
michael@0 | 260 | * a _usable_ current request (one with SIZE_AVAILABLE), this request is |
michael@0 | 261 | * "pending" until it becomes usable. Otherwise, this becomes the current |
michael@0 | 262 | * request. |
michael@0 | 263 | */ |
michael@0 | 264 | nsRefPtr<imgRequestProxy>& PrepareNextRequest(); |
michael@0 | 265 | |
michael@0 | 266 | /** |
michael@0 | 267 | * Called when we would normally call PrepareNextRequest(), but the request was |
michael@0 | 268 | * blocked. |
michael@0 | 269 | */ |
michael@0 | 270 | void SetBlockedRequest(nsIURI* aURI, int16_t aContentDecision); |
michael@0 | 271 | |
michael@0 | 272 | /** |
michael@0 | 273 | * Returns a COMPtr reference to the current/pending image requests, cleaning |
michael@0 | 274 | * up and canceling anything that was there before. Note that if you just want |
michael@0 | 275 | * to get rid of one of the requests, you should call |
michael@0 | 276 | * Clear*Request(NS_BINDING_ABORTED) instead, since it passes a more appropriate |
michael@0 | 277 | * aReason than Prepare*Request() does (NS_ERROR_IMAGE_SRC_CHANGED). |
michael@0 | 278 | */ |
michael@0 | 279 | nsRefPtr<imgRequestProxy>& PrepareCurrentRequest(); |
michael@0 | 280 | nsRefPtr<imgRequestProxy>& PreparePendingRequest(); |
michael@0 | 281 | |
michael@0 | 282 | /** |
michael@0 | 283 | * Switch our pending request to be our current request. |
michael@0 | 284 | * mPendingRequest must be non-null! |
michael@0 | 285 | */ |
michael@0 | 286 | void MakePendingRequestCurrent(); |
michael@0 | 287 | |
michael@0 | 288 | /** |
michael@0 | 289 | * Cancels and nulls-out the "current" and "pending" requests if they exist. |
michael@0 | 290 | */ |
michael@0 | 291 | void ClearCurrentRequest(nsresult aReason, uint32_t aFlags); |
michael@0 | 292 | void ClearPendingRequest(nsresult aReason, uint32_t aFlags); |
michael@0 | 293 | |
michael@0 | 294 | /** |
michael@0 | 295 | * Retrieve a pointer to the 'registered with the refresh driver' flag for |
michael@0 | 296 | * which a particular image request corresponds. |
michael@0 | 297 | * |
michael@0 | 298 | * @returns A pointer to the boolean flag for a given image request, or |
michael@0 | 299 | * |nullptr| if the request is not either |mPendingRequest| or |
michael@0 | 300 | * |mCurrentRequest|. |
michael@0 | 301 | */ |
michael@0 | 302 | bool* GetRegisteredFlagForRequest(imgIRequest* aRequest); |
michael@0 | 303 | |
michael@0 | 304 | /** |
michael@0 | 305 | * Reset animation of the current request if |mNewRequestsWillNeedAnimationReset| |
michael@0 | 306 | * was true when the request was prepared. |
michael@0 | 307 | */ |
michael@0 | 308 | void ResetAnimationIfNeeded(); |
michael@0 | 309 | |
michael@0 | 310 | /** |
michael@0 | 311 | * Static helper method to tell us if we have the size of a request. The |
michael@0 | 312 | * image may be null. |
michael@0 | 313 | */ |
michael@0 | 314 | static bool HaveSize(imgIRequest *aImage); |
michael@0 | 315 | |
michael@0 | 316 | /** |
michael@0 | 317 | * Adds/Removes a given imgIRequest from our document's tracker. |
michael@0 | 318 | * |
michael@0 | 319 | * No-op if aImage is null. |
michael@0 | 320 | * |
michael@0 | 321 | * REQUEST_DISCARD passed to UntrackImage means we request the discard of the |
michael@0 | 322 | * decoded data of the image. |
michael@0 | 323 | */ |
michael@0 | 324 | void TrackImage(imgIRequest* aImage); |
michael@0 | 325 | enum { |
michael@0 | 326 | REQUEST_DISCARD = 0x1 |
michael@0 | 327 | }; |
michael@0 | 328 | void UntrackImage(imgIRequest* aImage, uint32_t aFlags = 0); |
michael@0 | 329 | |
michael@0 | 330 | /* MEMBERS */ |
michael@0 | 331 | nsRefPtr<imgRequestProxy> mCurrentRequest; |
michael@0 | 332 | nsRefPtr<imgRequestProxy> mPendingRequest; |
michael@0 | 333 | uint32_t mCurrentRequestFlags; |
michael@0 | 334 | uint32_t mPendingRequestFlags; |
michael@0 | 335 | |
michael@0 | 336 | enum { |
michael@0 | 337 | // Set if the request needs ResetAnimation called on it. |
michael@0 | 338 | REQUEST_NEEDS_ANIMATION_RESET = 0x00000001U, |
michael@0 | 339 | // Set if the request is blocking onload. |
michael@0 | 340 | REQUEST_BLOCKS_ONLOAD = 0x00000002U, |
michael@0 | 341 | // Set if the request is currently tracked with the document. |
michael@0 | 342 | REQUEST_IS_TRACKED = 0x00000004U |
michael@0 | 343 | }; |
michael@0 | 344 | |
michael@0 | 345 | // If the image was blocked or if there was an error loading, it's nice to |
michael@0 | 346 | // still keep track of what the URI was despite not having an imgIRequest. |
michael@0 | 347 | // We only maintain this in those situations (in the common case, this is |
michael@0 | 348 | // always null). |
michael@0 | 349 | nsCOMPtr<nsIURI> mCurrentURI; |
michael@0 | 350 | |
michael@0 | 351 | private: |
michael@0 | 352 | /** |
michael@0 | 353 | * Typically we will have only one observer (our frame in the screen |
michael@0 | 354 | * prescontext), so we want to only make space for one and to |
michael@0 | 355 | * heap-allocate anything past that (saves memory and malloc churn |
michael@0 | 356 | * in the common case). The storage is a linked list, we just |
michael@0 | 357 | * happen to actually hold the first observer instead of a pointer |
michael@0 | 358 | * to it. |
michael@0 | 359 | */ |
michael@0 | 360 | ImageObserver mObserverList; |
michael@0 | 361 | |
michael@0 | 362 | /** |
michael@0 | 363 | * When mIsImageStateForced is true, this holds the ImageState that we'll |
michael@0 | 364 | * return in ImageState(). |
michael@0 | 365 | */ |
michael@0 | 366 | mozilla::EventStates mForcedImageState; |
michael@0 | 367 | |
michael@0 | 368 | int16_t mImageBlockingStatus; |
michael@0 | 369 | bool mLoadingEnabled : 1; |
michael@0 | 370 | |
michael@0 | 371 | /** |
michael@0 | 372 | * When true, we return mForcedImageState from ImageState(). |
michael@0 | 373 | */ |
michael@0 | 374 | bool mIsImageStateForced : 1; |
michael@0 | 375 | |
michael@0 | 376 | /** |
michael@0 | 377 | * The state we had the last time we checked whether we needed to notify the |
michael@0 | 378 | * document of a state change. These are maintained by UpdateImageState. |
michael@0 | 379 | */ |
michael@0 | 380 | bool mLoading : 1; |
michael@0 | 381 | bool mBroken : 1; |
michael@0 | 382 | bool mUserDisabled : 1; |
michael@0 | 383 | bool mSuppressed : 1; |
michael@0 | 384 | bool mFireEventsOnDecode : 1; |
michael@0 | 385 | |
michael@0 | 386 | protected: |
michael@0 | 387 | /** |
michael@0 | 388 | * A hack to get animations to reset, see bug 594771. On requests |
michael@0 | 389 | * that originate from setting .src, we mark them for needing their animation |
michael@0 | 390 | * reset when they are ready. mNewRequestsWillNeedAnimationReset is set to |
michael@0 | 391 | * true while preparing such requests (as a hack around needing to change an |
michael@0 | 392 | * interface), and the other two booleans store which of the current |
michael@0 | 393 | * and pending requests are of the sort that need their animation restarted. |
michael@0 | 394 | */ |
michael@0 | 395 | bool mNewRequestsWillNeedAnimationReset : 1; |
michael@0 | 396 | |
michael@0 | 397 | private: |
michael@0 | 398 | /* The number of nested AutoStateChangers currently tracking our state. */ |
michael@0 | 399 | uint8_t mStateChangerDepth; |
michael@0 | 400 | |
michael@0 | 401 | // Flags to indicate whether each of the current and pending requests are |
michael@0 | 402 | // registered with the refresh driver. |
michael@0 | 403 | bool mCurrentRequestRegistered; |
michael@0 | 404 | bool mPendingRequestRegistered; |
michael@0 | 405 | |
michael@0 | 406 | // True when FrameCreate has been called but FrameDestroy has not. |
michael@0 | 407 | bool mFrameCreateCalled; |
michael@0 | 408 | |
michael@0 | 409 | uint32_t mVisibleCount; |
michael@0 | 410 | }; |
michael@0 | 411 | |
michael@0 | 412 | #endif // nsImageLoadingContent_h__ |