зеркало из https://github.com/mozilla/gecko-dev.git
Tests for bug 359608 - Animated GIFs are animated even when user navigates to another page.r=joe,a=blocker
This commit is contained in:
Родитель
f1741c27cf
Коммит
4549ab9547
|
@ -50,6 +50,7 @@ EXPORTS = ImageErrors.h ImageLogging.h
|
|||
XPIDLSRCS = \
|
||||
imgICache.idl \
|
||||
imgIContainer.idl \
|
||||
imgIContainerDebug.idl \
|
||||
imgIContainerObserver.idl \
|
||||
imgIDecoderObserver.idl \
|
||||
imgIEncoder.idl \
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/** -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* ***** 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
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alon Zakai <azakai@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either 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 ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* This interface is used in debug builds (and only there) in
|
||||
* order to let automatic tests running JavaScript access
|
||||
* internal state of imgContainers. This lets us test
|
||||
* things like animation.
|
||||
*/
|
||||
[scriptable, uuid(52cbb839-6e63-4a70-b21a-1db4ca706c49)]
|
||||
interface imgIContainerDebug : nsISupports
|
||||
{
|
||||
/**
|
||||
* The # of frames this imgContainer has been notified about.
|
||||
* That is equal to the # of times the animation timer has
|
||||
* fired, and is usually equal to the # of frames actually
|
||||
* drawn (but actual drawing might be disabled).
|
||||
*/
|
||||
readonly attribute PRUint32 framesNotified;
|
||||
};
|
|
@ -166,8 +166,13 @@ DiscardingEnabled()
|
|||
namespace mozilla {
|
||||
namespace imagelib {
|
||||
|
||||
#ifndef DEBUG
|
||||
NS_IMPL_ISUPPORTS4(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
|
||||
nsISupportsWeakReference)
|
||||
#else
|
||||
NS_IMPL_ISUPPORTS5(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
|
||||
imgIContainerDebug, nsISupportsWeakReference)
|
||||
#endif
|
||||
|
||||
//******************************************************************************
|
||||
RasterImage::RasterImage(imgStatusTracker* aStatusTracker) :
|
||||
|
@ -181,6 +186,9 @@ RasterImage::RasterImage(imgStatusTracker* aStatusTracker) :
|
|||
mDecoder(nsnull),
|
||||
mWorker(nsnull),
|
||||
mBytesDecoded(0),
|
||||
#ifdef DEBUG
|
||||
mFramesNotified(0),
|
||||
#endif
|
||||
mHasSize(PR_FALSE),
|
||||
mDecodeOnDraw(PR_FALSE),
|
||||
mMultipart(PR_FALSE),
|
||||
|
@ -1406,6 +1414,10 @@ RasterImage::SetSourceSizeHint(PRUint32 sizeHint)
|
|||
NS_IMETHODIMP
|
||||
RasterImage::Notify(nsITimer *timer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mFramesNotified++;
|
||||
#endif
|
||||
|
||||
// This should never happen since the timer is only set up in StartAnimation()
|
||||
// after mAnim is checked to exist.
|
||||
NS_ABORT_IF_FALSE(mAnim, "Need anim for Notify()");
|
||||
|
@ -2732,5 +2744,19 @@ RasterImage::ShouldAnimate()
|
|||
mAnimationMode != kDontAnimMode && !mAnimationFinished;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
/* readonly attribute PRUint32 framesNotified; */
|
||||
#ifdef DEBUG
|
||||
NS_IMETHODIMP
|
||||
RasterImage::GetFramesNotified(PRUint32 *aFramesNotified)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFramesNotified);
|
||||
|
||||
*aFramesNotified = mFramesNotified;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace imagelib
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -64,6 +64,9 @@
|
|||
#include "imgFrame.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "DiscardTracker.h"
|
||||
#ifdef DEBUG
|
||||
#include "imgIContainerDebug.h"
|
||||
#endif
|
||||
|
||||
class imgIDecoder;
|
||||
class nsIInputStream;
|
||||
|
@ -145,16 +148,22 @@ namespace imagelib {
|
|||
class imgDecodeWorker;
|
||||
class Decoder;
|
||||
|
||||
class RasterImage : public mozilla::imagelib::Image,
|
||||
public nsITimerCallback,
|
||||
public nsIProperties,
|
||||
public nsSupportsWeakReference
|
||||
class RasterImage : public mozilla::imagelib::Image
|
||||
, public nsITimerCallback
|
||||
, public nsIProperties
|
||||
, public nsSupportsWeakReference
|
||||
#ifdef DEBUG
|
||||
, public imgIContainerDebug
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_IMGICONTAINER
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
NS_DECL_NSIPROPERTIES
|
||||
#ifdef DEBUG
|
||||
NS_DECL_IMGICONTAINERDEBUG
|
||||
#endif
|
||||
|
||||
RasterImage(imgStatusTracker* aStatusTracker = nsnull);
|
||||
virtual ~RasterImage();
|
||||
|
@ -473,6 +482,10 @@ private: // data
|
|||
nsRefPtr<imgDecodeWorker> mWorker;
|
||||
PRUint32 mBytesDecoded;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRUint32 mFramesNotified;
|
||||
#endif
|
||||
|
||||
// Boolean flags (clustered together to conserve space):
|
||||
PRPackedBool mHasSize:1; // Has SetSize() been called?
|
||||
PRPackedBool mDecodeOnDraw:1; // Decoding on draw?
|
||||
|
|
|
@ -48,6 +48,8 @@ MODULE = test_libpr0n
|
|||
|
||||
XPCSHELL_TESTS = unit
|
||||
|
||||
DIRS += mochitest
|
||||
DIRS += mochitest \
|
||||
browser \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
# ***** 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
|
||||
# the Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2008
|
||||
# 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 *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = modules/libpr0n/test/browser
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_FILES = head.js \
|
||||
browser_image.js \
|
||||
image.html \
|
||||
imageX2.html \
|
||||
animated.gif \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 70 KiB |
|
@ -0,0 +1,175 @@
|
|||
waitForExplicitFinish();
|
||||
|
||||
// A hold on the current timer, so it doens't get GCed out from
|
||||
// under us
|
||||
var gTimer;
|
||||
|
||||
// Browsing to a new URL - pushing us into the bfcache - should cause
|
||||
// animations to stop, and resume when we return
|
||||
function testBFCache() {
|
||||
function theTest() {
|
||||
var abort = false;
|
||||
var chances, gImage, gFrames;
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
switchToTabHavingURI(TESTROOT + "image.html", true, function(aBrowser) {
|
||||
var window = aBrowser.contentWindow;
|
||||
// If false, we are in an optimized build, and we abort this and
|
||||
// all further tests
|
||||
if (!actOnMozImage(window.document, "img1", function(image) {
|
||||
gImage = image;
|
||||
gFrames = gImage.framesNotified;
|
||||
})) {
|
||||
gBrowser.removeCurrentTab();
|
||||
abort = true;
|
||||
}
|
||||
goer.next();
|
||||
});
|
||||
yield;
|
||||
if (abort) {
|
||||
finish();
|
||||
yield; // optimized build
|
||||
}
|
||||
|
||||
// Let animation run for a bit
|
||||
chances = 120;
|
||||
do {
|
||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
gTimer.initWithCallback(function() {
|
||||
if (gImage.framesNotified >= 10) {
|
||||
goer.send(true);
|
||||
} else {
|
||||
chances--;
|
||||
goer.send(chances == 0); // maybe if we wait a bit, it will happen
|
||||
}
|
||||
}, 500, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
} while (!(yield));
|
||||
is(chances > 0, true, "Must have animated a few frames so far");
|
||||
|
||||
// Browse elsewhere; push our animating page into the bfcache
|
||||
gBrowser.loadURI("about:blank");
|
||||
|
||||
// Wait a bit for page to fully load, then wait a while and
|
||||
// see that no animation occurs.
|
||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
gTimer.initWithCallback(function() {
|
||||
gFrames = gImage.framesNotified;
|
||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
gTimer.initWithCallback(function() {
|
||||
// Might have a few stray frames, until other page totally loads
|
||||
is(gImage.framesNotified == gFrames, true, "Must have not animated in bfcache!");
|
||||
goer.next();
|
||||
}, 4000, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}, 0, Ci.nsITimer.TYPE_ONE_SHOT); // delay of 0 - wait for next event loop
|
||||
yield;
|
||||
|
||||
// Go back
|
||||
gBrowser.goBack();
|
||||
|
||||
chances = 120;
|
||||
do {
|
||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
gTimer.initWithCallback(function() {
|
||||
if (gImage.framesNotified - gFrames >= 10) {
|
||||
goer.send(true);
|
||||
} else {
|
||||
chances--;
|
||||
goer.send(chances == 0); // maybe if we wait a bit, it will happen
|
||||
}
|
||||
}, 500, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
} while (!(yield));
|
||||
is(chances > 0, true, "Must have animated once out of bfcache!");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
nextTest();
|
||||
}
|
||||
|
||||
var goer = theTest();
|
||||
goer.next();
|
||||
}
|
||||
|
||||
// Check that imgContainers are shared on the same page and
|
||||
// between tabs
|
||||
function testSharedContainers() {
|
||||
function theTest() {
|
||||
var gImages = [];
|
||||
var gFrames;
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
switchToTabHavingURI(TESTROOT + "image.html", true, function(aBrowser) {
|
||||
actOnMozImage(aBrowser.contentWindow.window.document, "img1", function(image) {
|
||||
gImages[0] = image;
|
||||
gFrames = image.framesNotified; // May in theory have frames from last test
|
||||
// in this counter - so subtract them out
|
||||
});
|
||||
goer.next();
|
||||
});
|
||||
yield;
|
||||
|
||||
// Load next tab somewhat later
|
||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
gTimer.initWithCallback(function() {
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
goer.next();
|
||||
}, 1500, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
yield;
|
||||
|
||||
switchToTabHavingURI(TESTROOT + "imageX2.html", true, function(aBrowser) {
|
||||
[1,2].forEach(function(i) {
|
||||
actOnMozImage(aBrowser.contentWindow.window.document, "img"+i, function(image) {
|
||||
gImages[i] = image;
|
||||
});
|
||||
});
|
||||
goer.next();
|
||||
});
|
||||
yield;
|
||||
|
||||
chances = 120;
|
||||
do {
|
||||
gTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
gTimer.initWithCallback(function() {
|
||||
if (gImages[0].framesNotified - gFrames >= 10) {
|
||||
goer.send(true);
|
||||
} else {
|
||||
chances--;
|
||||
goer.send(chances == 0); // maybe if we wait a bit, it will happen
|
||||
}
|
||||
}, 500, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
} while (!(yield));
|
||||
is(chances > 0, true, "Must have been animating while showing several images");
|
||||
|
||||
// Check they all have the same frame counts
|
||||
var theFrames = null;
|
||||
[0,1,2].forEach(function(i) {
|
||||
var frames = gImages[i].framesNotified;
|
||||
if (theFrames == null) {
|
||||
theFrames = frames;
|
||||
} else {
|
||||
is(theFrames, frames, "Sharing the same imgContainer means *exactly* the same frame counts!");
|
||||
}
|
||||
});
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
nextTest();
|
||||
}
|
||||
|
||||
var goer = theTest();
|
||||
goer.next();
|
||||
}
|
||||
|
||||
var tests = [testBFCache, testSharedContainers];
|
||||
|
||||
function nextTest() {
|
||||
if (tests.length == 0) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
tests.shift()();
|
||||
}
|
||||
|
||||
function test() {
|
||||
nextTest();
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const RELATIVE_DIR = "modules/libpr0n/test/browser/";
|
||||
const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
|
||||
const TESTROOT2 = "http://example.org/browser/" + RELATIVE_DIR;
|
||||
const CHROMEROOT = "chrome://mochikit/content/browser/" + RELATIVE_DIR;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
function getImageLoading(doc, id) {
|
||||
var htmlImg = doc.getElementById(id);
|
||||
return htmlImg.QueryInterface(Ci.nsIImageLoadingContent);
|
||||
}
|
||||
|
||||
// Tries to get the Moz debug image, imgIContainerDebug. Only works
|
||||
// in a debug build. If we succeed, we call func().
|
||||
function actOnMozImage(doc, id, func) {
|
||||
var imgContainer = getImageLoading(doc, id).getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST).image;
|
||||
var mozImage;
|
||||
try {
|
||||
mozImage = imgContainer.QueryInterface(Ci.imgIContainerDebug);
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
func(mozImage);
|
||||
return true;
|
||||
}
|
||||
|
||||
function awaitImageContainer(doc, id, func) {
|
||||
getImageLoading(doc, id).addObserver({
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.imgIDecoderObserver]),
|
||||
onStartContainer: function(aRequest, aContainer) {
|
||||
getImageLoading(doc, id).removeObserver(this);
|
||||
func(aContainer);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Imagelib2 animation tests</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Page with image</p>
|
||||
<img src="animated.gif" id="img1">
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Imagelib2 animation tests</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Page with images</p>
|
||||
<img src="animated.gif" id="img1">
|
||||
<br>
|
||||
<img src="animated.gif" id="img2">
|
||||
</body>
|
||||
</html>
|
||||
|
Загрузка…
Ссылка в новой задаче