Bug 1309082 - Part 1: Extract image tracking from nsDocument into a separate, refcounted object. r=bholley

This is refcounted as we'll need to hold strong references to the ImageTracker
from style structs that load images.

MozReview-Commit-ID: 994gE9tOjAn

--HG--
extra : rebase_source : 2d50059e51b42251c89a92a954cef7b49720ceba
This commit is contained in:
Cameron McCormack 2016-10-13 15:04:15 +08:00
parent 8898c08155
commit 58c32a9088
12 changed files with 275 additions and 196 deletions

161
dom/base/ImageTracker.cpp Normal file
View File

@ -0,0 +1,161 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* table of images used in a document, for batch locking/unlocking and
* animating */
#include "ImageTracker.h"
namespace mozilla {
namespace dom {
ImageTracker::ImageTracker()
: mLockingImages(false)
, mAnimatingImages(true)
{
}
ImageTracker::~ImageTracker()
{
SetImageLockingState(false);
}
nsresult
ImageTracker::AddImage(imgIRequest* aImage)
{
MOZ_ASSERT(aImage);
// See if the image is already in the hashtable. If it is, get the old count.
uint32_t oldCount = 0;
mImageTracker.Get(aImage, &oldCount);
// Put the image in the hashtable, with the proper count.
mImageTracker.Put(aImage, oldCount + 1);
nsresult rv = NS_OK;
// If this is the first insertion and we're locking images, lock this image
// too.
if (oldCount == 0 && mLockingImages) {
rv = aImage->LockImage();
}
// If this is the first insertion and we're animating images, request
// that this image be animated too.
if (oldCount == 0 && mAnimatingImages) {
nsresult rv2 = aImage->IncrementAnimationConsumers();
rv = NS_SUCCEEDED(rv) ? rv2 : rv;
}
return rv;
}
nsresult
ImageTracker::RemoveImage(imgIRequest* aImage, uint32_t aFlags)
{
NS_ENSURE_ARG_POINTER(aImage);
// Get the old count. It should exist and be > 0.
uint32_t count = 0;
DebugOnly<bool> found = mImageTracker.Get(aImage, &count);
MOZ_ASSERT(found, "Removing image that wasn't in the tracker!");
MOZ_ASSERT(count > 0, "Entry in the cache tracker with count 0!");
// We're removing, so decrement the count.
count--;
// If the count is now zero, remove from the tracker.
// Otherwise, set the new value.
if (count != 0) {
mImageTracker.Put(aImage, count);
return NS_OK;
}
mImageTracker.Remove(aImage);
nsresult rv = NS_OK;
// Now that we're no longer tracking this image, unlock it if we'd
// previously locked it.
if (mLockingImages) {
rv = aImage->UnlockImage();
}
// If we're animating images, remove our request to animate this one.
if (mAnimatingImages) {
nsresult rv2 = aImage->DecrementAnimationConsumers();
rv = NS_SUCCEEDED(rv) ? rv2 : rv;
}
if (aFlags & REQUEST_DISCARD) {
// Request that the image be discarded if nobody else holds a lock on it.
// Do this even if !mLockingImages, because even if we didn't just unlock
// this image, it might still be a candidate for discarding.
aImage->RequestDiscard();
}
return rv;
}
nsresult
ImageTracker::SetImageLockingState(bool aLocked)
{
if (XRE_IsContentProcess() &&
!Preferences::GetBool("image.mem.allow_locking_in_content_processes", true)) {
return NS_OK;
}
// If there's no change, there's nothing to do.
if (mLockingImages == aLocked)
return NS_OK;
// Otherwise, iterate over our images and perform the appropriate action.
for (auto iter = mImageTracker.Iter(); !iter.Done(); iter.Next()) {
imgIRequest* image = iter.Key();
if (aLocked) {
image->LockImage();
} else {
image->UnlockImage();
}
}
// Update state.
mLockingImages = aLocked;
return NS_OK;
}
void
ImageTracker::SetImagesNeedAnimating(bool aAnimating)
{
// If there's no change, there's nothing to do.
if (mAnimatingImages == aAnimating)
return;
// Otherwise, iterate over our images and perform the appropriate action.
for (auto iter = mImageTracker.Iter(); !iter.Done(); iter.Next()) {
imgIRequest* image = iter.Key();
if (aAnimating) {
image->IncrementAnimationConsumers();
} else {
image->DecrementAnimationConsumers();
}
}
// Update state.
mAnimatingImages = aAnimating;
}
void
ImageTracker::RequestDiscardAll()
{
for (auto iter = mImageTracker.Iter(); !iter.Done(); iter.Next()) {
iter.Key()->RequestDiscard();
}
}
} // namespace dom
} // namespace mozilla

69
dom/base/ImageTracker.h Normal file
View File

@ -0,0 +1,69 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* table of images used in a document, for batch locking/unlocking and
* animating */
#ifndef mozilla_dom_ImageTracker
#define mozilla_dom_ImageTracker
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
class imgIRequest;
namespace mozilla {
namespace dom {
/*
* Image Tracking
*
* Style and content images register their imgIRequests with their document's
* image tracker, so that we can efficiently tell all descendant images when
* they are and are not visible. When an image is on-screen, we want to call
* LockImage() on it so that it doesn't do things like discarding frame data
* to save memory. The PresShell informs its document's image tracker whether
* its images should be locked or not via SetImageLockingState().
*
* See bug 512260.
*/
class ImageTracker
{
public:
ImageTracker();
ImageTracker(const ImageTracker&) = delete;
ImageTracker& operator=(const ImageTracker&) = delete;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageTracker)
nsresult AddImage(imgIRequest* aImage);
enum { REQUEST_DISCARD = 0x1 };
nsresult RemoveImage(imgIRequest* aImage, uint32_t aFlags = 0);
// Makes the images on this document locked/unlocked. By default, the locking
// state is unlocked/false.
nsresult SetImageLockingState(bool aLocked);
// Makes the images on this document capable of having their animation
// active or suspended. An Image will animate as long as at least one of its
// owning Documents needs it to animate; otherwise it can suspend.
void SetImagesNeedAnimating(bool aAnimating);
void RequestDiscardAll();
private:
~ImageTracker();
nsDataHashtable<nsPtrHashKey<imgIRequest>, uint32_t> mImageTracker;
bool mLockingImages;
bool mAnimatingImages;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ImageTracker

View File

@ -786,8 +786,8 @@ AutoJSContext::AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (IsJSAPIActive()) {
mCx = danger::GetJSContext();
if (dom::IsJSAPIActive()) {
mCx = dom::danger::GetJSContext();
} else {
mJSAPI.Init();
mCx = mJSAPI.cx();

View File

@ -183,6 +183,7 @@ EXPORTS.mozilla.dom += [
'FragmentOrElement.h',
'FromParser.h',
'ImageEncoder.h',
'ImageTracker.h',
'ImportManager.h',
'Link.h',
'Location.h',
@ -244,6 +245,7 @@ UNIFIED_SOURCES += [
'FormData.cpp',
'FragmentOrElement.cpp',
'ImageEncoder.cpp',
'ImageTracker.cpp',
'ImportManager.cpp',
'Link.cpp',
'Location.cpp',

View File

@ -212,6 +212,7 @@
#include "mozilla/dom/Event.h"
#include "mozilla/dom/HTMLBodyElement.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "mozilla/dom/ImageTracker.h"
#include "mozilla/dom/MediaQueryList.h"
#include "mozilla/dom/NodeFilterBinding.h"
#include "mozilla/OwningNonNull.h"
@ -1331,7 +1332,6 @@ nsIDocument::nsIDocument()
nsDocument::nsDocument(const char* aContentType)
: nsIDocument()
, mAnimatingImages(true)
, mViewportType(Unknown)
{
SetContentTypeInternal(nsDependentCString(aContentType));
@ -1531,11 +1531,6 @@ nsDocument::~nsDocument()
mPendingTitleChangeEvent.Revoke();
// We don't want to leave residual locks on images. Make sure we're in an
// unlocked state, and then clear the table.
SetImageLockingState(false);
mImageTracker.Clear();
mPlugins.Clear();
}
@ -3727,9 +3722,7 @@ nsDocument::DeleteShell()
// When our shell goes away, request that all our images be immediately
// discarded, so we don't carry around decoded image data for a document we
// no longer intend to paint.
for (auto iter = mImageTracker.Iter(); !iter.Done(); iter.Next()) {
iter.Key()->RequestDiscard();
}
ImageTracker()->RequestDiscardAll();
// Now that we no longer have a shell, we need to forget about any FontFace
// objects for @font-face rules that came from the style set.
@ -8721,7 +8714,7 @@ nsDocument::OnPageShow(bool aPersisted,
}
if (aPersisted) {
SetImagesNeedAnimating(true);
ImageTracker()->SetImagesNeedAnimating(true);
}
UpdateVisibilityState();
@ -8816,7 +8809,7 @@ nsDocument::OnPageHide(bool aPersisted,
// when the page is refreshing while being dragged out
nsDocShell* docShell = mDocumentContainer.get();
if (aPersisted && !(docShell && docShell->InFrameSwap())) {
SetImagesNeedAnimating(false);
ImageTracker()->SetImagesNeedAnimating(false);
}
ExitPointerLock();
@ -10040,81 +10033,13 @@ nsIDocument::WarnOnceAbout(DocumentWarnings aWarning,
aParamsLength);
}
nsresult
nsDocument::AddImage(imgIRequest* aImage)
mozilla::dom::ImageTracker*
nsIDocument::ImageTracker()
{
NS_ENSURE_ARG_POINTER(aImage);
// See if the image is already in the hashtable. If it is, get the old count.
uint32_t oldCount = 0;
mImageTracker.Get(aImage, &oldCount);
// Put the image in the hashtable, with the proper count.
mImageTracker.Put(aImage, oldCount + 1);
nsresult rv = NS_OK;
// If this is the first insertion and we're locking images, lock this image
// too.
if (oldCount == 0 && mLockingImages) {
rv = aImage->LockImage();
if (!mImageTracker) {
mImageTracker = new mozilla::dom::ImageTracker;
}
// If this is the first insertion and we're animating images, request
// that this image be animated too.
if (oldCount == 0 && mAnimatingImages) {
nsresult rv2 = aImage->IncrementAnimationConsumers();
rv = NS_SUCCEEDED(rv) ? rv2 : rv;
}
return rv;
}
nsresult
nsDocument::RemoveImage(imgIRequest* aImage, uint32_t aFlags)
{
NS_ENSURE_ARG_POINTER(aImage);
// Get the old count. It should exist and be > 0.
uint32_t count = 0;
DebugOnly<bool> found = mImageTracker.Get(aImage, &count);
MOZ_ASSERT(found, "Removing image that wasn't in the tracker!");
MOZ_ASSERT(count > 0, "Entry in the cache tracker with count 0!");
// We're removing, so decrement the count.
count--;
// If the count is now zero, remove from the tracker.
// Otherwise, set the new value.
if (count != 0) {
mImageTracker.Put(aImage, count);
return NS_OK;
}
mImageTracker.Remove(aImage);
nsresult rv = NS_OK;
// Now that we're no longer tracking this image, unlock it if we'd
// previously locked it.
if (mLockingImages) {
rv = aImage->UnlockImage();
}
// If we're animating images, remove our request to animate this one.
if (mAnimatingImages) {
nsresult rv2 = aImage->DecrementAnimationConsumers();
rv = NS_SUCCEEDED(rv) ? rv2 : rv;
}
if (aFlags & REQUEST_DISCARD) {
// Request that the image be discarded if nobody else holds a lock on it.
// Do this even if !mLockingImages, because even if we didn't just unlock
// this image, it might still be a candidate for discarding.
aImage->RequestDiscard();
}
return rv;
return mImageTracker;
}
nsresult
@ -10183,55 +10108,6 @@ nsDocument::NotifyMediaFeatureValuesChanged()
}
}
nsresult
nsDocument::SetImageLockingState(bool aLocked)
{
if (XRE_IsContentProcess() &&
!Preferences::GetBool("image.mem.allow_locking_in_content_processes", true)) {
return NS_OK;
}
// If there's no change, there's nothing to do.
if (mLockingImages == aLocked)
return NS_OK;
// Otherwise, iterate over our images and perform the appropriate action.
for (auto iter = mImageTracker.Iter(); !iter.Done(); iter.Next()) {
imgIRequest* image = iter.Key();
if (aLocked) {
image->LockImage();
} else {
image->UnlockImage();
}
}
// Update state.
mLockingImages = aLocked;
return NS_OK;
}
void
nsDocument::SetImagesNeedAnimating(bool aAnimating)
{
// If there's no change, there's nothing to do.
if (mAnimatingImages == aAnimating)
return;
// Otherwise, iterate over our images and perform the appropriate action.
for (auto iter = mImageTracker.Iter(); !iter.Done(); iter.Next()) {
imgIRequest* image = iter.Key();
if (aAnimating) {
image->IncrementAnimationConsumers();
} else {
image->DecrementAnimationConsumers();
}
}
// Update state.
mAnimatingImages = aAnimating;
}
already_AddRefed<Touch>
nsIDocument::CreateTouch(nsGlobalWindow* aView,
EventTarget* aTarget,

View File

@ -94,6 +94,7 @@ namespace mozilla {
class EventChainPreVisitor;
namespace dom {
class BoxObject;
class ImageTracker;
class UndoManager;
struct LifecycleCallbacks;
class CallbackFunction;
@ -890,8 +891,6 @@ public:
virtual mozilla::PendingAnimationTracker*
GetOrCreatePendingAnimationTracker() override;
void SetImagesNeedAnimating(bool aAnimating) override;
virtual void SuppressEventHandling(SuppressionType aWhat,
uint32_t aIncrease) override;
@ -984,10 +983,6 @@ public:
virtual void MozSetImageElement(const nsAString& aImageElementId,
Element* aElement) override;
virtual nsresult AddImage(imgIRequest* aImage) override;
virtual nsresult RemoveImage(imgIRequest* aImage, uint32_t aFlags) override;
virtual nsresult SetImageLockingState(bool aLocked) override;
// AddPlugin adds a plugin-related element to mPlugins when the element is
// added to the tree.
virtual nsresult AddPlugin(nsIObjectLoadingContent* aPlugin) override;
@ -1417,12 +1412,6 @@ public:
bool mInXBLUpdate:1;
// Whether we're currently holding a lock on all of our images.
bool mLockingImages:1;
// Whether we currently require our images to animate
bool mAnimatingImages:1;
// Whether we're currently under a FlushPendingNotifications call to
// our presshell. This is used to handle flush reentry correctly.
bool mInFlush:1;
@ -1592,9 +1581,6 @@ private:
uint8_t mScrolledToRefAlready : 1;
uint8_t mChangeScrollPosWhenScrollingToRef : 1;
// Tracking for images in the document.
nsDataHashtable< nsPtrHashKey<imgIRequest>, uint32_t> mImageTracker;
// Tracking for plugins in the document.
nsTHashtable< nsPtrHashKey<nsIObjectLoadingContent> > mPlugins;

View File

@ -135,6 +135,7 @@ class EventTarget;
class FontFaceSet;
class FrameRequestCallback;
struct FullscreenRequest;
class ImageTracker;
class ImportManager;
class HTMLBodyElement;
struct LifecycleCallbackArgs;
@ -2071,11 +2072,6 @@ public:
virtual mozilla::PendingAnimationTracker*
GetOrCreatePendingAnimationTracker() = 0;
// Makes the images on this document capable of having their animation
// active or suspended. An Image will animate as long as at least one of its
// owning Documents needs it to animate; otherwise it can suspend.
virtual void SetImagesNeedAnimating(bool aAnimating) = 0;
enum SuppressionType {
eAnimationsOnly = 0x1,
@ -2354,29 +2350,7 @@ public:
// This returns true when the document tree is being teared down.
bool InUnlinkOrDeletion() { return mInUnlinkOrDeletion; }
/*
* Image Tracking
*
* Style and content images register their imgIRequests with their document
* so that the document can efficiently tell all descendant images when they
* are and are not visible. When an image is on-screen, we want to call
* LockImage() on it so that it doesn't do things like discarding frame data
* to save memory. The PresShell informs the document whether its images
* should be locked or not via SetImageLockingState().
*
* See bug 512260.
*/
// Add/Remove images from the document image tracker
virtual nsresult AddImage(imgIRequest* aImage) = 0;
// If the REQUEST_DISCARD flag is passed then if the lock count is zero we
// will request the image be discarded now (instead of waiting).
enum { REQUEST_DISCARD = 0x1 };
virtual nsresult RemoveImage(imgIRequest* aImage, uint32_t aFlags = 0) = 0;
// Makes the images on this document locked/unlocked. By default, the locking
// state is unlocked/false.
virtual nsresult SetImageLockingState(bool aLocked) = 0;
mozilla::dom::ImageTracker* ImageTracker();
virtual nsresult AddPlugin(nsIObjectLoadingContent* aPlugin) = 0;
virtual void RemovePlugin(nsIObjectLoadingContent* aPlugin) = 0;
@ -2927,6 +2901,9 @@ protected:
RefPtr<nsHTMLCSSStyleSheet> mStyleAttrStyleSheet;
RefPtr<mozilla::SVGAttrAnimationRuleProcessor> mSVGAttrAnimationRuleProcessor;
// Tracking for images in the document.
RefPtr<mozilla::dom::ImageTracker> mImageTracker;
// The set of all object, embed, applet, video/audio elements or
// nsIObjectLoadingContent or nsIDocumentActivity for which this is the
// owner document. (They might not be in the document.)

View File

@ -46,6 +46,7 @@
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/EventStates.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ImageTracker.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/Preferences.h"
@ -55,6 +56,7 @@
#endif
using namespace mozilla;
using namespace mozilla::dom;
#ifdef DEBUG_chb
static void PrintReqURL(imgIRequest* req) {
@ -1474,11 +1476,11 @@ nsImageLoadingContent::TrackImage(imgIRequest* aImage)
if (aImage == mCurrentRequest && !(mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
mCurrentRequestFlags |= REQUEST_IS_TRACKED;
doc->AddImage(mCurrentRequest);
doc->ImageTracker()->AddImage(mCurrentRequest);
}
if (aImage == mPendingRequest && !(mPendingRequestFlags & REQUEST_IS_TRACKED)) {
mPendingRequestFlags |= REQUEST_IS_TRACKED;
doc->AddImage(mPendingRequest);
doc->ImageTracker()->AddImage(mPendingRequest);
}
}
@ -1501,10 +1503,11 @@ nsImageLoadingContent::UntrackImage(imgIRequest* aImage,
if (aImage == mCurrentRequest) {
if (doc && (mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
mCurrentRequestFlags &= ~REQUEST_IS_TRACKED;
doc->RemoveImage(mCurrentRequest,
aNonvisibleAction == Some(OnNonvisible::DISCARD_IMAGES)
? nsIDocument::REQUEST_DISCARD
: 0);
doc->ImageTracker()->RemoveImage(
mCurrentRequest,
aNonvisibleAction == Some(OnNonvisible::DISCARD_IMAGES)
? ImageTracker::REQUEST_DISCARD
: 0);
} else if (aNonvisibleAction == Some(OnNonvisible::DISCARD_IMAGES)) {
// If we're not in the document we may still need to be discarded.
aImage->RequestDiscard();
@ -1513,10 +1516,11 @@ nsImageLoadingContent::UntrackImage(imgIRequest* aImage,
if (aImage == mPendingRequest) {
if (doc && (mPendingRequestFlags & REQUEST_IS_TRACKED)) {
mPendingRequestFlags &= ~REQUEST_IS_TRACKED;
doc->RemoveImage(mPendingRequest,
aNonvisibleAction == Some(OnNonvisible::DISCARD_IMAGES)
? nsIDocument::REQUEST_DISCARD
: 0);
doc->ImageTracker()->RemoveImage(
mPendingRequest,
aNonvisibleAction == Some(OnNonvisible::DISCARD_IMAGES)
? ImageTracker::REQUEST_DISCARD
: 0);
} else if (aNonvisibleAction == Some(OnNonvisible::DISCARD_IMAGES)) {
// If we're not in the document we may still need to be discarded.
aImage->RequestDiscard();

View File

@ -31,6 +31,7 @@
#include "nsSMILAnimationController.h"
#include "gfxContext.h"
#include "harfbuzz/hb.h"
#include "mozilla/dom/ImageTracker.h"
#define SVG_CONTENT_TYPE NS_LITERAL_CSTRING("image/svg+xml")
#define UTF8_CHARSET NS_LITERAL_CSTRING("utf-8")
@ -170,7 +171,7 @@ gfxSVGGlyphsDocument::SetupPresentation()
if (controller) {
controller->Resume(nsSMILTimeContainer::PAUSE_IMAGE);
}
mDocument->SetImagesNeedAnimating(true);
mDocument->ImageTracker()->SetImagesNeedAnimating(true);
mViewer = viewer;
mPresShell = presShell;

View File

@ -30,6 +30,7 @@
#include "nsMimeTypes.h"
#include "DOMSVGLength.h"
#include "nsDocument.h"
#include "mozilla/dom/ImageTracker.h"
// undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
#undef GetCurrentTime
@ -154,7 +155,7 @@ SVGDocumentWrapper::StartAnimation()
if (controller) {
controller->Resume(nsSMILTimeContainer::PAUSE_IMAGE);
}
doc->SetImagesNeedAnimating(true);
doc->ImageTracker()->SetImagesNeedAnimating(true);
}
}
@ -173,7 +174,7 @@ SVGDocumentWrapper::StopAnimation()
if (controller) {
controller->Pause(nsSMILTimeContainer::PAUSE_IMAGE);
}
doc->SetImagesNeedAnimating(false);
doc->ImageTracker()->SetImagesNeedAnimating(false);
}
}

View File

@ -195,6 +195,7 @@
#include "mozilla/StyleSetHandleInlines.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"
#include "mozilla/dom/ImageTracker.h"
#ifdef ANDROID
#include "nsIDocShellTreeOwner.h"
@ -10942,7 +10943,7 @@ PresShell::UpdateImageLockingState()
// We're locked if we're both thawed and active.
bool locked = !mFrozen && mIsActive;
nsresult rv = mDocument->SetImageLockingState(locked);
nsresult rv = mDocument->ImageTracker()->SetImageLockingState(locked);
if (locked) {
// Request decodes for visible image frames; we want to start decoding as

View File

@ -33,6 +33,7 @@
#include "CounterStyleManager.h"
#include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for PlaybackDirection
#include "mozilla/dom/ImageTracker.h"
#include "mozilla/Likely.h"
#include "nsIURI.h"
#include "nsIDocument.h"
@ -2011,7 +2012,7 @@ nsStyleImage::TrackImage(nsPresContext* aContext)
// Register the image with the document
nsIDocument* doc = aContext->Document();
if (doc) {
doc->AddImage(mImage);
doc->ImageTracker()->AddImage(mImage);
}
// Mark state
@ -2031,7 +2032,7 @@ nsStyleImage::UntrackImage(nsPresContext* aContext)
// Unregister the image with the document
nsIDocument* doc = aContext->Document();
if (doc) {
doc->RemoveImage(mImage);
doc->ImageTracker()->RemoveImage(mImage);
}
// Mark state
@ -3438,7 +3439,7 @@ nsStyleContentData::TrackImage(nsPresContext* aContext)
// Register the image with the document
nsIDocument* doc = aContext->Document();
if (doc) {
doc->AddImage(mContent.mImage);
doc->ImageTracker()->AddImage(mContent.mImage);
}
// Mark state
@ -3460,7 +3461,7 @@ nsStyleContentData::UntrackImage(nsPresContext* aContext)
// Unregister the image with the document
nsIDocument* doc = aContext->Document();
if (doc) {
doc->RemoveImage(mContent.mImage);
doc->ImageTracker()->RemoveImage(mContent.mImage);
}
// Mark state