зеркало из https://github.com/mozilla/gecko-dev.git
Bug 697230: Part 2 - Push onload blocking logic down into imagelib. r=joe sr=bz
This commit is contained in:
Родитель
dd495263dd
Коммит
b579ded900
|
@ -1658,6 +1658,21 @@ extern const nsIID kThisPtrOffsetsSID;
|
|||
NS_OFFSET_AND_INTERFACE_TABLE_END \
|
||||
NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
|
||||
|
||||
#define NS_NODE_INTERFACE_TABLE9(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, \
|
||||
_i8, _i9) \
|
||||
NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class) \
|
||||
NS_INTERFACE_TABLE_ENTRY(_class, _i1) \
|
||||
NS_INTERFACE_TABLE_ENTRY(_class, _i2) \
|
||||
NS_INTERFACE_TABLE_ENTRY(_class, _i3) \
|
||||
NS_INTERFACE_TABLE_ENTRY(_class, _i4) \
|
||||
NS_INTERFACE_TABLE_ENTRY(_class, _i5) \
|
||||
NS_INTERFACE_TABLE_ENTRY(_class, _i6) \
|
||||
NS_INTERFACE_TABLE_ENTRY(_class, _i7) \
|
||||
NS_INTERFACE_TABLE_ENTRY(_class, _i8) \
|
||||
NS_INTERFACE_TABLE_ENTRY(_class, _i9) \
|
||||
NS_OFFSET_AND_INTERFACE_TABLE_END \
|
||||
NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
|
||||
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsINode, NS_INODE_IID)
|
||||
|
||||
|
|
|
@ -76,8 +76,12 @@ public:
|
|||
NS_DECL_ISUPPORTS_INHERITED
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED3(nsGenConImageContent, nsXMLElement,
|
||||
nsIImageLoadingContent, imgIContainerObserver, imgIDecoderObserver)
|
||||
NS_IMPL_ISUPPORTS_INHERITED4(nsGenConImageContent,
|
||||
nsXMLElement,
|
||||
nsIImageLoadingContent,
|
||||
imgIContainerObserver,
|
||||
imgIDecoderObserver,
|
||||
imgIOnloadBlocker)
|
||||
|
||||
nsresult
|
||||
NS_NewGenConImageContent(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||
|
|
|
@ -187,23 +187,6 @@ nsImageLoadingContent::OnStartDecode(imgIRequest* aRequest)
|
|||
{
|
||||
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
// Onload blocking. This only applies for the current request.
|
||||
if (aRequest == mCurrentRequest) {
|
||||
|
||||
// Determine whether this is a background request (this can be the case
|
||||
// with multipart/x-mixed-replace images, for example).
|
||||
PRUint32 loadFlags;
|
||||
nsresult rv = aRequest->GetLoadFlags(&loadFlags);
|
||||
bool background =
|
||||
(NS_SUCCEEDED(rv) && (loadFlags & nsIRequest::LOAD_BACKGROUND));
|
||||
|
||||
// Block onload for non-background requests
|
||||
if (!background) {
|
||||
NS_ABORT_IF_FALSE(!mBlockingOnload, "Shouldn't already be blocking");
|
||||
SetBlockingOnload(true);
|
||||
}
|
||||
}
|
||||
|
||||
LOOP_OVER_OBSERVERS(OnStartDecode(aRequest));
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -249,10 +232,6 @@ nsImageLoadingContent::OnStopFrame(imgIRequest* aRequest,
|
|||
{
|
||||
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
// If we're blocking a load, one frame is enough
|
||||
if (aRequest == mCurrentRequest)
|
||||
SetBlockingOnload(false);
|
||||
|
||||
LOOP_OVER_OBSERVERS(OnStopFrame(aRequest, aFrame));
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -263,15 +242,6 @@ nsImageLoadingContent::OnStopContainer(imgIRequest* aRequest,
|
|||
{
|
||||
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
// This is really hacky. We need to handle the case where we start decoding,
|
||||
// block onload, but then hit an error before we get to our first frame. In
|
||||
// theory we would just hook in at OnStopDecode, but OnStopDecode is broken
|
||||
// until we fix bug 505385. OnStopContainer is actually going away at that
|
||||
// point. So for now we take advantage of the fact that OnStopContainer is
|
||||
// always fired in the decoders at the same time as OnStopDecode.
|
||||
if (aRequest == mCurrentRequest)
|
||||
SetBlockingOnload(false);
|
||||
|
||||
LOOP_OVER_OBSERVERS(OnStopContainer(aRequest, aContainer));
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -349,7 +319,7 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
|
|||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> thisNode = do_QueryInterface(this);
|
||||
nsCOMPtr<nsINode> thisNode = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
nsSVGEffects::InvalidateDirectRenderingObservers(thisNode->AsElement());
|
||||
|
||||
return NS_OK;
|
||||
|
@ -637,6 +607,36 @@ NS_IMETHODIMP nsImageLoadingContent::ForceReload()
|
|||
return LoadImage(currentURI, true, true, nsnull, nsIRequest::VALIDATE_ALWAYS);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoadingContent::BlockOnload(imgIRequest* aRequest)
|
||||
{
|
||||
if (aRequest != mCurrentRequest) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument* doc = GetOurDocument();
|
||||
if (doc) {
|
||||
doc->BlockOnload();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoadingContent::UnblockOnload(imgIRequest* aRequest)
|
||||
{
|
||||
if (aRequest != mCurrentRequest) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument* doc = GetOurDocument();
|
||||
if (doc) {
|
||||
doc->UnblockOnload(false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-interface methods
|
||||
*/
|
||||
|
@ -746,7 +746,7 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
|
|||
// We use the principal of aDocument to avoid having to QI |this| an extra
|
||||
// time. It should always be the same as the principal of this node.
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
NS_ABORT_IF_FALSE(thisContent &&
|
||||
thisContent->NodePrincipal() == aDocument->NodePrincipal(),
|
||||
"Principal mismatch?");
|
||||
|
@ -754,8 +754,11 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
|
|||
|
||||
// Are we blocked?
|
||||
PRInt16 cpDecision = nsIContentPolicy::REJECT_REQUEST;
|
||||
nsContentUtils::CanLoadImage(aNewURI, this, aDocument,
|
||||
aDocument->NodePrincipal(), &cpDecision);
|
||||
nsContentUtils::CanLoadImage(aNewURI,
|
||||
static_cast<nsIImageLoadingContent*>(this),
|
||||
aDocument,
|
||||
aDocument->NodePrincipal(),
|
||||
&cpDecision);
|
||||
if (!NS_CP_ACCEPTED(cpDecision)) {
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
SetBlockedRequest(aNewURI, cpDecision);
|
||||
|
@ -860,7 +863,7 @@ nsImageLoadingContent::UpdateImageState(bool aNotify)
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
if (!thisContent) {
|
||||
return;
|
||||
}
|
||||
|
@ -924,7 +927,7 @@ nsImageLoadingContent::UseAsPrimaryRequest(imgIRequest* aRequest,
|
|||
nsIDocument*
|
||||
nsImageLoadingContent::GetOurDocument()
|
||||
{
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
NS_ENSURE_TRUE(thisContent, nsnull);
|
||||
|
||||
return thisContent->OwnerDoc();
|
||||
|
@ -933,7 +936,7 @@ nsImageLoadingContent::GetOurDocument()
|
|||
nsIFrame*
|
||||
nsImageLoadingContent::GetOurPrimaryFrame()
|
||||
{
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
return thisContent->GetPrimaryFrame();
|
||||
}
|
||||
|
||||
|
@ -956,7 +959,7 @@ nsImageLoadingContent::StringToURI(const nsAString& aSpec,
|
|||
NS_PRECONDITION(aURI, "Null out param");
|
||||
|
||||
// (1) Get the base URI
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
NS_ASSERTION(thisContent, "An image loading content must be an nsIContent");
|
||||
nsCOMPtr<nsIURI> baseURL = thisContent->GetBaseURI();
|
||||
|
||||
|
@ -978,7 +981,7 @@ nsImageLoadingContent::FireEvent(const nsAString& aEventType)
|
|||
// loops in cases when onLoad handlers reset the src and the new src is in
|
||||
// cache.
|
||||
|
||||
nsCOMPtr<nsINode> thisNode = do_QueryInterface(this);
|
||||
nsCOMPtr<nsINode> thisNode = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
|
||||
nsRefPtr<nsAsyncDOMEvent> event =
|
||||
new nsLoadBlockingAsyncDOMEvent(thisNode, aEventType, false, false);
|
||||
|
@ -1086,10 +1089,6 @@ nsImageLoadingContent::ClearCurrentRequest(nsresult aReason)
|
|||
mCurrentRequest->CancelAndForgetObserver(aReason);
|
||||
mCurrentRequest = nsnull;
|
||||
mCurrentRequestNeedsResetAnimation = false;
|
||||
|
||||
// We only block onload during the decoding of "current" images. This one is
|
||||
// going away, so we should unblock unconditionally here.
|
||||
SetBlockingOnload(false);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1140,28 +1139,6 @@ nsImageLoadingContent::HaveSize(imgIRequest *aImage)
|
|||
return (NS_SUCCEEDED(rv) && (status & imgIRequest::STATUS_SIZE_AVAILABLE));
|
||||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::SetBlockingOnload(bool aBlocking)
|
||||
{
|
||||
// If we're already in the desired state, we have nothing to do
|
||||
if (mBlockingOnload == aBlocking)
|
||||
return;
|
||||
|
||||
// Get the document
|
||||
nsIDocument* doc = GetOurDocument();
|
||||
|
||||
if (doc) {
|
||||
// Take the appropriate action
|
||||
if (aBlocking)
|
||||
doc->BlockOnload();
|
||||
else
|
||||
doc->UnblockOnload(false);
|
||||
|
||||
// Update our state
|
||||
mBlockingOnload = aBlocking;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImageLoadingContent::TrackImage(imgIRequest* aImage)
|
||||
{
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
|
||||
#include "imgIContainerObserver.h"
|
||||
#include "imgIDecoderObserver.h"
|
||||
#include "imgIOnloadBlocker.h"
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsContentUtils.h" // NS_CONTENT_DELETE_LIST_MEMBER
|
||||
|
@ -59,7 +60,8 @@ class nsIDocument;
|
|||
class imgILoader;
|
||||
class nsIIOService;
|
||||
|
||||
class nsImageLoadingContent : public nsIImageLoadingContent
|
||||
class nsImageLoadingContent : public nsIImageLoadingContent,
|
||||
public imgIOnloadBlocker
|
||||
{
|
||||
/* METHODS */
|
||||
public:
|
||||
|
@ -69,6 +71,7 @@ public:
|
|||
NS_DECL_IMGICONTAINEROBSERVER
|
||||
NS_DECL_IMGIDECODEROBSERVER
|
||||
NS_DECL_NSIIMAGELOADINGCONTENT
|
||||
NS_DECL_IMGIONLOADBLOCKER
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
|
|
@ -219,12 +219,13 @@ DOMCI_NODE_DATA(HTMLImageElement, nsHTMLImageElement)
|
|||
|
||||
// QueryInterface implementation for nsHTMLImageElement
|
||||
NS_INTERFACE_TABLE_HEAD(nsHTMLImageElement)
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLImageElement,
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE6(nsHTMLImageElement,
|
||||
nsIDOMHTMLImageElement,
|
||||
nsIJSNativeInitializer,
|
||||
imgIDecoderObserver,
|
||||
nsIImageLoadingContent,
|
||||
imgIContainerObserver)
|
||||
imgIContainerObserver,
|
||||
imgIOnloadBlocker)
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLImageElement,
|
||||
nsGenericHTMLElement)
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLImageElement)
|
||||
|
|
|
@ -655,13 +655,14 @@ DOMCI_NODE_DATA(HTMLInputElement, nsHTMLInputElement)
|
|||
|
||||
// QueryInterface implementation for nsHTMLInputElement
|
||||
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLInputElement)
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE8(nsHTMLInputElement,
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE9(nsHTMLInputElement,
|
||||
nsIDOMHTMLInputElement,
|
||||
nsITextControlElement,
|
||||
nsIPhonetic,
|
||||
imgIDecoderObserver,
|
||||
nsIImageLoadingContent,
|
||||
imgIContainerObserver,
|
||||
imgIOnloadBlocker,
|
||||
nsIDOMNSEditableElement,
|
||||
nsIConstraintValidation)
|
||||
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLInputElement,
|
||||
|
|
|
@ -233,6 +233,7 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLObjectElement)
|
|||
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIFrameLoaderOwner)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIObjectLoadingContent)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIImageLoadingContent)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, imgIOnloadBlocker)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, imgIContainerObserver)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIInterfaceRequestor)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIChannelEventSink)
|
||||
|
|
|
@ -258,6 +258,7 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLSharedObjectElement)
|
|||
NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, nsIObjectLoadingContent)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, imgIDecoderObserver)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, nsIImageLoadingContent)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, imgIOnloadBlocker)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, nsIInterfaceRequestor)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, nsIChannelEventSink)
|
||||
NS_OFFSET_AND_INTERFACE_TABLE_END
|
||||
|
|
|
@ -5463,11 +5463,12 @@ NS_IMPL_RELEASE_INHERITED(nsSVGFEImageElement,nsSVGFEImageElementBase)
|
|||
DOMCI_NODE_DATA(SVGFEImageElement, nsSVGFEImageElement)
|
||||
|
||||
NS_INTERFACE_TABLE_HEAD(nsSVGFEImageElement)
|
||||
NS_NODE_INTERFACE_TABLE8(nsSVGFEImageElement, nsIDOMNode, nsIDOMElement,
|
||||
NS_NODE_INTERFACE_TABLE9(nsSVGFEImageElement, nsIDOMNode, nsIDOMElement,
|
||||
nsIDOMSVGElement,
|
||||
nsIDOMSVGFilterPrimitiveStandardAttributes,
|
||||
nsIDOMSVGFEImageElement, nsIDOMSVGURIReference,
|
||||
imgIDecoderObserver, nsIImageLoadingContent)
|
||||
imgIDecoderObserver, nsIImageLoadingContent,
|
||||
imgIOnloadBlocker)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEImageElement)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsSVGFEImageElementBase)
|
||||
|
||||
|
|
|
@ -72,11 +72,11 @@ NS_IMPL_RELEASE_INHERITED(nsSVGImageElement,nsSVGImageElementBase)
|
|||
DOMCI_NODE_DATA(SVGImageElement, nsSVGImageElement)
|
||||
|
||||
NS_INTERFACE_TABLE_HEAD(nsSVGImageElement)
|
||||
NS_NODE_INTERFACE_TABLE8(nsSVGImageElement, nsIDOMNode, nsIDOMElement,
|
||||
NS_NODE_INTERFACE_TABLE9(nsSVGImageElement, nsIDOMNode, nsIDOMElement,
|
||||
nsIDOMSVGElement, nsIDOMSVGTests,
|
||||
nsIDOMSVGImageElement,
|
||||
nsIDOMSVGURIReference, imgIDecoderObserver,
|
||||
nsIImageLoadingContent)
|
||||
nsIImageLoadingContent, imgIOnloadBlocker)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGImageElement)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsSVGImageElementBase)
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ XPIDLSRCS = \
|
|||
imgIDecoderObserver.idl \
|
||||
imgIEncoder.idl \
|
||||
imgILoader.idl \
|
||||
imgIOnloadBlocker.idl \
|
||||
imgIRequest.idl \
|
||||
imgITools.idl \
|
||||
$(NULL)
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/* -*- 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) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Kyle Huey <me@kylehuey.com> (original author)
|
||||
*
|
||||
* 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"
|
||||
|
||||
interface imgIRequest;
|
||||
|
||||
[uuid(dc126d90-0ee0-4683-b942-2fa66e443abc)]
|
||||
interface imgIOnloadBlocker : nsISupports
|
||||
{
|
||||
/**
|
||||
* blockOnload
|
||||
* Called when it is appropriate to block onload for the given imgIRequest.
|
||||
*
|
||||
* @param aRequest
|
||||
* The request that should block onload.
|
||||
*/
|
||||
void blockOnload(in imgIRequest aRequest);
|
||||
|
||||
/**
|
||||
* unblockOnload
|
||||
* Called when it is appropriate to unblock onload for the given
|
||||
* imgIRequest.
|
||||
*
|
||||
* @param aRequest
|
||||
* The request that should unblock onload.
|
||||
*/
|
||||
void unblockOnload(in imgIRequest aRequest);
|
||||
};
|
|
@ -117,7 +117,7 @@ imgRequest::imgRequest() :
|
|||
mValidator(nsnull), mImageSniffers("image-sniffing-services"),
|
||||
mInnerWindowId(0), mCORSMode(imgIRequest::CORS_NONE),
|
||||
mDecodeRequested(false), mIsMultiPartChannel(false), mGotData(false),
|
||||
mIsInCache(false)
|
||||
mIsInCache(false), mBlockingOnload(false)
|
||||
{
|
||||
// Register our pref observers if we haven't yet.
|
||||
if (NS_UNLIKELY(!gInitializedPrefCaches)) {
|
||||
|
@ -312,6 +312,18 @@ void imgRequest::Cancel(nsresult aStatus)
|
|||
LOG_SCOPE(gImgLog, "imgRequest::Cancel");
|
||||
|
||||
imgStatusTracker& statusTracker = GetStatusTracker();
|
||||
|
||||
if (mBlockingOnload) {
|
||||
mBlockingOnload = false;
|
||||
|
||||
statusTracker.RecordUnblockOnload();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
while (iter.HasMore()) {
|
||||
statusTracker.SendUnblockOnload(iter.GetNext());
|
||||
}
|
||||
}
|
||||
|
||||
statusTracker.RecordCancel();
|
||||
|
||||
RemoveFromCache();
|
||||
|
@ -545,11 +557,24 @@ NS_IMETHODIMP imgRequest::OnStartDecode(imgIRequest *request)
|
|||
"OnStartDecode callback before we've created our image");
|
||||
|
||||
|
||||
mImage->GetStatusTracker().RecordStartDecode();
|
||||
imgStatusTracker& tracker = mImage->GetStatusTracker();
|
||||
tracker.RecordStartDecode();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
while (iter.HasMore()) {
|
||||
mImage->GetStatusTracker().SendStartDecode(iter.GetNext());
|
||||
tracker.SendStartDecode(iter.GetNext());
|
||||
}
|
||||
|
||||
if (!mIsMultiPartChannel) {
|
||||
MOZ_ASSERT(!mBlockingOnload);
|
||||
mBlockingOnload = true;
|
||||
|
||||
tracker.RecordBlockOnload();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
while (iter.HasMore()) {
|
||||
tracker.SendBlockOnload(iter.GetNext());
|
||||
}
|
||||
}
|
||||
|
||||
/* In the case of streaming jpegs, it is possible to get multiple OnStartDecodes which
|
||||
|
@ -636,11 +661,23 @@ NS_IMETHODIMP imgRequest::OnStopFrame(imgIRequest *request,
|
|||
NS_ABORT_IF_FALSE(mImage,
|
||||
"OnStopFrame callback before we've created our image");
|
||||
|
||||
mImage->GetStatusTracker().RecordStopFrame(frame);
|
||||
imgStatusTracker& tracker = mImage->GetStatusTracker();
|
||||
tracker.RecordStopFrame(frame);
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
while (iter.HasMore()) {
|
||||
mImage->GetStatusTracker().SendStopFrame(iter.GetNext(), frame);
|
||||
tracker.SendStopFrame(iter.GetNext(), frame);
|
||||
}
|
||||
|
||||
if (mBlockingOnload) {
|
||||
mBlockingOnload = false;
|
||||
|
||||
tracker.RecordUnblockOnload();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
while (iter.HasMore()) {
|
||||
tracker.SendUnblockOnload(iter.GetNext());
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -654,11 +691,29 @@ NS_IMETHODIMP imgRequest::OnStopContainer(imgIRequest *request,
|
|||
NS_ABORT_IF_FALSE(mImage,
|
||||
"OnDataContainer callback before we've created our image");
|
||||
|
||||
mImage->GetStatusTracker().RecordStopContainer(image);
|
||||
imgStatusTracker& tracker = mImage->GetStatusTracker();
|
||||
tracker.RecordStopContainer(image);
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
while (iter.HasMore()) {
|
||||
mImage->GetStatusTracker().SendStopContainer(iter.GetNext(), image);
|
||||
tracker.SendStopContainer(iter.GetNext(), image);
|
||||
}
|
||||
|
||||
// This is really hacky. We need to handle the case where we start decoding,
|
||||
// block onload, but then hit an error before we get to our first frame. In
|
||||
// theory we would just hook in at OnStopDecode, but OnStopDecode is broken
|
||||
// until we fix bug 505385. OnStopContainer is actually going away at that
|
||||
// point. So for now we take advantage of the fact that OnStopContainer is
|
||||
// always fired in the decoders at the same time as OnStopDecode.
|
||||
if (mBlockingOnload) {
|
||||
mBlockingOnload = false;
|
||||
|
||||
tracker.RecordUnblockOnload();
|
||||
|
||||
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
|
||||
while (iter.HasMore()) {
|
||||
tracker.SendUnblockOnload(iter.GetNext());
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -262,6 +262,7 @@ private:
|
|||
bool mIsMultiPartChannel : 1;
|
||||
bool mGotData : 1;
|
||||
bool mIsInCache : 1;
|
||||
bool mBlockingOnload : 1;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "imgRequestProxy.h"
|
||||
#include "imgIOnloadBlocker.h"
|
||||
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIComponentManager.h"
|
||||
|
@ -789,6 +790,34 @@ void imgRequestProxy::OnStopRequest(bool lastPart)
|
|||
}
|
||||
}
|
||||
|
||||
void imgRequestProxy::BlockOnload()
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
nsCAutoString name;
|
||||
GetName(name);
|
||||
LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::BlockOnload", "name", name.get());
|
||||
#endif
|
||||
|
||||
nsCOMPtr<imgIOnloadBlocker> blocker = do_QueryInterface(mListener);
|
||||
if (blocker) {
|
||||
blocker->BlockOnload(this);
|
||||
}
|
||||
}
|
||||
|
||||
void imgRequestProxy::UnblockOnload()
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
nsCAutoString name;
|
||||
GetName(name);
|
||||
LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::UnblockOnload", "name", name.get());
|
||||
#endif
|
||||
|
||||
nsCOMPtr<imgIOnloadBlocker> blocker = do_QueryInterface(mListener);
|
||||
if (blocker) {
|
||||
blocker->UnblockOnload(this);
|
||||
}
|
||||
}
|
||||
|
||||
void imgRequestProxy::NullOutListener()
|
||||
{
|
||||
// If we have animation consumers, then they don't matter anymore
|
||||
|
|
|
@ -186,6 +186,10 @@ protected:
|
|||
void OnStartRequest();
|
||||
void OnStopRequest(bool aLastPart);
|
||||
|
||||
/* non-virtual imgIOnloadBlocker methods */
|
||||
void BlockOnload();
|
||||
void UnblockOnload();
|
||||
|
||||
/* Finish up canceling ourselves */
|
||||
void DoCancel(nsresult status);
|
||||
|
||||
|
|
|
@ -233,6 +233,10 @@ imgStatusTracker::SyncNotify(imgRequestProxy* proxy)
|
|||
if (mState & stateDecodeStarted)
|
||||
proxy->OnStartDecode();
|
||||
|
||||
// BlockOnload
|
||||
if (mState & stateBlockingOnload)
|
||||
proxy->BlockOnload();
|
||||
|
||||
if (mImage) {
|
||||
PRInt16 imageType = mImage->GetType();
|
||||
// Send frame messages (OnStartFrame, OnDataAvailable, OnStopFrame)
|
||||
|
@ -516,6 +520,7 @@ imgStatusTracker::RecordStartRequest()
|
|||
mState &= ~stateDecodeStarted;
|
||||
mState &= ~stateDecodeStopped;
|
||||
mState &= ~stateRequestStopped;
|
||||
mState &= ~stateBlockingOnload;
|
||||
|
||||
mState |= stateRequestStarted;
|
||||
}
|
||||
|
@ -548,3 +553,33 @@ imgStatusTracker::SendStopRequest(imgRequestProxy* aProxy, bool aLastPart, nsres
|
|||
aProxy->OnStopRequest(aLastPart);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
imgStatusTracker::RecordBlockOnload()
|
||||
{
|
||||
MOZ_ASSERT(!(mState & stateBlockingOnload));
|
||||
mState |= stateBlockingOnload;
|
||||
}
|
||||
|
||||
void
|
||||
imgStatusTracker::SendBlockOnload(imgRequestProxy* aProxy)
|
||||
{
|
||||
if (!aProxy->NotificationsDeferred()) {
|
||||
aProxy->BlockOnload();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
imgStatusTracker::RecordUnblockOnload()
|
||||
{
|
||||
MOZ_ASSERT(mState & stateBlockingOnload);
|
||||
mState &= ~stateBlockingOnload;
|
||||
}
|
||||
|
||||
void
|
||||
imgStatusTracker::SendUnblockOnload(imgRequestProxy* aProxy)
|
||||
{
|
||||
if (!aProxy->NotificationsDeferred()) {
|
||||
aProxy->UnblockOnload();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,8 @@ enum {
|
|||
stateDecodeStarted = PR_BIT(2),
|
||||
stateDecodeStopped = PR_BIT(3),
|
||||
stateFrameStopped = PR_BIT(4),
|
||||
stateRequestStopped = PR_BIT(5)
|
||||
stateRequestStopped = PR_BIT(5),
|
||||
stateBlockingOnload = PR_BIT(6)
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -174,6 +175,15 @@ public:
|
|||
void RecordStopRequest(bool aLastPart, nsresult aStatus);
|
||||
void SendStopRequest(imgRequestProxy* aProxy, bool aLastPart, nsresult aStatus);
|
||||
|
||||
/* non-virtual imgIOnloadBlocker methods */
|
||||
// NB: If UnblockOnload is sent, and then we are asked to replay the
|
||||
// notifications, we will not send a BlockOnload/UnblockOnload pair. This
|
||||
// is different from all the other notifications.
|
||||
void RecordBlockOnload();
|
||||
void SendBlockOnload(imgRequestProxy* aProxy);
|
||||
void RecordUnblockOnload();
|
||||
void SendUnblockOnload(imgRequestProxy* aProxy);
|
||||
|
||||
private:
|
||||
friend class imgStatusNotifyRunnable;
|
||||
friend class imgRequestNotifyRunnable;
|
||||
|
|
|
@ -75,7 +75,7 @@ function ImageListener(start_callback, stop_callback)
|
|||
|
||||
// We have to cancel the request when we're done with it to break any
|
||||
// reference loops!
|
||||
aRequest.cancel(0);
|
||||
aRequest.cancelAndForgetObserver(0);
|
||||
|
||||
this.state |= STOP_REQUEST;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче