Backout bug 552605 and bug 619048 due to increase in random failures in reftests on a CLOSED TREE

This commit is contained in:
Marco Bonardo 2011-07-01 18:08:24 +02:00
parent dafb1c73cf
commit 8ee34defda
24 changed files with 227 additions and 714 deletions

View File

@ -1,7 +0,0 @@
<html>
<head>
<title>Bug 89419</title>
</head>
<body>
<img src="http://mochi.test:8888/tests/docshell/test/chrome/bug89419.sjs">
</body>

View File

@ -44,9 +44,6 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_HTTP_FILES = \
bug89419.sjs \
blue.png \
red.png \
92598_nostore.html \
92598_nostore.html^headers^ \
112564_nocache.html \
@ -61,9 +58,6 @@ _HTTP_FILES = \
$(NULL)
_TEST_FILES = \
test_bug89419.xul \
bug89419_window.xul \
89419.html \
test_bug92598.xul \
bug92598_window.xul \
92598_nostore.html \

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1,13 +0,0 @@
function handleRequest(request, response)
{
var redirectstate = "/docshell/test/chrome/bug89419.sjs";
response.setStatusLine("1.1", 302, "Found");
if (getState(redirectstate) == "") {
response.setHeader("Location", "red.png", false);
setState(redirectstate, "red");
} else {
response.setHeader("Location", "blue.png", false);
setState(redirectstate, "");
}
response.setHeader("Cache-Control", "no-cache", false);
}

View File

@ -1,76 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window id="89419Test"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
width="600"
height="600"
onload="setTimeout(nextTest,0);"
title="bug 89419 test">
<script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
<script type="application/javascript" src="docshell_helpers.js" />
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
<script type="application/javascript"><![CDATA[
// Define the generator-iterator for the tests.
var tests = testIterator();
////
// Execute the next test in the generator function.
//
function nextTest() {
tests.next();
}
////
// Generator function for test steps for bug 89419:
// A visited link should have the :visited style applied
// to it when displayed on a page which was fetched from
// the bfcache.
//
function testIterator()
{
// Load a test page containing an image referring to the sjs that returns
// a different redirect every time it's loaded.
doPageNavigation({
uri: getHttpUrl("89419.html"),
onNavComplete: nextTest,
preventBFCache: true
});
yield;
var first = snapshotWindow(TestWindow.getWindow());
doPageNavigation({
uri: "about:blank",
onNavComplete: nextTest
});
yield;
var second = snapshotWindow(TestWindow.getWindow());
function snapshotsEqual(snap1, snap2) {
return compareSnapshots(snap1, snap2, true)[0];
}
ok(!snapshotsEqual(first, second), "about:blank should not be the same as the image web page");
doPageNavigation({
back: true,
onNavComplete: nextTest
});
yield;
var third = snapshotWindow(TestWindow.getWindow());
ok(!snapshotsEqual(third, second), "going back should not be the same as about:blank");
ok(snapshotsEqual(first, third), "going back should be the same as the initial load");
// Tell the framework the test is finished. Include the final 'yield'
// statement to prevent a StopIteration exception from being thrown.
finish();
yield;
}
]]></script>
<browser type="content-primary" flex="1" id="content" src="about:blank"/>
</window>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 B

View File

@ -1,43 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet
href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=89419.xul
-->
<window title="Mozilla Bug 89419"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<title>Test for Bug 89419</title>
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=89419">
Mozilla Bug 89419</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
/** Test for Bug 89419 **/
SimpleTest.waitForExplicitFinish();
window.open("bug89419_window.xul", "bug89419",
"chrome,width=600,height=600");
]]>
</script>
</window>

View File

@ -69,6 +69,9 @@ static PRUint32 gTotalDDBSize = 0;
// Returns true if an image of aWidth x aHeight is allowed and legal.
static PRBool AllowedImageSize(PRInt32 aWidth, PRInt32 aHeight)
{
NS_ASSERTION(aWidth > 0, "invalid image width");
NS_ASSERTION(aHeight > 0, "invalid image height");
// reject over-wide or over-tall images
const PRInt32 k64KLimit = 0x0000FFFF;
if (NS_UNLIKELY(aWidth > k64KLimit || aHeight > k64KLimit )) {
@ -76,8 +79,9 @@ static PRBool AllowedImageSize(PRInt32 aWidth, PRInt32 aHeight)
return PR_FALSE;
}
// protect against invalid sizes
if (NS_UNLIKELY(aHeight <= 0 || aWidth <= 0)) {
// protect against division by zero - this really shouldn't happen
// if our consumers were well behaved, but they aren't (bug 368427)
if (NS_UNLIKELY(aHeight == 0)) {
return PR_FALSE;
}

View File

@ -276,6 +276,35 @@ public:
NS_IMPL_ISUPPORTS1(imgMemoryReporter, nsIMemoryReporter)
/**
* A class that implements nsIProgressEventSink and forwards all calls to it to
* the original notification callbacks of the channel. Also implements
* nsIInterfaceRequestor and gives out itself for nsIProgressEventSink calls,
* and forwards everything else to the channel's notification callbacks.
*/
class nsProgressNotificationProxy : public nsIProgressEventSink
, public nsIChannelEventSink
, public nsIInterfaceRequestor
{
public:
nsProgressNotificationProxy(nsIChannel* channel,
imgIRequest* proxy)
: mImageRequest(proxy) {
channel->GetNotificationCallbacks(getter_AddRefs(mOriginalCallbacks));
}
NS_DECL_ISUPPORTS
NS_DECL_NSIPROGRESSEVENTSINK
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
private:
~nsProgressNotificationProxy() {}
nsCOMPtr<nsIInterfaceRequestor> mOriginalCallbacks;
nsCOMPtr<nsIRequest> mImageRequest;
};
NS_IMPL_ISUPPORTS3(nsProgressNotificationProxy,
nsIProgressEventSink,
nsIChannelEventSink,
@ -285,8 +314,7 @@ NS_IMETHODIMP
nsProgressNotificationProxy::OnProgress(nsIRequest* request,
nsISupports* ctxt,
PRUint64 progress,
PRUint64 progressMax)
{
PRUint64 progressMax) {
nsCOMPtr<nsILoadGroup> loadGroup;
request->GetLoadGroup(getter_AddRefs(loadGroup));
@ -304,8 +332,7 @@ NS_IMETHODIMP
nsProgressNotificationProxy::OnStatus(nsIRequest* request,
nsISupports* ctxt,
nsresult status,
const PRUnichar* statusArg)
{
const PRUnichar* statusArg) {
nsCOMPtr<nsILoadGroup> loadGroup;
request->GetLoadGroup(getter_AddRefs(loadGroup));
@ -323,8 +350,7 @@ NS_IMETHODIMP
nsProgressNotificationProxy::AsyncOnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel,
PRUint32 flags,
nsIAsyncVerifyRedirectCallback *cb)
{
nsIAsyncVerifyRedirectCallback *cb) {
// Tell the original original callbacks about it too
nsCOMPtr<nsILoadGroup> loadGroup;
newChannel->GetLoadGroup(getter_AddRefs(loadGroup));
@ -344,8 +370,7 @@ nsProgressNotificationProxy::AsyncOnChannelRedirect(nsIChannel *oldChannel,
NS_IMETHODIMP
nsProgressNotificationProxy::GetInterface(const nsIID& iid,
void** result)
{
void** result) {
if (iid.Equals(NS_GET_IID(nsIProgressEventSink))) {
*result = static_cast<nsIProgressEventSink*>(this);
NS_ADDREF_THIS();
@ -361,13 +386,17 @@ nsProgressNotificationProxy::GetInterface(const nsIID& iid,
return NS_NOINTERFACE;
}
static PRBool NewRequestAndEntry(imgRequest **request, imgCacheEntry **entry)
static PRBool NewRequestAndEntry(nsIURI *uri, imgRequest **request, imgCacheEntry **entry)
{
// If file, force revalidation on expiration
PRBool isFile;
uri->SchemeIs("file", &isFile);
*request = new imgRequest();
if (!*request)
return PR_FALSE;
*entry = new imgCacheEntry(*request);
*entry = new imgCacheEntry(*request, /* mustValidateIfExpired = */ isFile);
if (!*entry) {
delete *request;
return PR_FALSE;
@ -391,9 +420,6 @@ static PRBool ShouldRevalidateEntry(imgCacheEntry *aEntry,
if (aFlags & nsIRequest::VALIDATE_ALWAYS) {
bValidateEntry = PR_TRUE;
}
else if (aEntry->GetMustValidate()) {
bValidateEntry = PR_TRUE;
}
//
// The cache entry has expired... Determine whether the stale cache
// entry can be used without validation...
@ -407,7 +433,7 @@ static PRBool ShouldRevalidateEntry(imgCacheEntry *aEntry,
if (aFlags & (nsIRequest::VALIDATE_NEVER |
nsIRequest::VALIDATE_ONCE_PER_SESSION))
{
bValidateEntry = PR_FALSE;
bValidateEntry = aEntry->GetMustValidateIfExpired();
}
//
// LOAD_FROM_CACHE allows a stale cache entry to be used... Otherwise,
@ -495,15 +521,13 @@ static PRUint32 SecondsFromPRTime(PRTime prTime)
return PRUint32(PRInt64(prTime) / PRInt64(PR_USEC_PER_SEC));
}
imgCacheEntry::imgCacheEntry(imgRequest *request)
imgCacheEntry::imgCacheEntry(imgRequest *request, PRBool mustValidateIfExpired /* = PR_FALSE */)
: mRequest(request),
mDataSize(0),
mTouchedTime(SecondsFromPRTime(PR_Now())),
mExpiryTime(0),
mMustValidate(PR_FALSE),
// We start off as evicted so we don't try to update the cache. PutIntoCache
// will set this to false.
mEvicted(PR_TRUE),
mMustValidateIfExpired(mustValidateIfExpired),
mEvicted(PR_FALSE),
mHasNoProxies(PR_TRUE)
{}
@ -1174,9 +1198,6 @@ PRBool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
return NS_SUCCEEDED(rv);
} else {
// We will rely on Necko to cache this request when it's possible, and to
// tell imgCacheValidator::OnStartRequest whether the request came from its
// cache.
nsCOMPtr<nsIChannel> newChannel;
rv = NewImageChannel(getter_AddRefs(newChannel),
aURI,
@ -1190,6 +1211,16 @@ PRBool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
return PR_FALSE;
}
nsCOMPtr<nsICachingChannel> cacheChan(do_QueryInterface(newChannel));
if (cacheChan) {
// since this channel supports nsICachingChannel, we can ask it
// to only stream us data if the data comes off the net.
PRUint32 loadFlags;
if (NS_SUCCEEDED(newChannel->GetLoadFlags(&loadFlags)))
newChannel->SetLoadFlags(loadFlags | nsICachingChannel::LOAD_ONLY_IF_MODIFIED);
}
nsCOMPtr<imgIRequest> req;
rv = CreateNewProxyForRequest(request, aLoadGroup, aObserver,
aLoadFlags, aExistingRequest, getter_AddRefs(req));
@ -1198,18 +1229,18 @@ PRBool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
}
// Make sure that OnStatus/OnProgress calls have the right request set...
nsRefPtr<nsProgressNotificationProxy> progressproxy =
new nsProgressNotificationProxy(newChannel, req);
if (!progressproxy)
nsCOMPtr<nsIInterfaceRequestor> requestor(
new nsProgressNotificationProxy(newChannel, req));
if (!requestor)
return PR_FALSE;
newChannel->SetNotificationCallbacks(requestor);
nsRefPtr<imgCacheValidator> hvc = new imgCacheValidator(progressproxy, request, aCX);
imgCacheValidator *hvc = new imgCacheValidator(request, aCX);
if (!hvc) {
return PR_FALSE;
}
newChannel->SetNotificationCallbacks(hvc);
NS_ADDREF(hvc);
request->mValidator = hvc;
imgRequestProxy* proxy = static_cast<imgRequestProxy*>
@ -1228,6 +1259,8 @@ PRBool imgLoader::ValidateRequestWithNewChannel(imgRequest *request,
if (NS_SUCCEEDED(rv))
NS_ADDREF(*aProxyRequest = req.get());
NS_RELEASE(hvc);
return NS_SUCCEEDED(rv);
}
}
@ -1600,7 +1633,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
if (!NewRequestAndEntry(getter_AddRefs(request), getter_AddRefs(entry)))
if (!NewRequestAndEntry(aURI, getter_AddRefs(request), getter_AddRefs(entry)))
return NS_ERROR_OUT_OF_MEMORY;
PR_LOG(gImgLog, PR_LOG_DEBUG,
@ -1792,7 +1825,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
requestFlags, nsnull, _retval);
static_cast<imgRequestProxy*>(*_retval)->NotifyListener();
} else {
if (!NewRequestAndEntry(getter_AddRefs(request), getter_AddRefs(entry)))
if (!NewRequestAndEntry(uri, getter_AddRefs(request), getter_AddRefs(entry)))
return NS_ERROR_OUT_OF_MEMORY;
// We use originalURI here to fulfil the imgIRequest contract on GetURI.
@ -1809,7 +1842,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
NS_RELEASE(pl);
// Try to add the new request into the cache.
PutIntoCache(originalURI, entry);
PutIntoCache(uri, entry);
rv = CreateNewProxyForRequest(request, loadGroup, aObserver,
requestFlags, nsnull, _retval);
@ -1998,20 +2031,14 @@ NS_IMETHODIMP ProxyListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *
* http validate class. check a channel for a 304
*/
NS_IMPL_ISUPPORTS5(imgCacheValidator, nsIStreamListener, nsIRequestObserver,
nsIChannelEventSink, nsIInterfaceRequestor,
nsIAsyncVerifyRedirectCallback)
NS_IMPL_ISUPPORTS2(imgCacheValidator, nsIStreamListener, nsIRequestObserver)
imgLoader imgCacheValidator::sImgLoader;
imgCacheValidator::imgCacheValidator(nsProgressNotificationProxy* progress,
imgRequest *request, void *aContext)
: mProgressProxy(progress),
mRequest(request),
mContext(aContext)
{
NewRequestAndEntry(getter_AddRefs(mNewRequest), getter_AddRefs(mNewEntry));
}
imgCacheValidator::imgCacheValidator(imgRequest *request, void *aContext) :
mRequest(request),
mContext(aContext)
{}
imgCacheValidator::~imgCacheValidator()
{
@ -2034,22 +2061,14 @@ void imgCacheValidator::AddProxy(imgRequestProxy *aProxy)
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt)
{
// If this request is coming from cache and has the same URI as our
// imgRequest, the request all our proxies are pointing at is valid, and all
// we have to do is tell them to notify their listeners.
// If this request is coming from cache, the request all our proxies are
// pointing at is valid, and all we have to do is tell them to notify their
// listeners.
nsCOMPtr<nsICachingChannel> cacheChan(do_QueryInterface(aRequest));
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
if (cacheChan && channel) {
PRBool isFromCache = PR_FALSE;
cacheChan->IsFromCache(&isFromCache);
if (cacheChan) {
PRBool isFromCache;
if (NS_SUCCEEDED(cacheChan->IsFromCache(&isFromCache)) && isFromCache) {
nsCOMPtr<nsIURI> channelURI;
PRBool sameURI = PR_FALSE;
channel->GetURI(getter_AddRefs(channelURI));
if (channelURI)
channelURI->Equals(mRequest->mCurrentURI, &sameURI);
if (isFromCache && sameURI) {
PRUint32 count = mProxies.Count();
for (PRInt32 i = count-1; i>=0; i--) {
imgRequestProxy *proxy = static_cast<imgRequestProxy *>(mProxies[i]);
@ -2066,24 +2085,21 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
proxy->SyncNotifyListener();
}
// We don't need to load this any more.
aRequest->Cancel(NS_BINDING_ABORTED);
mRequest->SetLoadId(mContext);
mRequest->mValidator = nsnull;
mRequest = nsnull;
mNewRequest = nsnull;
mNewEntry = nsnull;
return NS_OK;
}
}
// We can't load out of cache. We have to create a whole new request for the
// data that's coming in off the channel.
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
nsRefPtr<imgCacheEntry> entry;
nsCOMPtr<nsIURI> uri;
mRequest->GetURI(getter_AddRefs(uri));
#if defined(PR_LOGGING)
@ -2098,24 +2114,34 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
mRequest->mValidator = nsnull;
mRequest = nsnull;
imgRequest *request;
if (!NewRequestAndEntry(uri, &request, getter_AddRefs(entry)))
return NS_ERROR_OUT_OF_MEMORY;
// We use originalURI here to fulfil the imgIRequest contract on GetURI.
nsCOMPtr<nsIURI> originalURI;
channel->GetOriginalURI(getter_AddRefs(originalURI));
mNewRequest->Init(originalURI, uri, channel, channel, mNewEntry, NS_GetCurrentThread(), mContext);
request->Init(originalURI, uri, channel, channel, entry, NS_GetCurrentThread(), mContext);
ProxyListener *pl = new ProxyListener(static_cast<nsIStreamListener *>(mNewRequest));
ProxyListener *pl = new ProxyListener(static_cast<nsIStreamListener *>(request));
if (!pl) {
request->CancelAndAbort(NS_ERROR_OUT_OF_MEMORY);
NS_RELEASE(request);
return NS_ERROR_OUT_OF_MEMORY;
}
mDestListener = static_cast<nsIStreamListener*>(pl);
// Try to add the new request into the cache. Note that the entry must be in
// the cache before the proxies' ownership changes, because adding a proxy
// changes the caching behaviour for imgRequests.
sImgLoader.PutIntoCache(originalURI, mNewEntry);
sImgLoader.PutIntoCache(uri, entry);
PRUint32 count = mProxies.Count();
for (PRInt32 i = count-1; i>=0; i--) {
imgRequestProxy *proxy = static_cast<imgRequestProxy *>(mProxies[i]);
proxy->ChangeOwner(mNewRequest);
proxy->ChangeOwner(request);
// Proxies waiting on cache validation should be deferring notifications.
// Undefer them.
@ -2129,8 +2155,10 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
proxy->SyncNotifyListener();
}
mNewRequest = nsnull;
mNewEntry = nsnull;
NS_RELEASE(request);
if (!mDestListener)
return NS_OK;
return mDestListener->OnStartRequest(aRequest, ctxt);
}
@ -2150,6 +2178,15 @@ NS_IMETHODIMP imgCacheValidator::OnStopRequest(nsIRequest *aRequest, nsISupports
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */
NS_IMETHODIMP imgCacheValidator::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
{
#ifdef DEBUG
nsCOMPtr<nsICachingChannel> cacheChan(do_QueryInterface(aRequest));
if (cacheChan) {
PRBool isFromCache;
if (NS_SUCCEEDED(cacheChan->IsFromCache(&isFromCache)) && isFromCache)
NS_ERROR("OnDataAvailable not suppressed by LOAD_ONLY_IF_MODIFIED load flag");
}
#endif
if (!mDestListener) {
// XXX see bug 113959
PRUint32 _retval;
@ -2159,62 +2196,3 @@ NS_IMETHODIMP imgCacheValidator::OnDataAvailable(nsIRequest *aRequest, nsISuppor
return mDestListener->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset, count);
}
/** nsIInterfaceRequestor methods **/
NS_IMETHODIMP imgCacheValidator::GetInterface(const nsIID & aIID, void **aResult)
{
if (aIID.Equals(NS_GET_IID(nsIChannelEventSink)))
return QueryInterface(aIID, aResult);
return mProgressProxy->GetInterface(aIID, aResult);
}
// These functions are materially the same as the same functions in imgRequest.
// We duplicate them because we're verifying whether cache loads are necessary,
// not unconditionally loading.
/** nsIChannelEventSink methods **/
NS_IMETHODIMP imgCacheValidator::AsyncOnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel, PRUint32 flags,
nsIAsyncVerifyRedirectCallback *callback)
{
// Note all cache information we get from the old channel.
mNewRequest->SetCacheValidation(mNewEntry, oldChannel);
// Prepare for callback
mRedirectCallback = callback;
mRedirectChannel = newChannel;
return mProgressProxy->AsyncOnChannelRedirect(oldChannel, newChannel, flags, this);
}
NS_IMETHODIMP imgCacheValidator::OnRedirectVerifyCallback(nsresult aResult)
{
// If we've already been told to abort, just do so.
if (NS_FAILED(aResult)) {
mRedirectCallback->OnRedirectVerifyCallback(aResult);
mRedirectCallback = nsnull;
mRedirectChannel = nsnull;
return NS_OK;
}
// make sure we have a protocol that returns data rather than opens
// an external application, e.g. mailto:
nsCOMPtr<nsIURI> uri;
mRedirectChannel->GetURI(getter_AddRefs(uri));
PRBool doesNotReturnData = PR_FALSE;
NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
&doesNotReturnData);
nsresult result = NS_OK;
if (doesNotReturnData) {
result = NS_ERROR_ABORT;
}
mRedirectCallback->OnRedirectVerifyCallback(result);
mRedirectCallback = nsnull;
mRedirectChannel = nsnull;
return NS_OK;
}

View File

@ -52,8 +52,6 @@
#include "imgRequest.h"
#include "nsIObserverService.h"
#include "nsIChannelPolicy.h"
#include "nsIProgressEventSink.h"
#include "nsIChannel.h"
#ifdef LOADER_THREADSAFE
#include "prlock.h"
@ -68,7 +66,7 @@ class nsILoadGroup;
class imgCacheEntry
{
public:
imgCacheEntry(imgRequest *request);
imgCacheEntry(imgRequest *request, PRBool mustValidateIfExpired = PR_FALSE);
~imgCacheEntry();
nsrefcnt AddRef()
@ -125,13 +123,13 @@ public:
Touch();
}
PRBool GetMustValidate() const
PRBool GetMustValidateIfExpired() const
{
return mMustValidate;
return mMustValidateIfExpired;
}
void SetMustValidate(PRBool aValidate)
void SetMustValidateIfExpired(PRBool aValidate)
{
mMustValidate = aValidate;
mMustValidateIfExpired = aValidate;
Touch();
}
@ -180,7 +178,7 @@ private: // data
PRInt32 mTouchedTime;
PRInt32 mExpiryTime;
nsExpirationState mExpirationState;
PRPackedBool mMustValidate : 1;
PRPackedBool mMustValidateIfExpired : 1;
PRPackedBool mEvicted : 1;
PRPackedBool mHasNoProxies : 1;
};
@ -376,33 +374,6 @@ private:
nsCOMPtr<nsIStreamListener> mDestListener;
};
/**
* A class that implements nsIProgressEventSink and forwards all calls to it to
* the original notification callbacks of the channel. Also implements
* nsIInterfaceRequestor and gives out itself for nsIProgressEventSink calls,
* and forwards everything else to the channel's notification callbacks.
*/
class nsProgressNotificationProxy : public nsIProgressEventSink
, public nsIChannelEventSink
, public nsIInterfaceRequestor
{
public:
nsProgressNotificationProxy(nsIChannel* channel,
imgIRequest* proxy)
: mImageRequest(proxy) {
channel->GetNotificationCallbacks(getter_AddRefs(mOriginalCallbacks));
}
NS_DECL_ISUPPORTS
NS_DECL_NSIPROGRESSEVENTSINK
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
private:
~nsProgressNotificationProxy() {}
nsCOMPtr<nsIInterfaceRequestor> mOriginalCallbacks;
nsCOMPtr<nsIRequest> mImageRequest;
};
/**
* validate checker
@ -410,36 +381,25 @@ class nsProgressNotificationProxy : public nsIProgressEventSink
#include "nsCOMArray.h"
class imgCacheValidator : public nsIStreamListener,
public nsIChannelEventSink,
public nsIInterfaceRequestor,
public nsIAsyncVerifyRedirectCallback
class imgCacheValidator : public nsIStreamListener
{
public:
imgCacheValidator(nsProgressNotificationProxy* progress, imgRequest *request, void *aContext);
imgCacheValidator(imgRequest *request, void *aContext);
virtual ~imgCacheValidator();
void AddProxy(imgRequestProxy *aProxy);
/* additional members */
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
private:
nsCOMPtr<nsIStreamListener> mDestListener;
nsRefPtr<nsProgressNotificationProxy> mProgressProxy;
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
nsCOMPtr<nsIChannel> mRedirectChannel;
nsRefPtr<imgRequest> mRequest;
nsCOMArray<imgIRequest> mProxies;
nsRefPtr<imgRequest> mNewRequest;
nsRefPtr<imgCacheEntry> mNewEntry;
void *mContext;
static imgLoader sImgLoader;

View File

@ -191,16 +191,16 @@ imgRequest::imgRequest() :
imgRequest::~imgRequest()
{
if (mURI) {
if (mKeyURI) {
nsCAutoString spec;
mURI->GetSpec(spec);
mKeyURI->GetSpec(spec);
LOG_FUNC_WITH_PARAM(gImgLog, "imgRequest::~imgRequest()", "keyuri", spec.get());
} else
LOG_FUNC(gImgLog, "imgRequest::~imgRequest()");
}
nsresult imgRequest::Init(nsIURI *aURI,
nsIURI *aCurrentURI,
nsIURI *aKeyURI,
nsIRequest *aRequest,
nsIChannel *aChannel,
imgCacheEntry *aCacheEntry,
@ -211,7 +211,7 @@ nsresult imgRequest::Init(nsIURI *aURI,
NS_ABORT_IF_FALSE(!mImage, "Multiple calls to init");
NS_ABORT_IF_FALSE(aURI, "No uri");
NS_ABORT_IF_FALSE(aCurrentURI, "No current uri");
NS_ABORT_IF_FALSE(aKeyURI, "No key uri");
NS_ABORT_IF_FALSE(aRequest, "No request");
NS_ABORT_IF_FALSE(aChannel, "No channel");
@ -220,7 +220,7 @@ nsresult imgRequest::Init(nsIURI *aURI,
mStatusTracker = new imgStatusTracker(nsnull);
mURI = aURI;
mCurrentURI = aCurrentURI;
mKeyURI = aKeyURI;
mRequest = aRequest;
mChannel = aChannel;
mTimedChannel = do_QueryInterface(mChannel);
@ -281,8 +281,8 @@ nsresult imgRequest::AddProxy(imgRequestProxy *proxy)
// If we're empty before adding, we have to tell the loader we now have
// proxies.
if (mObservers.IsEmpty()) {
NS_ABORT_IF_FALSE(mURI, "Trying to SetHasProxies without key uri.");
imgLoader::SetHasProxies(mURI);
NS_ABORT_IF_FALSE(mKeyURI, "Trying to SetHasProxies without key uri.");
imgLoader::SetHasProxies(mKeyURI);
}
// If we don't have any current observers, we should restart any animation.
@ -322,14 +322,14 @@ nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, PRBoo
// been cancelled and thus removed from the cache, tell the image loader so
// we can be evicted from the cache.
if (mCacheEntry) {
NS_ABORT_IF_FALSE(mURI, "Removing last observer without key uri.");
NS_ABORT_IF_FALSE(mKeyURI, "Removing last observer without key uri.");
imgLoader::SetHasNoProxies(mURI, mCacheEntry);
imgLoader::SetHasNoProxies(mKeyURI, mCacheEntry);
}
#if defined(PR_LOGGING)
else {
nsCAutoString spec;
mURI->GetSpec(spec);
mKeyURI->GetSpec(spec);
LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy no cache entry", "uri", spec.get());
}
#endif
@ -410,8 +410,8 @@ nsresult imgRequest::GetKeyURI(nsIURI **aKeyURI)
{
LOG_FUNC(gImgLog, "imgRequest::GetKeyURI");
if (mURI) {
*aKeyURI = mURI;
if (mKeyURI) {
*aKeyURI = mKeyURI;
NS_ADDREF(*aKeyURI);
return NS_OK;
}
@ -438,7 +438,7 @@ void imgRequest::RemoveFromCache()
if (mCacheEntry)
imgLoader::RemoveFromCache(mCacheEntry);
else
imgLoader::RemoveFromCache(mURI);
imgLoader::RemoveFromCache(mKeyURI);
}
mCacheEntry = nsnull;
@ -507,71 +507,6 @@ void imgRequest::UpdateCacheEntrySize()
}
}
void imgRequest::SetCacheValidation(imgCacheEntry* aCacheEntry, nsIRequest* aRequest)
{
/* get the expires info */
if (aCacheEntry) {
nsCOMPtr<nsICachingChannel> cacheChannel(do_QueryInterface(aRequest));
if (cacheChannel) {
nsCOMPtr<nsISupports> cacheToken;
cacheChannel->GetCacheToken(getter_AddRefs(cacheToken));
if (cacheToken) {
nsCOMPtr<nsICacheEntryInfo> entryDesc(do_QueryInterface(cacheToken));
if (entryDesc) {
PRUint32 expiration;
/* get the expiration time from the caching channel's token */
entryDesc->GetExpirationTime(&expiration);
// Expiration time defaults to 0. We set the expiration time on our
// entry if it hasn't been set yet.
if (aCacheEntry->GetExpiryTime() == 0)
aCacheEntry->SetExpiryTime(expiration);
}
}
}
// Determine whether the cache entry must be revalidated when we try to use it.
// Currently, only HTTP specifies this information...
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
if (httpChannel) {
PRBool bMustRevalidate = PR_FALSE;
httpChannel->IsNoStoreResponse(&bMustRevalidate);
if (!bMustRevalidate) {
httpChannel->IsNoCacheResponse(&bMustRevalidate);
}
if (!bMustRevalidate) {
nsCAutoString cacheHeader;
httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Cache-Control"),
cacheHeader);
if (PL_strcasestr(cacheHeader.get(), "must-revalidate")) {
bMustRevalidate = PR_TRUE;
}
}
// Cache entries default to not needing to validate. We ensure that
// multiple calls to this function don't override an earlier decision to
// validate by making validation a one-way decision.
if (bMustRevalidate)
aCacheEntry->SetMustValidate(bMustRevalidate);
}
// We always need to validate file URIs.
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
if (channel) {
nsCOMPtr<nsIURI> uri;
channel->GetURI(getter_AddRefs(uri));
PRBool isfile = PR_FALSE;
uri->SchemeIs("file", &isfile);
if (isfile)
aCacheEntry->SetMustValidate(isfile);
}
}
}
nsresult
imgRequest::LockImage()
{
@ -815,6 +750,8 @@ NS_IMETHODIMP imgRequest::OnDiscard(imgIRequest *aRequest)
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt)
{
nsresult rv;
LOG_SCOPE(gImgLog, "imgRequest::OnStartRequest");
// Figure out if we're multipart
@ -886,7 +823,55 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt
}
}
SetCacheValidation(mCacheEntry, aRequest);
/* get the expires info */
if (mCacheEntry) {
nsCOMPtr<nsICachingChannel> cacheChannel(do_QueryInterface(aRequest));
if (cacheChannel) {
nsCOMPtr<nsISupports> cacheToken;
cacheChannel->GetCacheToken(getter_AddRefs(cacheToken));
if (cacheToken) {
nsCOMPtr<nsICacheEntryInfo> entryDesc(do_QueryInterface(cacheToken));
if (entryDesc) {
PRUint32 expiration;
/* get the expiration time from the caching channel's token */
entryDesc->GetExpirationTime(&expiration);
/* set the expiration time on our entry */
mCacheEntry->SetExpiryTime(expiration);
}
}
}
//
// Determine whether the cache entry must be revalidated when it expires.
// If so, then the cache entry must *not* be used during HISTORY loads if
// it has expired.
//
// Currently, only HTTP specifies this information...
//
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
if (httpChannel) {
PRBool bMustRevalidate = PR_FALSE;
rv = httpChannel->IsNoStoreResponse(&bMustRevalidate);
if (!bMustRevalidate) {
rv = httpChannel->IsNoCacheResponse(&bMustRevalidate);
}
if (!bMustRevalidate) {
nsCAutoString cacheHeader;
rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Cache-Control"),
cacheHeader);
if (PL_strcasestr(cacheHeader.get(), "must-revalidate")) {
bMustRevalidate = PR_TRUE;
}
}
mCacheEntry->SetMustValidateIfExpired(bMustRevalidate);
}
}
// Shouldn't we be dead already if this gets hit? Probably multipart/x-mixed-replace...
if (mObservers.IsEmpty()) {
@ -1254,8 +1239,6 @@ imgRequest::AsyncOnChannelRedirect(nsIChannel *oldChannel,
NS_ASSERTION(mChannel == oldChannel, "Got a channel redirect for an unknown channel!");
NS_ASSERTION(newChannel, "Got a redirect to a NULL channel!");
SetCacheValidation(mCacheEntry, oldChannel);
// Prepare for callback
mRedirectCallback = callback;
mNewRedirectChannel = newChannel;
@ -1270,7 +1253,7 @@ imgRequest::AsyncOnChannelRedirect(nsIChannel *oldChannel,
}
return rv;
}
(void) OnRedirectVerifyCallback(NS_OK);
return NS_OK;
}
@ -1280,7 +1263,7 @@ imgRequest::OnRedirectVerifyCallback(nsresult result)
{
NS_ASSERTION(mRedirectCallback, "mRedirectCallback not set in callback");
NS_ASSERTION(mNewRedirectChannel, "mNewRedirectChannel not set in callback");
if (NS_FAILED(result)) {
mRedirectCallback->OnRedirectVerifyCallback(result);
mRedirectCallback = nsnull;
@ -1292,19 +1275,21 @@ imgRequest::OnRedirectVerifyCallback(nsresult result)
mTimedChannel = do_QueryInterface(mChannel);
mNewRedirectChannel = nsnull;
#if defined(PR_LOGGING)
// Don't make any cache changes if we're going to point to the same thing. We
// compare specs and not just URIs here because URIs that compare as
// .Equals() might have different hashes.
nsCAutoString oldspec;
if (mCurrentURI)
mCurrentURI->GetSpec(oldspec);
if (mKeyURI)
mKeyURI->GetSpec(oldspec);
LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnChannelRedirect", "old", oldspec.get());
#endif
// make sure we have a protocol that returns data rather than opens
// an external application, e.g. mailto:
mChannel->GetURI(getter_AddRefs(mCurrentURI));
nsCOMPtr<nsIURI> uri;
mChannel->GetURI(getter_AddRefs(uri));
PRBool doesNotReturnData = PR_FALSE;
nsresult rv =
NS_URIChainHasFlags(mCurrentURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
&doesNotReturnData);
if (NS_SUCCEEDED(rv) && doesNotReturnData)
@ -1316,6 +1301,34 @@ imgRequest::OnRedirectVerifyCallback(nsresult result)
return NS_OK;
}
nsCOMPtr<nsIURI> newURI;
mChannel->GetOriginalURI(getter_AddRefs(newURI));
nsCAutoString newspec;
if (newURI)
newURI->GetSpec(newspec);
LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnChannelRedirect", "new", newspec.get());
if (oldspec != newspec) {
if (mIsInCache) {
// Remove the cache entry from the cache, but don't null out mCacheEntry
// (as imgRequest::RemoveFromCache() does), because we need it to put
// ourselves back in the cache.
if (mCacheEntry)
imgLoader::RemoveFromCache(mCacheEntry);
else
imgLoader::RemoveFromCache(mKeyURI);
}
mKeyURI = newURI;
if (mIsInCache) {
// If we don't still have a URI or cache entry, we don't want to put
// ourselves back into the cache.
if (mKeyURI && mCacheEntry)
imgLoader::PutIntoCache(mKeyURI, mCacheEntry);
}
}
mRedirectCallback->OnRedirectVerifyCallback(NS_OK);
mRedirectCallback = nsnull;
return NS_OK;

View File

@ -90,7 +90,7 @@ public:
NS_DECL_ISUPPORTS
nsresult Init(nsIURI *aURI,
nsIURI *aCurrentURI,
nsIURI *aKeyURI,
nsIRequest *aRequest,
nsIChannel *aChannel,
imgCacheEntry *aCacheEntry,
@ -129,12 +129,6 @@ public:
return mWindowId;
}
// Set the cache validation information (expiry time, whether we must
// validate, etc) on the cache entry based on the request information.
// If this function is called multiple times, the information set earliest
// wins.
static void SetCacheValidation(imgCacheEntry* aEntry, nsIRequest* aRequest);
private:
friend class imgCacheEntry;
friend class imgRequestProxy;
@ -211,11 +205,10 @@ private:
friend class imgMemoryReporter;
nsCOMPtr<nsIRequest> mRequest;
// The original URI we were loaded with. This is the same as the URI we are
// keyed on in the cache.
// The original URI we were loaded with.
nsCOMPtr<nsIURI> mURI;
// The URI of the resource we ended up loading after all redirects, etc.
nsCOMPtr<nsIURI> mCurrentURI;
// The URI we are keyed on in the cache.
nsCOMPtr<nsIURI> mKeyURI;
nsCOMPtr<nsIPrincipal> mPrincipal;
// Status-tracker -- transferred to mImage, when it gets instantiated
nsAutoPtr<imgStatusTracker> mStatusTracker;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 B

View File

@ -13,8 +13,3 @@ load delaytest.html?523528-2.gif
# this would have exposed the leak discovered in bug 642902
load invalid-icc-profile.jpg
# maximum (256) width and height icons that we currently (due to bug 668068)
# interpret as 0-width and 0-height.
load 256-width.ico
load 256-height.ico

View File

@ -76,13 +76,6 @@ _TEST_FILES = imgutils.js \
test_bug614392.html \
test_bug657191.html \
bug657191.sjs \
bug89419-iframe.html \
bug89419.sjs \
test_bug89419-1.html \
test_bug89419-2.html \
test_bug552605-1.html \
test_bug552605-2.html \
bug552605.sjs \
$(NULL)
# Tests disabled due to intermittent orange

View File

@ -1,13 +0,0 @@
function handleRequest(request, response)
{
var redirectstate = "/modules/libpr0n/test/mochitest/bug89419.sjs";
response.setStatusLine("1.1", 302, "Found");
if (getState(redirectstate) == "") {
response.setHeader("Location", "red.png", false);
setState(redirectstate, "red");
} else {
response.setHeader("Location", "blue.png", false);
setState(redirectstate, "");
}
response.setHeader("Cache-Control", "no-cache", false);
}

View File

@ -1,7 +0,0 @@
<html>
<head>
<title>Bug 89419 iframe</title>
<body>
<img src="bug89419.sjs" width="100" height="100" />
</body>
</html>

View File

@ -1,13 +0,0 @@
function handleRequest(request, response)
{
var redirectstate = "/modules/libpr0n/test/mochitest/bug89419.sjs";
response.setStatusLine("1.1", 302, "Found");
if (getState(redirectstate) == "") {
response.setHeader("Location", "red.png", false);
setState(redirectstate, "red");
} else {
response.setHeader("Location", "blue.png", false);
setState(redirectstate, "");
}
response.setHeader("Cache-Control", "no-cache", false);
}

View File

@ -1,56 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=552605
-->
<head>
<title>Test for Bug 552605</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=552605">Mozilla Bug 552605</a>
<p id="display"></p>
<pre id="test">
<script type="application/javascript">
var first, second;
SimpleTest.waitForExplicitFinish();
function checkFirst()
{
var testimage = document.getElementById('test-image');
first = document.createElement('canvas')
var ctx = first.getContext('2d');
ctx.drawImage(testimage, 0, 0);
var newimg = new Image();
newimg.onload = checkSecond;
newimg.src = "bug552605.sjs";
document.body.appendChild(newimg);
}
function checkSecond()
{
var testimage = document.getElementById('test-image');
second = document.createElement('canvas')
var ctx = second.getContext('2d');
ctx.drawImage(testimage, 0, 0);
// Check that the images are the same, since they're in the same document.
[correct, val1, val2] = compareSnapshots(first, second, true);
ok(correct, "Image should be the same for all loads.");
SimpleTest.finish();
}
</script>
</pre>
<div id="content"> <!-- style="display: none" -->
<img src="bug552605.sjs" onload="checkFirst()" id="test-image"></iframe>
</div>
</body>
</html>

View File

@ -1,53 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=552605
-->
<head>
<title>Test for Bug 552605</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=552605">Mozilla Bug 552605</a>
<p id="display"></p>
<pre id="test">
<script type="application/javascript">
var count = 0;
SimpleTest.waitForExplicitFinish();
function check()
{
count++;
if (count != 2)
return;
var image1 = document.getElementById('test-image1');
var image2 = document.getElementById('test-image2');
var first = document.createElement('canvas')
var ctx = first.getContext('2d');
ctx.drawImage(image1, 0, 0);
var second = document.createElement('canvas');
ctx = second.getContext('2d');
ctx.drawImage(image2, 0, 0);
// Check that the images are the same, since they're in the same document.
[correct, val1, val2] = compareSnapshots(first, second, true);
ok(correct, "Image should be the same for all loads.");
SimpleTest.finish();
}
</script>
</pre>
<div id="content"> <!-- style="display: none" -->
<img src="bug552605.sjs" onload="check()" id="test-image1"></iframe>
<img src="bug552605.sjs" onload="check()" id="test-image2"></iframe>
</div>
</body>
</html>

View File

@ -1,68 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=89419
-->
<head>
<title>Test for Bug 89419</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=89419">Mozilla Bug 89419</a>
<p id="display"></p>
<pre id="test">
<script type="application/javascript">
var first, second, third;
var correct, val1, val2;
SimpleTest.waitForExplicitFinish();
function checkFirst()
{
var iframeelem = document.getElementById('test-iframe');
first = snapshotWindow(iframeelem.contentWindow, false);
iframeelem.onload = checkSecond;
iframeelem.contentWindow.location.reload(false);
}
function checkSecond()
{
var iframeelem = document.getElementById('test-iframe');
second = snapshotWindow(iframeelem.contentWindow, false);
// Check that we actually reloaded.
[correct, val1, val2] = compareSnapshots(first, second, false);
ok(correct, "Image should have changed after the first reload.");
iframeelem.onload = checkThird;
iframeelem.contentWindow.location.reload(false);
}
function checkThird()
{
var iframeelem = document.getElementById('test-iframe');
third = snapshotWindow(iframeelem.contentWindow, false);
// Check that we actually reloaded.
[correct, val1, val2] = compareSnapshots(second, third, false);
ok(correct, "Image should have changed after the second reload.");
// Make sure we looped back to the first image.
[correct, val1, val2] = compareSnapshots(first, third, true);
ok(correct, "Third image should match first image.");
SimpleTest.finish();
}
</script>
</pre>
<div id="content"> <!-- style="display: none" -->
<iframe id="test-iframe" src="bug89419-iframe.html" onload="checkFirst()"></iframe>
</div>
</body>
</html>

View File

@ -1,68 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=89419
-->
<head>
<title>Test for Bug 89419</title>
<script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=89419">Mozilla Bug 89419</a>
<p id="display"></p>
<pre id="test">
<script type="application/javascript">
var first, second, third;
var correct, val1, val2;
SimpleTest.waitForExplicitFinish();
function checkFirst()
{
var iframeelem = document.getElementById('test-iframe');
first = snapshotWindow(iframeelem.contentWindow, false);
iframeelem.onload = checkSecond;
iframeelem.contentWindow.location.href = iframeelem.contentWindow.location.href;
}
function checkSecond()
{
var iframeelem = document.getElementById('test-iframe');
second = snapshotWindow(iframeelem.contentWindow, false);
// Check that we actually reloaded.
[correct, val1, val2] = compareSnapshots(first, second, false);
ok(correct, "Image should have changed after the first reload.");
iframeelem.onload = checkThird;
iframeelem.contentWindow.location.href = iframeelem.contentWindow.location.href;
}
function checkThird()
{
var iframeelem = document.getElementById('test-iframe');
third = snapshotWindow(iframeelem.contentWindow, false);
// Check that we actually reloaded.
[correct, val1, val2] = compareSnapshots(second, third, false);
ok(correct, "Image should have changed after the second reload.");
// Make sure we looped back to the first image.
[correct, val1, val2] = compareSnapshots(first, third, true);
ok(correct, "Third image should match first image.");
SimpleTest.finish();
}
</script>
</pre>
<div id="content"> <!-- style="display: none" -->
<iframe id="test-iframe" src="bug89419-iframe.html" onload="checkFirst()"></iframe>
</div>
</body>
</html>

View File

@ -3,7 +3,7 @@ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var gWindowUtils;
try {
gWindowUtils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils);
gWindowUtils = window.QueryInterface(CI.nsIInterfaceRequestor).getInterface(CI.nsIDOMWindowUtils);
if (gWindowUtils && !gWindowUtils.compareCanvases)
gWindowUtils = null;
} catch (e) {