| author | Josh Matthews <josh@joshmatthews.net> |
| Fri, 12 Oct 2012 12:11:22 -0400 | |
| changeset 110103 | a913c8c0de54 |
| parent 110102 | 423503422b51 |
| child 110104 | 3187167bb0c9 |
| push id | 23671 |
| push user | ryanvm@gmail.com |
| push date | 2012-10-13 08:36 +0000 |
| treeherder | mozilla-central@0be7bfea4744 [default view] [failures only] |
| perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
| reviewers | joe |
| bugs | 505385 |
| milestone | 19.0a1 |
| first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
| last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -59,17 +59,17 @@ class nsIScriptSecurityManager; class nsTextFragment; class nsIJSContextStack; class nsIThreadJSContextStack; class nsIParser; class nsIParserService; class nsIIOService; class nsIURI; class imgIContainer; -class imgIDecoderObserver; +class imgINotificationObserver; class imgIRequest; class imgILoader; class imgICache; class nsIImageLoadingContent; class nsIDOMHTMLFormElement; class nsIDOMDocument; class nsIConsoleService; class nsIStringBundleService; @@ -656,17 +656,17 @@ public: * @param aObserver the observer for the image load * @param aLoadFlags the load flags to use. See nsIRequest * @return the imgIRequest for the image load */ static nsresult LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument, nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer, - imgIDecoderObserver* aObserver, + imgINotificationObserver* aObserver, int32_t aLoadFlags, imgIRequest** aRequest); /** * Obtain an image loader that respects the given document/channel's privacy status. * Null document/channel arguments return the public image loader. */ static imgILoader* GetImgLoaderForDocument(nsIDocument* aDoc);
--- a/content/base/public/nsIImageLoadingContent.idl +++ b/content/base/public/nsIImageLoadingContent.idl @@ -1,14 +1,14 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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/. */ -#include "imgIDecoderObserver.idl" +#include "imgINotificationObserver.idl" interface imgIRequest; interface nsIChannel; interface nsIStreamListener; interface nsIURI; interface nsIDocument; interface nsIFrame; @@ -29,18 +29,18 @@ interface nsIFrame; * observers to check which request they are getting notifications for. * * Observers added in mid-load will not get any notifications they * missed. We should NOT freeze this interface without considering * this issue. (It could be that the image status on imgIRequest is * sufficient, when combined with the imageBlockingStatus information.) */ -[scriptable, uuid(4bf1a7c5-6edb-4191-a257-e31a90f6aa85)] -interface nsIImageLoadingContent : imgIDecoderObserver +[scriptable, builtinclass, uuid(497bfb9b-d996-4d1e-a647-8137b0cfc876)] +interface nsIImageLoadingContent : imgINotificationObserver { /** * Request types. Image loading content nodes attempt to do atomic * image changes when the image url is changed. This means that * when the url changes the new image load will start, but the old * image will remain the "current" request until the new image is * fully loaded. At that point, the old "current" request will be * discarded and the "pending" request will become "current". @@ -70,24 +70,24 @@ interface nsIImageLoadingContent : imgID * Notifications from ongoing image loads will be passed to all * registered observers. Notifications for all request types, * current and pending, will be passed through. * * @param aObserver the observer to register * * @throws NS_ERROR_OUT_OF_MEMORY */ - void addObserver(in imgIDecoderObserver aObserver); + void addObserver(in imgINotificationObserver aObserver); /** * Used to unregister an image decoder observer. * * @param aObserver the observer to unregister */ - void removeObserver(in imgIDecoderObserver aObserver); + void removeObserver(in imgINotificationObserver aObserver); /** * Accessor to get the image requests * * @param aRequestType a value saying which request is wanted * * @return the imgIRequest object (may be null, even when no error * is thrown)
--- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -46,17 +46,17 @@ #include "nsIContentSink.h" #include "nsContentList.h" #include "nsIHTMLDocument.h" #include "nsIDOMHTMLFormElement.h" #include "nsIDOMHTMLElement.h" #include "nsIForm.h" #include "nsIFormControl.h" #include "nsGkAtoms.h" -#include "imgIDecoderObserver.h" +#include "imgINotificationObserver.h" #include "imgIRequest.h" #include "imgIContainer.h" #include "imgILoader.h" #include "nsDocShellCID.h" #include "nsIImageLoadingContent.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" #include "nsILoadGroup.h" @@ -2729,17 +2729,17 @@ nsContentUtils::IsImageInCache(nsIURI* a nsresult rv = cache->FindEntryProperties(aURI, getter_AddRefs(props)); return (NS_SUCCEEDED(rv) && props); } // static nsresult nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument, nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer, - imgIDecoderObserver* aObserver, int32_t aLoadFlags, + imgINotificationObserver* aObserver, int32_t aLoadFlags, imgIRequest** aRequest) { NS_PRECONDITION(aURI, "Must have a URI"); NS_PRECONDITION(aLoadingDocument, "Must have a document"); NS_PRECONDITION(aLoadingPrincipal, "Must have a principal"); NS_PRECONDITION(aRequest, "Null out param"); imgILoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument); @@ -2772,17 +2772,17 @@ nsContentUtils::LoadImage(nsIURI* aURI, // XXXbz using "documentURI" for the initialDocumentURI is not quite // right, but the best we can do here... return imgLoader->LoadImage(aURI, /* uri to load */ documentURI, /* initialDocumentURI */ aReferrer, /* referrer */ aLoadingPrincipal, /* loading principal */ loadGroup, /* loadgroup */ - aObserver, /* imgIDecoderObserver */ + aObserver, /* imgINotificationObserver */ aLoadingDocument, /* uniquification key */ aLoadFlags, /* load flags */ nullptr, /* cache key */ nullptr, /* existing request*/ channelPolicy, /* CSP info */ aRequest); }
--- a/content/base/src/nsGenConImageContent.cpp +++ b/content/base/src/nsGenConImageContent.cpp @@ -43,21 +43,20 @@ public: private: virtual ~nsGenConImageContent(); public: NS_DECL_ISUPPORTS_INHERITED }; -NS_IMPL_ISUPPORTS_INHERITED4(nsGenConImageContent, +NS_IMPL_ISUPPORTS_INHERITED3(nsGenConImageContent, nsXMLElement, nsIImageLoadingContent, - imgIContainerObserver, - imgIDecoderObserver, + imgINotificationObserver, imgIOnloadBlocker) nsresult NS_NewGenConImageContent(nsIContent** aResult, already_AddRefed<nsINodeInfo> aNodeInfo, imgIRequest* aImageRequest) { NS_PRECONDITION(aImageRequest, "Must have request!"); nsGenConImageContent *it = new nsGenConImageContent(aNodeInfo);
--- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -117,122 +117,66 @@ nsImageLoadingContent::~nsImageLoadingCo observer = next) { \ next = observer->mNext; \ if (observer->mObserver) { \ observer->mObserver->func_; \ } \ } \ PR_END_MACRO - /* - * imgIContainerObserver impl - */ -NS_IMETHODIMP -nsImageLoadingContent::FrameChanged(imgIRequest* aRequest, - imgIContainer* aContainer, - const nsIntRect* aDirtyRect) -{ - LOOP_OVER_OBSERVERS(FrameChanged(aRequest, aContainer, aDirtyRect)); - return NS_OK; -} - -/* - * imgIDecoderObserver impl + * imgINotificationObserver impl */ NS_IMETHODIMP -nsImageLoadingContent::OnStartRequest(imgIRequest* aRequest) -{ - NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); - - LOOP_OVER_OBSERVERS(OnStartRequest(aRequest)); - return NS_OK; -} - -NS_IMETHODIMP -nsImageLoadingContent::OnStartDecode(imgIRequest* aRequest) +nsImageLoadingContent::Notify(imgIRequest* aRequest, + int32_t aType, + const nsIntRect* aData) { - NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); + if (aType == imgINotificationObserver::IS_ANIMATED) { + return OnImageIsAnimated(aRequest); + } - LOOP_OVER_OBSERVERS(OnStartDecode(aRequest)); - return NS_OK; -} + if (aType == imgINotificationObserver::STOP_DECODE) { + // We should definitely have a request here + NS_ABORT_IF_FALSE(aRequest, "no request?"); -NS_IMETHODIMP -nsImageLoadingContent::OnStartContainer(imgIRequest* aRequest, - imgIContainer* aContainer) -{ + NS_PRECONDITION(aRequest == mCurrentRequest || aRequest == mPendingRequest, + "Unknown request"); + } + NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); - LOOP_OVER_OBSERVERS(OnStartContainer(aRequest, aContainer)); - - // Have to check for state changes here, since we might have been in - // the LOADING state before. - UpdateImageState(true); - return NS_OK; -} - -NS_IMETHODIMP -nsImageLoadingContent::OnStartFrame(imgIRequest* aRequest, - uint32_t aFrame) -{ - NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); - - LOOP_OVER_OBSERVERS(OnStartFrame(aRequest, aFrame)); - return NS_OK; -} + if (aType != imgINotificationObserver::FRAME_CHANGED) { + LOOP_OVER_OBSERVERS(Notify(aRequest, aType, aData)); + } -NS_IMETHODIMP -nsImageLoadingContent::OnDataAvailable(imgIRequest* aRequest, - bool aCurrentFrame, - const nsIntRect* aRect) -{ - NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); - - LOOP_OVER_OBSERVERS(OnDataAvailable(aRequest, aCurrentFrame, aRect)); - return NS_OK; -} + if (aType == imgINotificationObserver::START_CONTAINER) { + // Have to check for state changes here, since we might have been in + // the LOADING state before. + UpdateImageState(true); + } -NS_IMETHODIMP -nsImageLoadingContent::OnStopFrame(imgIRequest* aRequest, - uint32_t aFrame) -{ - NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); + if (aType == imgINotificationObserver::STOP_DECODE) { + uint32_t reqStatus; + aRequest->GetImageStatus(&reqStatus); + nsresult status = + reqStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK; + return OnStopDecode(aRequest, status); + } - LOOP_OVER_OBSERVERS(OnStopFrame(aRequest, aFrame)); - return NS_OK; -} - -NS_IMETHODIMP -nsImageLoadingContent::OnStopContainer(imgIRequest* aRequest, - imgIContainer* aContainer) -{ - NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); - - LOOP_OVER_OBSERVERS(OnStopContainer(aRequest, aContainer)); return NS_OK; } // Warning - This isn't actually fired when decode is complete. Rather, it's // fired when load is complete. See bug 505385, and in the mean time use // OnStopContainer. -NS_IMETHODIMP +nsresult nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest, - nsresult aStatus, - const PRUnichar* aStatusArg) + nsresult aStatus) { - NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); - - // We should definitely have a request here - NS_ABORT_IF_FALSE(aRequest, "no request?"); - - NS_PRECONDITION(aRequest == mCurrentRequest || aRequest == mPendingRequest, - "Unknown request"); - LOOP_OVER_OBSERVERS(OnStopDecode(aRequest, aStatus, aStatusArg)); - // XXXbholley - When we fix bug 505385, everything here should go in // OnStopRequest. // Our state may change. Watch it. AutoStateChanger changer(this, true); // If the pending request is loaded, switch to it. if (aRequest == mPendingRequest) { @@ -279,48 +223,28 @@ nsImageLoadingContent::OnStopDecode(imgI } nsCOMPtr<nsINode> thisNode = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this)); nsSVGEffects::InvalidateDirectRenderingObservers(thisNode->AsElement()); return NS_OK; } -NS_IMETHODIMP -nsImageLoadingContent::OnStopRequest(imgIRequest* aRequest, bool aLastPart) -{ - NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); - - LOOP_OVER_OBSERVERS(OnStopRequest(aRequest, aLastPart)); - - return NS_OK; -} - -NS_IMETHODIMP +nsresult nsImageLoadingContent::OnImageIsAnimated(imgIRequest *aRequest) { bool* requestFlag = GetRegisteredFlagForRequest(aRequest); if (requestFlag) { nsLayoutUtils::RegisterImageRequest(GetFramePresContext(), aRequest, requestFlag); } return NS_OK; } -NS_IMETHODIMP -nsImageLoadingContent::OnDiscard(imgIRequest *aRequest) -{ - NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); - - LOOP_OVER_OBSERVERS(OnDiscard(aRequest)); - - return NS_OK; -} - /* * nsIImageLoadingContent impl */ NS_IMETHODIMP nsImageLoadingContent::GetLoadingEnabled(bool *aLoadingEnabled) { NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); @@ -346,17 +270,17 @@ nsImageLoadingContent::GetImageBlockingS NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); NS_PRECONDITION(aStatus, "Null out param"); *aStatus = mImageBlockingStatus; return NS_OK; } NS_IMETHODIMP -nsImageLoadingContent::AddObserver(imgIDecoderObserver* aObserver) +nsImageLoadingContent::AddObserver(imgINotificationObserver* aObserver) { NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); NS_ENSURE_ARG_POINTER(aObserver); if (!mObserverList.mObserver) { mObserverList.mObserver = aObserver; // Don't touch the linking of the list! @@ -374,17 +298,17 @@ nsImageLoadingContent::AddObserver(imgID if (! observer->mNext) { return NS_ERROR_OUT_OF_MEMORY; } return NS_OK; } NS_IMETHODIMP -nsImageLoadingContent::RemoveObserver(imgIDecoderObserver* aObserver) +nsImageLoadingContent::RemoveObserver(imgINotificationObserver* aObserver) { NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); NS_ENSURE_ARG_POINTER(aObserver); if (mObserverList.mObserver == aObserver) { mObserverList.mObserver = nullptr; // Don't touch the linking of the list!
--- a/content/base/src/nsImageLoadingContent.h +++ b/content/base/src/nsImageLoadingContent.h @@ -8,18 +8,17 @@ * A base class which implements nsIImageLoadingContent and can be * subclassed by various content nodes that want to provide image * loading functionality (eg <img>, <object>, etc). */ #ifndef nsImageLoadingContent_h__ #define nsImageLoadingContent_h__ -#include "imgIContainerObserver.h" -#include "imgIDecoderObserver.h" +#include "imgINotificationObserver.h" #include "imgIOnloadBlocker.h" #include "mozilla/CORSMode.h" #include "nsCOMPtr.h" #include "nsContentUtils.h" // NS_CONTENT_DELETE_LIST_MEMBER #include "nsEventStates.h" #include "nsIImageLoadingContent.h" #include "nsIRequest.h" @@ -31,18 +30,17 @@ class nsIIOService; class nsImageLoadingContent : public nsIImageLoadingContent, public imgIOnloadBlocker { /* METHODS */ public: nsImageLoadingContent(); virtual ~nsImageLoadingContent(); - NS_DECL_IMGICONTAINEROBSERVER - NS_DECL_IMGIDECODEROBSERVER + NS_DECL_IMGINOTIFICATIONOBSERVER NS_DECL_NSIIMAGELOADINGCONTENT NS_DECL_IMGIONLOADBLOCKER protected: /** * LoadImage is called by subclasses when the appropriate * attributes (eg 'src' for <img> tags) change. The string passed * in is the new uri string; this consolidates the code for getting @@ -156,34 +154,37 @@ protected: */ virtual mozilla::CORSMode GetCORSMode(); // Subclasses are *required* to call BindToTree/UnbindFromTree. void BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers); void UnbindFromTree(bool aDeep, bool aNullParent); + nsresult OnStopDecode(imgIRequest* aRequest, nsresult aStatus); + nsresult OnImageIsAnimated(imgIRequest *aRequest); + private: /** * Struct used to manage the image observers. */ struct ImageObserver { - ImageObserver(imgIDecoderObserver* aObserver) : + ImageObserver(imgINotificationObserver* aObserver) : mObserver(aObserver), mNext(nullptr) { MOZ_COUNT_CTOR(ImageObserver); } ~ImageObserver() { MOZ_COUNT_DTOR(ImageObserver); NS_CONTENT_DELETE_LIST_MEMBER(ImageObserver, this, mNext); } - nsCOMPtr<imgIDecoderObserver> mObserver; + nsCOMPtr<imgINotificationObserver> mObserver; ImageObserver* mNext; }; /** * Struct to report state changes */ struct AutoStateChanger { AutoStateChanger(nsImageLoadingContent* aImageContent,
--- a/content/base/src/nsObjectLoadingContent.h +++ b/content/base/src/nsObjectLoadingContent.h @@ -93,23 +93,16 @@ class nsObjectLoadingContent : public ns NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER NS_DECL_NSIFRAMELOADEROWNER NS_DECL_NSIOBJECTLOADINGCONTENT NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSICHANNELEVENTSINK -#ifdef HAVE_CPP_AMBIGUITY_RESOLVING_USING - // Fix gcc compile warnings - using nsImageLoadingContent::OnStartRequest; - using nsImageLoadingContent::OnDataAvailable; - using nsImageLoadingContent::OnStopRequest; -#endif - /** * Object state. This is a bitmask of NS_EVENT_STATEs epresenting the * current state of the object. */ nsEventStates ObjectState() const; ObjectType Type() { return mType; }
--- a/content/html/content/src/nsHTMLImageElement.cpp +++ b/content/html/content/src/nsHTMLImageElement.cpp @@ -24,17 +24,17 @@ #include "nsGUIEvent.h" #include "nsContentPolicyUtils.h" #include "nsIDOMWindow.h" #include "nsFocusManager.h" #include "imgIContainer.h" #include "imgILoader.h" #include "imgIRequest.h" -#include "imgIDecoderObserver.h" +#include "imgINotificationObserver.h" #include "nsILoadGroup.h" #include "nsRuleData.h" #include "nsIJSContextStack.h" #include "nsIDOMHTMLMapElement.h" #include "nsEventDispatcher.h" @@ -84,23 +84,22 @@ nsHTMLImageElement::~nsHTMLImageElement( NS_IMPL_ADDREF_INHERITED(nsHTMLImageElement, nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsHTMLImageElement, nsGenericElement) DOMCI_NODE_DATA(HTMLImageElement, nsHTMLImageElement) // QueryInterface implementation for nsHTMLImageElement NS_INTERFACE_TABLE_HEAD(nsHTMLImageElement) - NS_HTML_CONTENT_INTERFACE_TABLE6(nsHTMLImageElement, + NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLImageElement, nsIDOMHTMLImageElement, nsIJSNativeInitializer, - imgIDecoderObserver, nsIImageLoadingContent, - imgIContainerObserver, - imgIOnloadBlocker) + imgIOnloadBlocker, + imgINotificationObserver) NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLImageElement, nsGenericHTMLElement) NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLImageElement) NS_IMPL_ELEMENT_CLONE(nsHTMLImageElement)
--- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -637,23 +637,22 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_ADDREF_INHERITED(nsHTMLInputElement, nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsHTMLInputElement, nsGenericElement) DOMCI_NODE_DATA(HTMLInputElement, nsHTMLInputElement) // QueryInterface implementation for nsHTMLInputElement NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLInputElement) - NS_HTML_CONTENT_INTERFACE_TABLE9(nsHTMLInputElement, + NS_HTML_CONTENT_INTERFACE_TABLE8(nsHTMLInputElement, nsIDOMHTMLInputElement, nsITextControlElement, nsIPhonetic, - imgIDecoderObserver, + imgINotificationObserver, nsIImageLoadingContent, - imgIContainerObserver, imgIOnloadBlocker, nsIDOMNSEditableElement, nsIConstraintValidation) NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLInputElement, nsGenericHTMLFormElement) NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLInputElement) // nsIConstraintValidation
--- a/content/html/content/src/nsHTMLObjectElement.cpp +++ b/content/html/content/src/nsHTMLObjectElement.cpp @@ -180,24 +180,23 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_ADDREF_INHERITED(nsHTMLObjectElement, nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsHTMLObjectElement, nsGenericElement) DOMCI_NODE_DATA(HTMLObjectElement, nsHTMLObjectElement) NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLObjectElement) NS_HTML_CONTENT_INTERFACE_TABLE_BEGIN(nsHTMLObjectElement) NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIDOMHTMLObjectElement) - NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, imgIDecoderObserver) + NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, imgINotificationObserver) NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIRequestObserver) NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIStreamListener) 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) NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIConstraintValidation) NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIDOMGetSVGDocument) NS_OFFSET_AND_INTERFACE_TABLE_END NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLObjectElement, nsGenericHTMLFormElement) NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLObjectElement)
--- a/content/html/content/src/nsHTMLSharedObjectElement.cpp +++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp @@ -229,19 +229,18 @@ nsHTMLSharedObjectElement::GetClassInfoI } NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLSharedObjectElement) NS_HTML_CONTENT_INTERFACE_TABLE_AMBIGUOUS_BEGIN(nsHTMLSharedObjectElement, nsIDOMHTMLAppletElement) NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, nsIRequestObserver) NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, nsIStreamListener) NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, nsIFrameLoaderOwner) - NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, imgIContainerObserver) NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, nsIObjectLoadingContent) - NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, imgIDecoderObserver) + NS_INTERFACE_TABLE_ENTRY(nsHTMLSharedObjectElement, imgINotificationObserver) 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 NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE_AMBIGUOUS(nsHTMLSharedObjectElement, nsGenericHTMLElement, nsIDOMHTMLAppletElement)
--- a/content/html/content/test/test_bug389797.html +++ b/content/html/content/test/test_bug389797.html @@ -67,17 +67,17 @@ function HTML_TAG(aTagName, aImplClass) if (arguments.length > 3) { for (i = 0; i < arguments[3].length; ++i) { interfacesNonClassinfo[aTagName].push(arguments[3][i]); } } } const objectIfaces = [ - "imgIDecoderObserver", "nsIRequestObserver", "nsIStreamListener", + "imgINotificationObserver", "nsIRequestObserver", "nsIStreamListener", "nsIFrameLoaderOwner", "nsIObjectLoadingContent", "nsIInterfaceRequestor", "nsIChannelEventSink" ]; var objectIfaces2 = []; for each (var iface in objectIfaces) { objectIfaces2.push(iface); } @@ -155,19 +155,19 @@ HTML_TAG("head", "Head"); HTML_TAG("header", "") HTML_TAG("hgroup", "") HTML_TAG("hr", "HR"); HTML_TAG("html", "Html"); HTML_TAG("i", ""); HTML_TAG("iframe", "IFrame", [ "nsIDOMGetSVGDocument", "nsIDOMMozBrowserFrame" ], [ "nsIFrameLoaderOwner" ]); HTML_TAG("image", "Span"); -HTML_TAG("img", "Image", [], [ "imgIDecoderObserver", +HTML_TAG("img", "Image", [], [ "imgINotificationObserver", "nsIImageLoadingContent" ]); -HTML_TAG("input", "Input", [], [ "imgIDecoderObserver", +HTML_TAG("input", "Input", [], [ "imgINotificationObserver", "nsIImageLoadingContent", "nsIDOMNSEditableElement" ]); HTML_TAG("ins", "Mod"); HTML_TAG("kbd", ""); HTML_TAG("keygen", "Span"); HTML_TAG("label", "Label"); HTML_TAG("legend", "Legend"); HTML_TAG("li", "LI");
--- a/content/html/document/src/ImageDocument.cpp +++ b/content/html/document/src/ImageDocument.cpp @@ -13,17 +13,17 @@ #include "nsIDOMEvent.h" #include "nsIDOMKeyEvent.h" #include "nsIDOMMouseEvent.h" #include "nsIDOMEventListener.h" #include "nsGkAtoms.h" #include "imgIRequest.h" #include "imgILoader.h" #include "imgIContainer.h" -#include "nsStubImageDecoderObserver.h" +#include "imgINotificationObserver.h" #include "nsIPresShell.h" #include "nsPresContext.h" #include "nsStyleContext.h" #include "nsAutoPtr.h" #include "nsStyleSet.h" #include "nsIChannel.h" #include "nsIContentPolicy.h" #include "nsContentPolicyUtils.h" @@ -59,17 +59,17 @@ public: virtual ~ImageListener(); /* nsIRequestObserver */ NS_IMETHOD OnStartRequest(nsIRequest* request, nsISupports *ctxt); }; class ImageDocument : public MediaDocument , public nsIImageDocument - , public nsStubImageDecoderObserver + , public imgINotificationObserver , public nsIDOMEventListener { public: ImageDocument(); virtual ~ImageDocument(); NS_DECL_ISUPPORTS_INHERITED @@ -84,22 +84,17 @@ public: nsIContentSink* aSink = nullptr); virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject); virtual void Destroy(); virtual void OnPageShow(bool aPersisted, nsIDOMEventTarget* aDispatchStartTarget); NS_DECL_NSIIMAGEDOCUMENT - - // imgIDecoderObserver (override nsStubImageDecoderObserver) - NS_IMETHOD OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage); - NS_IMETHOD OnStopContainer(imgIRequest* aRequest, imgIContainer* aImage); - NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult aStatus, const PRUnichar *aStatusArg); - NS_IMETHOD OnDiscard(imgIRequest *aRequest); + NS_DECL_IMGINOTIFICATIONOBSERVER // nsIDOMEventListener NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ImageDocument, MediaDocument) friend class ImageListener; @@ -118,16 +113,19 @@ protected: float GetRatio() { return NS_MIN((float)mVisibleWidth / mImageWidth, (float)mVisibleHeight / mImageHeight); } void ResetZoomLevel(); float GetZoomLevel(); + nsresult OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage); + nsresult OnStopDecode(imgIRequest *aRequest, nsresult aStatus); + nsCOMPtr<nsIContent> mImageContent; int32_t mVisibleWidth; int32_t mVisibleHeight; int32_t mImageWidth; int32_t mImageHeight; bool mResizeImageByDefault; @@ -233,18 +231,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_ADDREF_INHERITED(ImageDocument, MediaDocument) NS_IMPL_RELEASE_INHERITED(ImageDocument, MediaDocument) DOMCI_NODE_DATA(ImageDocument, ImageDocument) NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(ImageDocument) NS_HTML_DOCUMENT_INTERFACE_TABLE_BEGIN(ImageDocument) NS_INTERFACE_TABLE_ENTRY(ImageDocument, nsIImageDocument) - NS_INTERFACE_TABLE_ENTRY(ImageDocument, imgIDecoderObserver) - NS_INTERFACE_TABLE_ENTRY(ImageDocument, imgIContainerObserver) + NS_INTERFACE_TABLE_ENTRY(ImageDocument, imgINotificationObserver) NS_INTERFACE_TABLE_ENTRY(ImageDocument, nsIDOMEventListener) NS_OFFSET_AND_INTERFACE_TABLE_END NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ImageDocument) NS_INTERFACE_MAP_END_INHERITING(MediaDocument) nsresult @@ -504,46 +501,70 @@ ImageDocument::ToggleImageSize() ResetZoomLevel(); ShrinkToFit(); } return NS_OK; } NS_IMETHODIMP +ImageDocument::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData) +{ + if (aType == imgINotificationObserver::START_CONTAINER) { + nsCOMPtr<imgIContainer> image; + aRequest->GetImage(getter_AddRefs(image)); + return OnStartContainer(aRequest, image); + } + + if (aType == imgINotificationObserver::STOP_CONTAINER) { + if (mImageContent) { + // Update the background-color of the image only after the + // image has been decoded to prevent flashes of just the + // background-color. + mImageContent->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, + NS_LITERAL_STRING("decoded"), true); + } + } + + if (aType == imgINotificationObserver::DISCARD) { + // mImageContent can be null if the document is already destroyed + if (mImageContent) { + // Remove any decoded-related styling when the image is unloaded. + mImageContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, + true); + } + } + + if (aType == imgINotificationObserver::STOP_DECODE) { + uint32_t reqStatus; + aRequest->GetImageStatus(&reqStatus); + nsresult status = + reqStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK; + return OnStopDecode(aRequest, status); + } + + return NS_OK; +} + +nsresult ImageDocument::OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage) { aImage->GetWidth(&mImageWidth); aImage->GetHeight(&mImageHeight); nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableMethod(this, &ImageDocument::DefaultCheckOverflowing); nsContentUtils::AddScriptRunner(runnable); UpdateTitleAndCharset(); return NS_OK; } -NS_IMETHODIMP -ImageDocument::OnStopContainer(imgIRequest* aRequest, imgIContainer* aImage) -{ - if (mImageContent) { - // Update the background-color of the image only after the - // image has been decoded to prevent flashes of just the - // background-color. - mImageContent->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, - NS_LITERAL_STRING("decoded"), true); - } - - return NS_OK; -} - -NS_IMETHODIMP +nsresult ImageDocument::OnStopDecode(imgIRequest *aRequest, - nsresult aStatus, - const PRUnichar *aStatusArg) + nsresult aStatus) { UpdateTitleAndCharset(); // mImageContent can be null if the document is already destroyed if (NS_FAILED(aStatus) && mStringBundle && mImageContent) { nsAutoCString src; mDocumentURI->GetSpec(src); NS_ConvertUTF8toUTF16 srcString(src); @@ -555,28 +576,16 @@ ImageDocument::OnStopDecode(imgIRequest mImageContent->SetAttr(kNameSpaceID_None, nsGkAtoms::alt, errorMsg, false); } return NS_OK; } NS_IMETHODIMP -ImageDocument::OnDiscard(imgIRequest *aRequest) -{ - // mImageContent can be null if the document is already destroyed - if (mImageContent) { - // Remove any decoded-related styling when the image is unloaded. - mImageContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class, - true); - } - return NS_OK; -} - -NS_IMETHODIMP ImageDocument::HandleEvent(nsIDOMEvent* aEvent) { nsAutoString eventType; aEvent->GetType(eventType); if (eventType.EqualsLiteral("resize")) { CheckOverflowing(false); } else if (eventType.EqualsLiteral("click") && mClickResizingEnabled) {
--- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/nsSVGFilters.cpp @@ -5500,17 +5500,17 @@ NS_IMPL_RELEASE_INHERITED(nsSVGFEImageEl DOMCI_NODE_DATA(SVGFEImageElement, nsSVGFEImageElement) NS_INTERFACE_TABLE_HEAD(nsSVGFEImageElement) NS_NODE_INTERFACE_TABLE9(nsSVGFEImageElement, nsIDOMNode, nsIDOMElement, nsIDOMSVGElement, nsIDOMSVGFilterPrimitiveStandardAttributes, nsIDOMSVGFEImageElement, nsIDOMSVGURIReference, - imgIDecoderObserver, nsIImageLoadingContent, + imgINotificationObserver, nsIImageLoadingContent, imgIOnloadBlocker) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEImageElement) NS_INTERFACE_MAP_END_INHERITING(nsSVGFEImageElementBase) //---------------------------------------------------------------------- // Implementation nsSVGFEImageElement::nsSVGFEImageElement(already_AddRefed<nsINodeInfo> aNodeInfo) @@ -5751,53 +5751,37 @@ nsSVGFEImageElement::GetPreserveAspectRa nsSVGElement::StringAttributesInfo nsSVGFEImageElement::GetStringInfo() { return StringAttributesInfo(mStringAttributes, sStringInfo, ArrayLength(sStringInfo)); } //---------------------------------------------------------------------- -// imgIDecoderObserver methods - -NS_IMETHODIMP -nsSVGFEImageElement::OnStopDecode(imgIRequest *aRequest, - nsresult status, - const PRUnichar *statusArg) -{ - nsresult rv = - nsImageLoadingContent::OnStopDecode(aRequest, status, statusArg); - Invalidate(); - return rv; -} +// imgINotificationObserver methods NS_IMETHODIMP -nsSVGFEImageElement::FrameChanged(imgIRequest* aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect) -{ - nsresult rv = - nsImageLoadingContent::FrameChanged(aRequest, aContainer, aDirtyRect); - Invalidate(); - return rv; -} - -NS_IMETHODIMP -nsSVGFEImageElement::OnStartContainer(imgIRequest *aRequest, - imgIContainer *aContainer) -{ - nsresult rv = - nsImageLoadingContent::OnStartContainer(aRequest, aContainer); - - // Request a decode - NS_ABORT_IF_FALSE(aContainer, "who sent the notification then?"); - aContainer->StartDecoding(); - - // We have a size - invalidate - Invalidate(); +nsSVGFEImageElement::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData) +{ + nsresult rv = nsImageLoadingContent::Notify(aRequest, aType, aData); + + if (aType == imgINotificationObserver::START_CONTAINER) { + // Request a decode + nsCOMPtr<imgIContainer> container; + aRequest->GetImage(getter_AddRefs(container)); + NS_ABORT_IF_FALSE(container, "who sent the notification then?"); + container->StartDecoding(); + } + + if (aType == imgINotificationObserver::STOP_DECODE || + aType == imgINotificationObserver::FRAME_CHANGED || + aType == imgINotificationObserver::START_CONTAINER) { + Invalidate(); + } + return rv; } //---------------------------------------------------------------------- // helper methods void nsSVGFEImageElement::Invalidate()
--- a/content/svg/content/src/nsSVGFilters.h +++ b/content/svg/content/src/nsSVGFilters.h @@ -262,26 +262,17 @@ public: virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, bool aNotify); virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers); virtual void UnbindFromTree(bool aDeep, bool aNullParent); virtual nsEventStates IntrinsicState() const; - // imgIDecoderObserver - NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status, - const PRUnichar *statusArg); - // imgIContainerObserver - NS_IMETHOD FrameChanged(imgIRequest* aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect); - // imgIContainerObserver - NS_IMETHOD OnStartContainer(imgIRequest *aRequest, - imgIContainer *aContainer); + NS_IMETHODIMP Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData); void MaybeLoadSVGImage(); virtual nsXPCClassInfo* GetClassInfo(); virtual nsIDOMNode* AsDOMNode() { return this; } private: // Invalidate users of the filter containing this element.
--- a/content/svg/content/src/nsSVGImageElement.cpp +++ b/content/svg/content/src/nsSVGImageElement.cpp @@ -5,17 +5,17 @@ #include "mozilla/Util.h" #include "nsSVGImageElement.h" #include "nsCOMPtr.h" #include "nsIURI.h" #include "nsNetUtil.h" #include "imgIContainer.h" -#include "imgIDecoderObserver.h" +#include "imgINotificationObserver.h" #include "gfxContext.h" using namespace mozilla; nsSVGElement::LengthInfo nsSVGImageElement::sLengthInfo[4] = { { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X }, { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y }, @@ -37,17 +37,17 @@ NS_IMPL_ADDREF_INHERITED(nsSVGImageEleme NS_IMPL_RELEASE_INHERITED(nsSVGImageElement,nsSVGImageElementBase) DOMCI_NODE_DATA(SVGImageElement, nsSVGImageElement) NS_INTERFACE_TABLE_HEAD(nsSVGImageElement) NS_NODE_INTERFACE_TABLE9(nsSVGImageElement, nsIDOMNode, nsIDOMElement, nsIDOMSVGElement, nsIDOMSVGTests, nsIDOMSVGImageElement, - nsIDOMSVGURIReference, imgIDecoderObserver, + nsIDOMSVGURIReference, imgINotificationObserver, nsIImageLoadingContent, imgIOnloadBlocker) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGImageElement) NS_INTERFACE_MAP_END_INHERITING(nsSVGImageElementBase) //---------------------------------------------------------------------- // Implementation nsSVGImageElement::nsSVGImageElement(already_AddRefed<nsINodeInfo> aNodeInfo)
--- a/image/public/Makefile.in +++ b/image/public/Makefile.in @@ -18,15 +18,17 @@ EXPORTS = ImageLogging.h XPIDLSRCS = \ imgICache.idl \ imgIContainer.idl \ imgIContainerDebug.idl \ imgIContainerObserver.idl \ imgIDecoderObserver.idl \ imgIEncoder.idl \ imgILoader.idl \ + imgINotificationObserver.idl \ imgIOnloadBlocker.idl \ imgIRequest.idl \ + imgIScriptedNotificationObserver.idl \ imgITools.idl \ $(NULL) include $(topsrcdir)/config/rules.mk
--- a/image/public/imgILoader.idl +++ b/image/public/imgILoader.idl @@ -1,17 +1,17 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * 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/. */ #include "nsISupports.idl" -interface imgIDecoderObserver; +interface imgINotificationObserver; interface imgIRequest; interface nsIChannel; interface nsILoadGroup; interface nsIPrincipal; interface nsIStreamListener; interface nsIURI; @@ -56,17 +56,17 @@ interface imgILoader : nsISupports * make sure to Cancel() the resulting request before the observer * goes away. */ imgIRequest loadImage(in nsIURI aURI, in nsIURI aInitialDocumentURL, in nsIURI aReferrerURI, in nsIPrincipal aLoadingPrincipal, in nsILoadGroup aLoadGroup, - in imgIDecoderObserver aObserver, + in imgINotificationObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, in nsISupports cacheKey, in imgIRequest aRequest, in nsIChannelPolicy channelPolicy); /** * Start the load and decode of an image. @@ -81,12 +81,12 @@ interface imgILoader : nsISupports * not interested in the data. @aChannel will be canceled for you in * this case. * * libpr0n does NOT keep a strong ref to the observer; this prevents * reference cycles. This means that callers of loadImageWithChannel should * make sure to Cancel() the resulting request before the observer goes away. */ imgIRequest loadImageWithChannel(in nsIChannel aChannel, - in imgIDecoderObserver aObserver, + in imgINotificationObserver aObserver, in nsISupports cx, out nsIStreamListener aListener); };
new file mode 100644 --- /dev/null +++ b/image/public/imgINotificationObserver.idl @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#include "nsISupports.idl" + +interface imgIRequest; + +%{C++ +#include "nsRect.h" +%} + +[ptr] native nsIntRect(nsIntRect); + +[scriptable, builtinclass, uuid(bf9ed307-02a5-4732-b3eb-659bde5de84f)] +interface imgINotificationObserver : nsISupports +{ + const long START_REQUEST = 1; + const long START_CONTAINER = 2; + const long START_FRAME = 3; + const long DATA_AVAILABLE = 4; + const long STOP_FRAME = 5; + const long STOP_CONTAINER = 6; + const long STOP_DECODE = 7; + const long DISCARD = 8; + const long IS_ANIMATED = 9; + const long FRAME_CHANGED = 10; + const long STOP_REQUEST = 11; + const long START_DECODE = 12; + + [noscript] void notify(in imgIRequest aProxy, in long aType, [const] in nsIntRect aRect); +};
--- a/image/public/imgIRequest.idl +++ b/image/public/imgIRequest.idl @@ -3,28 +3,28 @@ * 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/. */ #include "nsISupports.idl" #include "nsIRequest.idl" interface imgIContainer; -interface imgIDecoderObserver; +interface imgINotificationObserver; interface nsIURI; interface nsIPrincipal; /** * imgIRequest interface * * @author Stuart Parmenter <stuart@mozilla.com> * @version 0.1 * @see imagelib2 */ -[scriptable, uuid(a5a785a8-9881-11e1-aaff-001fbc092072)] +[scriptable, uuid(3ea9fc87-2e97-45bf-b373-d1dd253a0b5e)] interface imgIRequest : nsIRequest { /** * the image container... * @return the image object associated with the request. * @attention NEED DOCS */ readonly attribute imgIContainer image; @@ -77,27 +77,27 @@ interface imgIRequest : nsIRequest /** * The URI the image load was started with. Note that this might not be the * actual URI for the image (e.g. if HTTP redirects happened during the * load). */ readonly attribute nsIURI URI; - readonly attribute imgIDecoderObserver decoderObserver; + readonly attribute imgINotificationObserver notificationObserver; readonly attribute string mimeType; /** * Clone this request; the returned request will have aObserver as the * observer. aObserver will be notified synchronously (before the clone() * call returns) with all the notifications that have already been dispatched * for this image load. */ - imgIRequest clone(in imgIDecoderObserver aObserver); + imgIRequest clone(in imgINotificationObserver aObserver); /** * The principal gotten from the channel the image was loaded from. */ readonly attribute nsIPrincipal imagePrincipal; /** * Whether the request is multipart (ie, multipart/x-mixed-replace)
new file mode 100644 --- /dev/null +++ b/image/public/imgIScriptedNotificationObserver.idl @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#include "nsISupports.idl" + +interface imgIRequest; + +[scriptable, uuid(1296bf6c-6067-424b-ba8e-389ec89ee48b)] +interface imgIScriptedNotificationObserver : nsISupports +{ + void startRequest(in imgIRequest aRequest); + void startContainer(in imgIRequest aRequest); + void startFrame(in imgIRequest aRequest); + void startDecode(in imgIRequest aRequest); + void dataAvailable(in imgIRequest aRequest); + void stopFrame(in imgIRequest aRequest); + void stopContainer(in imgIRequest aRequest); + void stopDecode(in imgIRequest aRequest); + void stopRequest(in imgIRequest aRequest); + void discard(in imgIRequest aRequest); + void isAnimated(in imgIRequest aRequest); + void frameChanged(in imgIRequest aRequest); +};
--- a/image/public/imgITools.idl +++ b/image/public/imgITools.idl @@ -6,18 +6,20 @@ #include "nsISupports.idl" interface nsIInputStream; interface imgIContainer; interface imgILoader; interface imgICache; interface nsIDOMDocument; +interface imgIScriptedNotificationObserver; +interface imgINotificationObserver; -[scriptable, uuid(53dd1cbe-cb9f-4d9e-8104-1ab72851c88e)] +[scriptable, uuid(98bd5bf9-87eb-4d92-81b1-4cd10c64f7b2)] interface imgITools : nsISupports { /** * decodeImageData * Caller provides an input stream and mimetype. We read from the stream * and decompress it (according to the specified mime type) and return * the resulting imgIContainer. (If the caller already has a container, * it can be provided as input to be reused). @@ -118,9 +120,17 @@ interface imgITools : nsISupports */ nsIInputStream encodeCroppedImage(in imgIContainer aContainer, in ACString aMimeType, in long aOffsetX, in long aOffsetY, in long aWidth, in long aHeight, [optional] in AString outputOptions); + + /** + * Create a wrapper around a scripted notification observer (ordinarily + * imgINotificationObserver cannot be implemented from scripts). + * + * @param aObserver The scripted observer to wrap + */ + imgINotificationObserver createScriptedObserver(in imgIScriptedNotificationObserver aObserver); };
--- a/image/src/Makefile.in +++ b/image/src/Makefile.in @@ -22,16 +22,17 @@ EXPORTS = imgLoader.h \ imgRequest.h \ $(NULL) CPPSRCS = \ Image.cpp \ Decoder.cpp \ DiscardTracker.cpp \ RasterImage.cpp \ + ScriptedNotificationObserver.cpp \ SVGDocumentWrapper.cpp \ VectorImage.cpp \ imgFrame.cpp \ imgLoader.cpp \ imgRequest.cpp \ imgRequestProxy.cpp \ imgTools.cpp \ imgStatusTracker.cpp \
new file mode 100644 --- /dev/null +++ b/image/src/ScriptedNotificationObserver.cpp @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#include "ScriptedNotificationObserver.h" +#include "imgIScriptedNotificationObserver.h" +#include "nsCycleCollectionParticipant.h" + +using namespace mozilla::image; + +NS_IMPL_CYCLE_COLLECTION_1(ScriptedNotificationObserver, mInner) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptedNotificationObserver) + NS_INTERFACE_MAP_ENTRY(imgINotificationObserver) + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(ScriptedNotificationObserver) +NS_IMPL_CYCLE_COLLECTING_RELEASE(ScriptedNotificationObserver) + +ScriptedNotificationObserver::ScriptedNotificationObserver( + imgIScriptedNotificationObserver* aInner) +: mInner(aInner) +{ +} + +NS_IMETHODIMP +ScriptedNotificationObserver::Notify(imgIRequest* aRequest, + int32_t aType, + const nsIntRect* /*aUnused*/) +{ + if (aType == imgINotificationObserver::START_REQUEST) + return mInner->StartRequest(aRequest); + if (aType == imgINotificationObserver::START_CONTAINER) + return mInner->StartContainer(aRequest); + if (aType == imgINotificationObserver::START_FRAME) + return mInner->StartFrame(aRequest); + if (aType == imgINotificationObserver::START_DECODE) + return mInner->StartDecode(aRequest); + if (aType == imgINotificationObserver::DATA_AVAILABLE) + return mInner->DataAvailable(aRequest); + if (aType == imgINotificationObserver::STOP_FRAME) + return mInner->StopFrame(aRequest); + if (aType == imgINotificationObserver::STOP_CONTAINER) + return mInner->StopContainer(aRequest); + if (aType == imgINotificationObserver::STOP_DECODE) + return mInner->StopDecode(aRequest); + if (aType == imgINotificationObserver::STOP_REQUEST) + return mInner->StopRequest(aRequest); + if (aType == imgINotificationObserver::DISCARD) + return mInner->StopRequest(aRequest); + if (aType == imgINotificationObserver::IS_ANIMATED) + return mInner->IsAnimated(aRequest); + if (aType == imgINotificationObserver::FRAME_CHANGED) + return mInner->FrameChanged(aRequest); + return NS_OK; +}
new file mode 100644 --- /dev/null +++ b/image/src/ScriptedNotificationObserver.h @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +#include "imgINotificationObserver.h" +#include "nsCOMPtr.h" +#include "nsCycleCollectionParticipant.h" + +class imgIScriptedNotificationObserver; + +namespace mozilla { +namespace image { + +class ScriptedNotificationObserver : public imgINotificationObserver +{ +public: + ScriptedNotificationObserver(imgIScriptedNotificationObserver* aInner); + virtual ~ScriptedNotificationObserver() {} + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_IMGINOTIFICATIONOBSERVER + NS_DECL_CYCLE_COLLECTION_CLASS(ScriptedNotificationObserver) + +private: + nsCOMPtr<imgIScriptedNotificationObserver> mInner; +}; + +}}
--- a/image/src/imgLoader.cpp +++ b/image/src/imgLoader.cpp @@ -675,17 +675,17 @@ imgCacheQueue::iterator imgCacheQueue::e return mQueue.end(); } imgCacheQueue::const_iterator imgCacheQueue::end() const { return mQueue.end(); } nsresult imgLoader::CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup, - imgIDecoderObserver *aObserver, + imgINotificationObserver *aObserver, nsLoadFlags aLoadFlags, imgIRequest *aProxyRequest, imgIRequest **_retval) { LOG_SCOPE_WITH_PARAM(gImgLog, "imgLoader::CreateNewProxyForRequest", "imgRequest", aRequest); /* XXX If we move decoding onto separate threads, we should save off the calling thread here and pass it off to |proxyRequest| so that it call proxy calls to |aObserver|. @@ -1157,17 +1157,17 @@ void imgLoader::CheckCacheLimits(imgCach } } bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request, nsIURI *aURI, nsIURI *aInitialDocumentURI, nsIURI *aReferrerURI, nsILoadGroup *aLoadGroup, - imgIDecoderObserver *aObserver, + imgINotificationObserver *aObserver, nsISupports *aCX, nsLoadFlags aLoadFlags, imgIRequest *aExistingRequest, imgIRequest **aProxyRequest, nsIChannelPolicy *aPolicy, nsIPrincipal* aLoadingPrincipal, int32_t aCORSMode) { @@ -1279,17 +1279,17 @@ bool imgLoader::ValidateRequestWithNewCh } } bool imgLoader::ValidateEntry(imgCacheEntry *aEntry, nsIURI *aURI, nsIURI *aInitialDocumentURI, nsIURI *aReferrerURI, nsILoadGroup *aLoadGroup, - imgIDecoderObserver *aObserver, + imgINotificationObserver *aObserver, nsISupports *aCX, nsLoadFlags aLoadFlags, bool aCanMakeNewChannel, imgIRequest *aExistingRequest, imgIRequest **aProxyRequest, nsIChannelPolicy *aPolicy, nsIPrincipal* aLoadingPrincipal, int32_t aCORSMode) @@ -1516,24 +1516,24 @@ nsresult imgLoader::EvictEntries(imgCach #define LOAD_FLAGS_CACHE_MASK (nsIRequest::LOAD_BYPASS_CACHE | \ nsIRequest::LOAD_FROM_CACHE) #define LOAD_FLAGS_VALIDATE_MASK (nsIRequest::VALIDATE_ALWAYS | \ nsIRequest::VALIDATE_NEVER | \ nsIRequest::VALIDATE_ONCE_PER_SESSION) -/* imgIRequest loadImage (in nsIURI aURI, in nsIURI initialDocumentURI, in nsIPrincipal loadingPrincipal, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, in nsISupports cacheKey, in imgIRequest aRequest); */ +/* imgIRequest loadImage (in nsIURI aURI, in nsIURI initialDocumentURI, in nsIPrincipal loadingPrincipal, in nsILoadGroup aLoadGroup, in imgINotificationObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, in nsISupports cacheKey, in imgIRequest aRequest); */ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsIURI *aInitialDocumentURI, nsIURI *aReferrerURI, nsIPrincipal* aLoadingPrincipal, nsILoadGroup *aLoadGroup, - imgIDecoderObserver *aObserver, + imgINotificationObserver *aObserver, nsISupports *aCX, nsLoadFlags aLoadFlags, nsISupports *aCacheKey, imgIRequest *aRequest, nsIChannelPolicy *aPolicy, imgIRequest **_retval) { VerifyCacheSizes(); @@ -1779,18 +1779,18 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIUR return rv; } NS_ASSERTION(*_retval, "imgLoader::LoadImage -- no return value"); return NS_OK; } -/* imgIRequest loadImageWithChannel(in nsIChannel channel, in imgIDecoderObserver aObserver, in nsISupports cx, out nsIStreamListener); */ -NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderObserver *aObserver, nsISupports *aCX, nsIStreamListener **listener, imgIRequest **_retval) +/* imgIRequest loadImageWithChannel(in nsIChannel channel, in imgINotificationObserver aObserver, in nsISupports cx, out nsIStreamListener); */ +NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgINotificationObserver *aObserver, nsISupports *aCX, nsIStreamListener **listener, imgIRequest **_retval) { NS_ASSERTION(channel, "imgLoader::LoadImageWithChannel -- NULL channel pointer"); MOZ_ASSERT(NS_UsePrivateBrowsing(channel) == mRespectPrivacy); nsRefPtr<imgRequest> request; nsCOMPtr<nsIURI> uri;
--- a/image/src/imgLoader.h +++ b/image/src/imgLoader.h @@ -25,17 +25,17 @@ #ifdef LOADER_THREADSAFE #include "prlock.h" #endif class imgLoader; class imgRequest; class imgRequestProxy; class imgIRequest; -class imgIDecoderObserver; +class imgINotificationObserver; class nsILoadGroup; class imgCacheExpirationTracker; class imgMemoryReporter; class imgCacheEntry { public: imgCacheEntry(imgLoader* loader, imgRequest *request, bool aForcePrincipalCheck); @@ -284,37 +284,37 @@ public: bool SetHasProxies(nsIURI *key); private: // methods bool ValidateEntry(imgCacheEntry *aEntry, nsIURI *aKey, nsIURI *aInitialDocumentURI, nsIURI *aReferrerURI, nsILoadGroup *aLoadGroup, - imgIDecoderObserver *aObserver, nsISupports *aCX, + imgINotificationObserver *aObserver, nsISupports *aCX, nsLoadFlags aLoadFlags, bool aCanMakeNewChannel, imgIRequest *aExistingRequest, imgIRequest **aProxyRequest, nsIChannelPolicy *aPolicy, nsIPrincipal* aLoadingPrincipal, int32_t aCORSMode); bool ValidateRequestWithNewChannel(imgRequest *request, nsIURI *aURI, nsIURI *aInitialDocumentURI, nsIURI *aReferrerURI, nsILoadGroup *aLoadGroup, - imgIDecoderObserver *aObserver, + imgINotificationObserver *aObserver, nsISupports *aCX, nsLoadFlags aLoadFlags, imgIRequest *aExistingRequest, imgIRequest **aProxyRequest, nsIChannelPolicy *aPolicy, nsIPrincipal* aLoadingPrincipal, int32_t aCORSMode); nsresult CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup, - imgIDecoderObserver *aObserver, + imgINotificationObserver *aObserver, nsLoadFlags aLoadFlags, imgIRequest *aRequestProxy, imgIRequest **_retval); void ReadAcceptHeaderPref(); typedef nsRefPtrHashtable<nsCStringHashKey, imgCacheEntry> imgCacheTable;
--- a/image/src/imgRequestProxy.cpp +++ b/image/src/imgRequestProxy.cpp @@ -85,17 +85,17 @@ imgRequestProxy::~imgRequestProxy() */ mOwner->RemoveProxy(this, NS_OK); } } } nsresult imgRequestProxy::Init(imgStatusTracker* aStatusTracker, nsILoadGroup* aLoadGroup, - nsIURI* aURI, imgIDecoderObserver* aObserver) + nsIURI* aURI, imgINotificationObserver* aObserver) { NS_PRECONDITION(!mOwner && !mListener, "imgRequestProxy is already initialized"); LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequestProxy::Init", "request", aStatusTracker->GetRequest()); NS_ABORT_IF_FALSE(mAnimationConsumers == 0, "Cannot have animation before Init"); mOwner = aStatusTracker->GetRequest(); @@ -453,21 +453,21 @@ NS_IMETHODIMP imgRequestProxy::GetURI(ns if (!mURI) return NS_ERROR_FAILURE; NS_ADDREF(*aURI = mURI); return NS_OK; } -/* readonly attribute imgIDecoderObserver decoderObserver; */ -NS_IMETHODIMP imgRequestProxy::GetDecoderObserver(imgIDecoderObserver **aDecoderObserver) +/* readonly attribute imgINotificationObserver notificationObserver; */ +NS_IMETHODIMP imgRequestProxy::GetNotificationObserver(imgINotificationObserver **aObserver) { - *aDecoderObserver = mListener; - NS_IF_ADDREF(*aDecoderObserver); + *aObserver = mListener; + NS_IF_ADDREF(*aObserver); return NS_OK; } /* readonly attribute string mimeType; */ NS_IMETHODIMP imgRequestProxy::GetMimeType(char **aMimeType) { if (!mOwner) return NS_ERROR_FAILURE; @@ -476,17 +476,17 @@ NS_IMETHODIMP imgRequestProxy::GetMimeTy if (!type) return NS_ERROR_FAILURE; *aMimeType = NS_strdup(type); return NS_OK; } -NS_IMETHODIMP imgRequestProxy::Clone(imgIDecoderObserver* aObserver, +NS_IMETHODIMP imgRequestProxy::Clone(imgINotificationObserver* aObserver, imgIRequest** aClone) { NS_PRECONDITION(aClone, "Null out param"); LOG_SCOPE(gImgLog, "imgRequestProxy::Clone"); *aClone = nullptr; nsRefPtr<imgRequestProxy> clone = new imgRequestProxy(); @@ -586,149 +586,147 @@ NS_IMETHODIMP imgRequestProxy::GetHasTra *hasData = mOwner->HasTransferredData(); } else { // The safe thing to do is to claim we have data *hasData = true; } return NS_OK; } -/** imgIContainerObserver methods **/ - void imgRequestProxy::FrameChanged(imgIContainer *container, const nsIntRect *dirtyRect) { LOG_FUNC(gImgLog, "imgRequestProxy::FrameChanged"); if (mListener && !mCanceled) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->FrameChanged(this, container, dirtyRect); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::FRAME_CHANGED, dirtyRect); } } /** imgIDecoderObserver methods **/ void imgRequestProxy::OnStartDecode() { LOG_FUNC(gImgLog, "imgRequestProxy::OnStartDecode"); if (mListener && !mCanceled) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->OnStartDecode(this); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::START_DECODE, nullptr); } } void imgRequestProxy::OnStartContainer(imgIContainer *image) { LOG_FUNC(gImgLog, "imgRequestProxy::OnStartContainer"); if (mListener && !mCanceled && !mSentStartContainer) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->OnStartContainer(this, image); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::START_CONTAINER, nullptr); mSentStartContainer = true; } } void imgRequestProxy::OnStartFrame(uint32_t frame) { LOG_FUNC(gImgLog, "imgRequestProxy::OnStartFrame"); if (mListener && !mCanceled) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->OnStartFrame(this, frame); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::START_FRAME, nullptr); } } void imgRequestProxy::OnDataAvailable(bool aCurrentFrame, const nsIntRect * rect) { LOG_FUNC(gImgLog, "imgRequestProxy::OnDataAvailable"); if (mListener && !mCanceled) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->OnDataAvailable(this, aCurrentFrame, rect); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::DATA_AVAILABLE, rect); } } void imgRequestProxy::OnStopFrame(uint32_t frame) { LOG_FUNC(gImgLog, "imgRequestProxy::OnStopFrame"); if (mListener && !mCanceled) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->OnStopFrame(this, frame); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::STOP_FRAME, nullptr); } } void imgRequestProxy::OnStopContainer(imgIContainer *image) { LOG_FUNC(gImgLog, "imgRequestProxy::OnStopContainer"); if (mListener && !mCanceled) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->OnStopContainer(this, image); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::STOP_CONTAINER, nullptr); } // Multipart needs reset for next OnStartContainer if (mOwner && mOwner->GetMultipart()) mSentStartContainer = false; } void imgRequestProxy::OnStopDecode(nsresult status, const PRUnichar *statusArg) { LOG_FUNC(gImgLog, "imgRequestProxy::OnStopDecode"); if (mListener && !mCanceled) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->OnStopDecode(this, status, statusArg); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::STOP_DECODE, nullptr); } } void imgRequestProxy::OnDiscard() { LOG_FUNC(gImgLog, "imgRequestProxy::OnDiscard"); if (mListener && !mCanceled) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->OnDiscard(this); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::DISCARD, nullptr); } } void imgRequestProxy::OnImageIsAnimated() { LOG_FUNC(gImgLog, "imgRequestProxy::OnImageIsAnimated"); if (mListener && !mCanceled) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->OnImageIsAnimated(this); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::IS_ANIMATED, nullptr); } } void imgRequestProxy::OnStartRequest() { #ifdef PR_LOGGING nsAutoCString name; GetName(name); LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::OnStartRequest", "name", name.get()); #endif // Notify even if mCanceled, since OnStartRequest is guaranteed by the // nsIStreamListener contract so it makes sense to do the same here. if (mListener) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->OnStartRequest(this); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::START_REQUEST, nullptr); } } void imgRequestProxy::OnStopRequest(bool lastPart) { #ifdef PR_LOGGING nsAutoCString name; GetName(name); @@ -736,18 +734,18 @@ void imgRequestProxy::OnStopRequest(bool #endif // There's all sorts of stuff here that could kill us (the OnStopRequest call // on the listener, the removal from the loadgroup, the release of the // listener, etc). Don't let them do it. nsCOMPtr<imgIRequest> kungFuDeathGrip(this); if (mListener) { // Hold a ref to the listener while we call it, just in case. - nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener); - mListener->OnStopRequest(this, lastPart); + nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener); + mListener->Notify(this, imgINotificationObserver::STOP_REQUEST, nullptr); } // If we're expecting more data from a multipart channel, re-add ourself // to the loadgroup so that the document doesn't lose track of the load. // If the request is already a background request and there's more data // coming, we can just leave the request in the loadgroup as-is. if (lastPart || (mLoadFlags & nsIRequest::LOAD_BACKGROUND) == 0) { RemoveFromLoadGroup(lastPart); @@ -759,17 +757,17 @@ void imgRequestProxy::OnStopRequest(bool } } if (mListenerIsStrongRef) { NS_PRECONDITION(mListener, "How did that happen?"); // Drop our strong ref to the listener now that we're done with // everything. Note that this can cancel us and other fun things // like that. Don't add anything in this method after this point. - imgIDecoderObserver* obs = mListener; + imgINotificationObserver* obs = mListener; mListenerIsStrongRef = false; NS_RELEASE(obs); } } void imgRequestProxy::BlockOnload() { #ifdef PR_LOGGING @@ -801,17 +799,17 @@ void imgRequestProxy::UnblockOnload() void imgRequestProxy::NullOutListener() { // If we have animation consumers, then they don't matter anymore if (mListener) ClearAnimationConsumers(); if (mListenerIsStrongRef) { // Releasing could do weird reentery stuff, so just play it super-safe - nsCOMPtr<imgIDecoderObserver> obs; + nsCOMPtr<imgINotificationObserver> obs; obs.swap(mListener); mListenerIsStrongRef = false; } else { mListener = nullptr; } } NS_IMETHODIMP
--- a/image/src/imgRequestProxy.h +++ b/image/src/imgRequestProxy.h @@ -3,17 +3,17 @@ * 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/. */ #ifndef imgRequestProxy_h__ #define imgRequestProxy_h__ #include "imgIRequest.h" -#include "imgIDecoderObserver.h" +#include "imgINotificationObserver.h" #include "nsISecurityInfoProvider.h" #include "nsIRequestObserver.h" #include "nsIChannel.h" #include "nsILoadGroup.h" #include "nsISupportsPriority.h" #include "nsITimedChannel.h" #include "nsCOMPtr.h" @@ -54,17 +54,17 @@ public: imgRequestProxy(); virtual ~imgRequestProxy(); // Callers to Init or ChangeOwner are required to call NotifyListener after // (although not immediately after) doing so. nsresult Init(imgStatusTracker* aStatusTracker, nsILoadGroup *aLoadGroup, - nsIURI* aURI, imgIDecoderObserver *aObserver); + nsIURI* aURI, imgINotificationObserver *aObserver); nsresult ChangeOwner(imgRequest *aNewOwner); // this will change mOwner. Do not call this if the previous // owner has already sent notifications out! void AddToLoadGroup(); void RemoveFromLoadGroup(bool releaseLoadGroup); inline bool HasObserver() const { @@ -194,17 +194,17 @@ private: nsRefPtr<imgRequest> mOwner; // The URI of our request. nsCOMPtr<nsIURI> mURI; // mListener is only promised to be a weak ref (see imgILoader.idl), // but we actually keep a strong ref to it until we've seen our // first OnStopRequest. - imgIDecoderObserver* mListener; + imgINotificationObserver* mListener; nsCOMPtr<nsILoadGroup> mLoadGroup; nsLoadFlags mLoadFlags; uint32_t mLockCount; uint32_t mAnimationConsumers; bool mCanceled; bool mIsInLoadGroup; bool mListenerIsStrongRef;
--- a/image/src/imgTools.cpp +++ b/image/src/imgTools.cpp @@ -18,16 +18,18 @@ #include "nsStringStream.h" #include "nsComponentManagerUtils.h" #include "nsWeakReference.h" #include "nsIInterfaceRequestorUtils.h" #include "nsStreamUtils.h" #include "nsNetUtil.h" #include "nsContentUtils.h" #include "RasterImage.h" +#include "ScriptedNotificationObserver.h" +#include "imgIScriptedNotificationObserver.h" using namespace mozilla::image; class nsIDOMDocument; class nsIDocument; /* ========== imgITools implementation ========== */ @@ -271,16 +273,23 @@ NS_IMETHODIMP imgTools::GetFirstImageFra NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(frame, NS_ERROR_NOT_AVAILABLE); NS_ENSURE_TRUE(frame->Width() && frame->Height(), NS_ERROR_FAILURE); frame.forget(aSurface); return NS_OK; } +NS_IMETHODIMP imgTools::CreateScriptedObserver(imgIScriptedNotificationObserver* aInner, + imgINotificationObserver** aObserver) +{ + NS_ADDREF(*aObserver = new ScriptedNotificationObserver(aInner)); + return NS_OK; +} + NS_IMETHODIMP imgTools::GetImgLoaderForDocument(nsIDOMDocument* aDoc, imgILoader** aLoader) { nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc); NS_IF_ADDREF(*aLoader = nsContentUtils::GetImgLoaderForDocument(doc)); return NS_OK; }
--- a/image/test/mochitest/imgutils.js +++ b/image/test/mochitest/imgutils.js @@ -116,20 +116,24 @@ function getImagePref(pref) default: throw new Error("Unknown pref type"); } } else return null; } -// JS implementation of imgIDecoderObserver with stubs for all of its methods. +// JS implementation of imgIScriptedNotificationObserver with stubs for all of its methods. function ImageDecoderObserverStub() { - this.onStartRequest = function onStartRequest(aRequest) {} - this.onStartDecode = function onStartDecode(aRequest) {} - this.onStartContainer = function onStartContainer(aRequest, aContainer) {} - this.onStartFrame = function onStartFrame(aRequest, aFrame) {} - this.onStopFrame = function onStopFrame(aRequest, aFrame) {} - this.onStopContainer = function onStopContainer(aRequest, aContainer) {} - this.onStopDecode = function onStopDecode(aRequest, status, statusArg) {} - this.onStopRequest = function onStopRequest(aRequest, aIsLastPart) {} + this.startRequest = function startRequest(aRequest) {} + this.startDecode = function startDecode(aRequest) {} + this.startContainer = function startContainer(aRequest) {} + this.startFrame = function startFrame(aRequest) {} + this.stopFrame = function stopFrame(aRequest) {} + this.stopContainer = function stopContainer(aRequest) {} + this.stopDecode = function stopDecode(aRequest) {} + this.stopRequest = function stopRequest(aRequest) {} + this.dataAvailable = function dataAvailable(aRequest) {} + this.discard = function discard(aRequest) {} + this.isAnimated = function isAnimated(aRequest) {} + this.frameChanged = function frameChanged(aRequest) {} }
--- a/image/test/mochitest/test_animSVGImage.html +++ b/image/test/mochitest/test_animSVGImage.html @@ -21,16 +21,17 @@ https://bugzilla.mozilla.org/show_bug.cg <pre id="test"> <script type="application/javascript;version=1.8"> /** Test for Bug 610419**/ SimpleTest.waitForExplicitFinish(); const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes) +const Cc = Components.classes; const Ci = Components.interfaces; const gImg = document.getElementsByTagName("img")[0]; var gMyDecoderObserver; // value will be set in main() var gReferenceSnapshot; // value will be set in takeReferenceSnapshot() var gOnStopFrameCounter = 0; var gIsTestFinished = false; @@ -48,17 +49,17 @@ function takeReferenceSnapshot() { // Re-hide reference div, and take another snapshot to be sure it's gone referenceDiv.style.display = "none"; let blankSnapshot2 = snapshotWindow(window, false); ok(compareSnapshots(blankSnapshot, blankSnapshot2, true)[0], "reference div should disappear when it becomes display:none"); } -function myOnStopFrame(aRequest, aFrame) { +function myOnStopFrame(aRequest) { gOnStopFrameCounter++; ok(true, "myOnStopFrame called"); let currentSnapshot = snapshotWindow(window, false); if (compareSnapshots(currentSnapshot, gReferenceSnapshot, true)[0]) { // SUCCESS! ok(true, "Animated image looks correct, " + "at call #" + gOnStopFrameCounter + " to onStopFrame"); cleanUpAndFinish(); @@ -84,18 +85,21 @@ function cleanUpAndFinish() { SimpleTest.finish(); gIsTestFinished = true; } function main() { takeReferenceSnapshot(); // Create, customize & attach decoder observer - gMyDecoderObserver = new ImageDecoderObserverStub(); - gMyDecoderObserver.onStopFrame = myOnStopFrame; + observer = new ImageDecoderObserverStub(); + observer.stopFrame = myOnStopFrame; + gMyDecoderObserver = + Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) + .createScriptedObserver(observer); let imgLoadingContent = gImg.QueryInterface(Ci.nsIImageLoadingContent); imgLoadingContent.addObserver(gMyDecoderObserver); // We want to test the cold loading behavior, so clear cache in case an // earlier test got our image in there already. clearImageCache(); // kick off image-loading! myOnStopFrame handles the rest.
--- a/image/test/unit/async_load_tests.js +++ b/image/test/unit/async_load_tests.js @@ -40,39 +40,51 @@ function getCloneStopCallback(original_l // but they aren't synchronous right now. function checkClone(other_listener, aRequest) { do_test_pending(); // For as long as clone notification is synchronous, we can't test the clone state reliably. var listener = new ImageListener(null, function(foo, bar) { do_test_finished(); } /*getCloneStopCallback(other_listener)*/); listener.synchronous = false; - var clone = aRequest.clone(listener); + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) + .createScriptedObserver(listener); + var clone = aRequest.clone(outer); } // Ensure that all the callbacks were called on aRequest. function checkAllCallbacks(listener, aRequest) { + do_check_neq(listener.state & START_REQUEST, 0); + do_check_neq(listener.state & START_DECODE, 0); + do_check_neq(listener.state & START_CONTAINER, 0); + do_check_neq(listener.state & START_FRAME, 0); + do_check_neq(listener.state & STOP_FRAME, 0); + do_check_neq(listener.state & STOP_CONTAINER, 0); + do_check_neq(listener.state & STOP_DECODE, 0); + do_check_neq(listener.state & STOP_REQUEST, 0); do_check_eq(listener.state, ALL_BITS); do_test_finished(); } function secondLoadDone(oldlistener, aRequest) { do_test_pending(); try { var staticrequest = aRequest.getStaticRequest(); // For as long as clone notification is synchronous, we can't test the // clone state reliably. var listener = new ImageListener(null, checkAllCallbacks); listener.synchronous = false; - var staticrequestclone = staticrequest.clone(listener); + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) + .createScriptedObserver(listener); + var staticrequestclone = staticrequest.clone(outer); } catch(e) { // We can't create a static request. Most likely the request we started // with didn't load successfully. do_test_finished(); } run_loadImageWithChannel_tests(); @@ -81,17 +93,19 @@ function secondLoadDone(oldlistener, aRe // Load the request a second time. This should come from the image cache, and // therefore would be at most risk of being served synchronously. function checkSecondLoad() { do_test_pending(); var listener = new ImageListener(checkClone, secondLoadDone); - requests.push(gCurrentLoader.loadImage(uri, null, null, null, null, listener, null, 0, null, null, null)); + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) + .createScriptedObserver(listener); + requests.push(gCurrentLoader.loadImage(uri, null, null, null, null, outer, null, 0, null, null, null)); listener.synchronous = false; } function firstLoadDone(oldlistener, aRequest) { checkSecondLoad(uri); do_test_finished(); @@ -136,18 +150,20 @@ function checkSecondChannelLoad() var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); var channel = ioService.newChannelFromURI(uri); var channellistener = new ChannelListener(); channel.asyncOpen(channellistener, null); var listener = new ImageListener(getChannelLoadImageStartCallback(channellistener), getChannelLoadImageStopCallback(channellistener, all_done_callback)); + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) + .createScriptedObserver(listener); var outlistener = {}; - requests.push(gCurrentLoader.loadImageWithChannel(channel, listener, null, outlistener)); + requests.push(gCurrentLoader.loadImageWithChannel(channel, outer, null, outlistener)); channellistener.outputListener = outlistener.value; listener.synchronous = false; } function run_loadImageWithChannel_tests() { // To ensure we're testing what we expect to, create a new loader and cache. @@ -158,18 +174,20 @@ function run_loadImageWithChannel_tests( var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); var channel = ioService.newChannelFromURI(uri); var channellistener = new ChannelListener(); channel.asyncOpen(channellistener, null); var listener = new ImageListener(getChannelLoadImageStartCallback(channellistener), getChannelLoadImageStopCallback(channellistener, checkSecondChannelLoad)); + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) + .createScriptedObserver(listener); var outlistener = {}; - requests.push(gCurrentLoader.loadImageWithChannel(channel, listener, null, outlistener)); + requests.push(gCurrentLoader.loadImageWithChannel(channel, outer, null, outlistener)); channellistener.outputListener = outlistener.value; listener.synchronous = false; } function all_done_callback() { server.stop(function() { do_test_finished(); }); @@ -177,32 +195,36 @@ function all_done_callback() function startImageCallback(otherCb) { return function(listener, request) { // Make sure we can load the same image immediately out of the cache. do_test_pending(); var listener2 = new ImageListener(null, function(foo, bar) { do_test_finished(); }); - requests.push(gCurrentLoader.loadImage(uri, null, null, null, null, listener2, null, 0, null, null, null)); + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) + .createScriptedObserver(listener2); + requests.push(gCurrentLoader.loadImage(uri, null, null, null, null, outer, null, 0, null, null, null)); listener2.synchronous = false; // Now that we've started another load, chain to the callback. otherCb(listener, request); } } var gCurrentLoader; function run_test() { gCurrentLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader); do_test_pending(); var listener = new ImageListener(startImageCallback(checkClone), firstLoadDone); - var req = gCurrentLoader.loadImage(uri, null, null, null, null, listener, null, 0, null, null, null); + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) + .createScriptedObserver(listener); + var req = gCurrentLoader.loadImage(uri, null, null, null, null, outer, null, 0, null, null, null); requests.push(req); // Ensure that we don't cause any mayhem when we lock an image. req.lockImage(); listener.synchronous = false; }
--- a/image/test/unit/image_load_helpers.js +++ b/image/test/unit/image_load_helpers.js @@ -15,78 +15,81 @@ const STOP_CONTAINER = 0x20; const STOP_DECODE = 0x40; const STOP_REQUEST = 0x80; const ALL_BITS = 0xFF; // An implementation of imgIDecoderObserver with the ability to call specified // functions on onStartRequest and onStopRequest. function ImageListener(start_callback, stop_callback) { - this.onStartRequest = function onStartRequest(aRequest) + this.startRequest = function onStartRequest(aRequest) { do_check_false(this.synchronous); this.state |= START_REQUEST; if (this.start_callback) this.start_callback(this, aRequest); } - this.onStartDecode = function onStartDecode(aRequest) + this.startDecode = function onStartDecode(aRequest) { do_check_false(this.synchronous); this.state |= START_DECODE; } - this.onStartContainer = function onStartContainer(aRequest, aContainer) + this.startContainer = function onStartContainer(aRequest) { do_check_false(this.synchronous); this.state |= START_CONTAINER; } - this.onStartFrame = function onStartFrame(aRequest, aFrame) + this.startFrame = function onStartFrame(aRequest) { do_check_false(this.synchronous); this.state |= START_FRAME; } - this.onStopFrame = function onStopFrame(aRequest, aFrame) + this.stopFrame = function onStopFrame(aRequest) { do_check_false(this.synchronous); this.state |= STOP_FRAME; } - this.onStopContainer = function onStopContainer(aRequest, aContainer) + this.stopContainer = function onStopContainer(aRequest) { do_check_false(this.synchronous); this.state |= STOP_CONTAINER; } - this.onStopDecode = function onStopDecode(aRequest, status, statusArg) + this.stopDecode = function onStopDecode(aRequest) { do_check_false(this.synchronous); this.state |= STOP_DECODE; } - this.onStopRequest = function onStopRequest(aRequest, aIsLastPart) + this.stopRequest = function onStopRequest(aRequest) { do_check_false(this.synchronous); // onStopDecode must always be called before, and with, onStopRequest. See // imgRequest::OnStopDecode for more information. do_check_true(!!(this.state & STOP_DECODE)); // We have to cancel the request when we're done with it to break any // reference loops! aRequest.cancelAndForgetObserver(0); this.state |= STOP_REQUEST; if (this.stop_callback) this.stop_callback(this, aRequest); } + this.dataAvailable = function onDataAvailable(aRequest) + { + } // Initialize the synchronous flag to true to start. This must be set to // false before exiting to the event loop! this.synchronous = true; // A function to call when onStartRequest is called. this.start_callback = start_callback;
--- a/image/test/unit/test_private_channel.js +++ b/image/test/unit/test_private_channel.js @@ -50,31 +50,35 @@ var gImgPath = 'http://localhost:8088/im function setup_chan(path, isPrivate, callback) { var uri = gIoService.newURI(gImgPath, null, null); var chan = gIoService.newChannelFromURI(uri); chan.notificationCallbacks = new NotificationCallbacks(isPrivate); var channelListener = new ChannelListener(); chan.asyncOpen(channelListener, null); var listener = new ImageListener(null, callback); - listeners.push(listener); var outlistener = {}; var loader = isPrivate ? gPrivateLoader : gPublicLoader; - requests.push(loader.loadImageWithChannel(chan, listener, null, outlistener)); + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) + .createScriptedObserver(listener); + listeners.push(outer); + requests.push(loader.loadImageWithChannel(chan, outer, null, outlistener)); channelListener.outputListener = outlistener.value; listener.synchronous = false; } function loadImage(isPrivate, callback) { var listener = new ImageListener(null, callback); + var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) + .createScriptedObserver(listener); var uri = gIoService.newURI(gImgPath, null, null); var loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance(Ci.nsILoadGroup); loadGroup.notificationCallbacks = new NotificationCallbacks(isPrivate); var loader = isPrivate ? gPrivateLoader : gPublicLoader; - requests.push(loader.loadImage(uri, null, null, null, loadGroup, listener, null, 0, null, null, null)); + requests.push(loader.loadImage(uri, null, null, null, loadGroup, outer, null, 0, null, null, null)); listener.synchronous = false; } function run_loadImage_tests() { let cs = Cc["@mozilla.org/network/cache-service;1"].getService(Ci.nsICacheService); cs.evictEntries(Ci.nsICache.STORE_ANYWHERE); gHits = 0;
--- a/layout/generic/nsBulletFrame.cpp +++ b/layout/generic/nsBulletFrame.cpp @@ -1426,19 +1426,47 @@ nsBulletFrame::GetMinWidth(nsRenderingCo nsBulletFrame::GetPrefWidth(nsRenderingContext *aRenderingContext) { nsHTMLReflowMetrics metrics; DISPLAY_PREF_WIDTH(this, metrics.width); GetDesiredSize(PresContext(), aRenderingContext, metrics, 1.0f); return metrics.width; } +NS_IMETHODIMP +nsBulletFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) +{ + if (aType == imgINotificationObserver::START_CONTAINER) { + nsCOMPtr<imgIContainer> image; + aRequest->GetImage(getter_AddRefs(image)); + return OnStartContainer(aRequest, image); + } -NS_IMETHODIMP nsBulletFrame::OnStartContainer(imgIRequest *aRequest, - imgIContainer *aImage) + if (aType == imgINotificationObserver::DATA_AVAILABLE || + aType == imgINotificationObserver::FRAME_CHANGED) { + // The image has changed. + // Invalidate the entire content area. Maybe it's not optimal but it's simple and + // always correct, and I'll be a stunned mullet if it ever matters for performance + InvalidateFrame(); + } + + if (aType == imgINotificationObserver::IS_ANIMATED) { + // Register the image request with the refresh driver now that we know it's + // animated. + if (aRequest == mImageRequest) { + nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest, + &mRequestRegistered); + } + } + + return NS_OK; +} + +nsresult nsBulletFrame::OnStartContainer(imgIRequest *aRequest, + imgIContainer *aImage) { if (!aImage) return NS_ERROR_INVALID_ARG; if (!aRequest) return NS_ERROR_INVALID_ARG; uint32_t status; aRequest->GetImageStatus(&status); if (status & imgIRequest::STATUS_ERROR) { return NS_OK; @@ -1470,70 +1498,16 @@ NS_IMETHODIMP nsBulletFrame::OnStartCont // Ensure the animation (if any) is started. Note: There is no // corresponding call to Decrement for this. This Increment will be // 'cleaned up' by the Request when it is destroyed, but only then. aRequest->IncrementAnimationConsumers(); return NS_OK; } -NS_IMETHODIMP nsBulletFrame::OnDataAvailable(imgIRequest *aRequest, - bool aCurrentFrame, - const nsIntRect *aRect) -{ - // The image has changed. - // Invalidate the entire content area. Maybe it's not optimal but it's simple and - // always correct, and I'll be a stunned mullet if it ever matters for performance - InvalidateFrame(); - - return NS_OK; -} - -NS_IMETHODIMP nsBulletFrame::OnStopDecode(imgIRequest *aRequest, - nsresult aStatus, - const PRUnichar *aStatusArg) -{ - // XXX should the bulletframe do anything if the image failed to load? - // it didn't in the old code... - -#if 0 - if (NS_FAILED(aStatus)) { - // We failed to load the image. Notify the pres shell - if (NS_FAILED(aStatus) && (mImageRequest == aRequest || !mImageRequest)) { - imageFailed = true; - } - } -#endif - - return NS_OK; -} - -NS_IMETHODIMP nsBulletFrame::OnImageIsAnimated(imgIRequest* aRequest) -{ - // Register the image request with the refresh driver now that we know it's - // animated. - if (aRequest == mImageRequest) { - nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest, - &mRequestRegistered); - } - - return NS_OK; -} - -NS_IMETHODIMP nsBulletFrame::FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect) -{ - // Invalidate the entire content area. Maybe it's not optimal but it's simple and - // always correct. - InvalidateFrame(); - - return NS_OK; -} - void nsBulletFrame::GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup) { if (!aPresContext) return; NS_PRECONDITION(nullptr != aLoadGroup, "null OUT parameter pointer"); @@ -1619,65 +1593,26 @@ nsBulletFrame::GetBaseline() const -NS_IMPL_ISUPPORTS2(nsBulletListener, imgIDecoderObserver, imgIContainerObserver) +NS_IMPL_ISUPPORTS1(nsBulletListener, imgINotificationObserver) nsBulletListener::nsBulletListener() : mFrame(nullptr) { } nsBulletListener::~nsBulletListener() { } -NS_IMETHODIMP nsBulletListener::OnStartContainer(imgIRequest *aRequest, - imgIContainer *aImage) +NS_IMETHODIMP +nsBulletListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) { if (!mFrame) return NS_ERROR_FAILURE; - - return mFrame->OnStartContainer(aRequest, aImage); -} - -NS_IMETHODIMP nsBulletListener::OnDataAvailable(imgIRequest *aRequest, - bool aCurrentFrame, - const nsIntRect *aRect) -{ - if (!mFrame) - return NS_OK; - - return mFrame->OnDataAvailable(aRequest, aCurrentFrame, aRect); + return mFrame->Notify(aRequest, aType, aData); } - -NS_IMETHODIMP nsBulletListener::OnStopDecode(imgIRequest *aRequest, - nsresult status, - const PRUnichar *statusArg) -{ - if (!mFrame) - return NS_OK; - - return mFrame->OnStopDecode(aRequest, status, statusArg); -} - -NS_IMETHODIMP nsBulletListener::OnImageIsAnimated(imgIRequest *aRequest) -{ - if (!mFrame) - return NS_OK; - - return mFrame->OnImageIsAnimated(aRequest); -} - -NS_IMETHODIMP nsBulletListener::FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect) -{ - if (!mFrame) - return NS_OK; - - return mFrame->FrameChanged(aRequest, aContainer, aDirtyRect); -}
--- a/layout/generic/nsBulletFrame.h +++ b/layout/generic/nsBulletFrame.h @@ -9,42 +9,31 @@ #define nsBulletFrame_h___ #include "mozilla/Attributes.h" #include "nsFrame.h" #include "nsStyleContext.h" #include "imgIRequest.h" #include "imgIDecoderObserver.h" -#include "nsStubImageDecoderObserver.h" +#include "imgINotificationObserver.h" #define BULLET_FRAME_IMAGE_LOADING NS_FRAME_STATE_BIT(63) #define BULLET_FRAME_HAS_FONT_INFLATION NS_FRAME_STATE_BIT(62) class nsBulletFrame; -class nsBulletListener : public nsStubImageDecoderObserver +class nsBulletListener : public imgINotificationObserver { public: nsBulletListener(); virtual ~nsBulletListener(); NS_DECL_ISUPPORTS - // imgIDecoderObserver (override nsStubImageDecoderObserver) - NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage); - NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, bool aCurrentFrame, - const nsIntRect *aRect); - NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status, - const PRUnichar *statusArg); - NS_IMETHOD OnImageIsAnimated(imgIRequest *aRequest); - - // imgIContainerObserver (override nsStubImageDecoderObserver) - NS_IMETHOD FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *dirtyRect); + NS_DECL_IMGINOTIFICATIONOBSERVER void SetFrame(nsBulletFrame *frame) { mFrame = frame; } private: nsBulletFrame *mFrame; }; /** @@ -56,16 +45,18 @@ public: NS_DECL_FRAMEARENA_HELPERS nsBulletFrame(nsStyleContext* aContext) : nsFrame(aContext) { } virtual ~nsBulletFrame(); + NS_IMETHOD Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData); + // nsIFrame virtual void DestroyFrom(nsIFrame* aDestructRoot); NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists); virtual nsIAtom* GetType() const MOZ_OVERRIDE; virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE; #ifdef DEBUG @@ -80,28 +71,16 @@ public: virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; // nsBulletFrame int32_t SetListItemOrdinal(int32_t aNextOrdinal, bool* aChanged, int32_t aIncrement); - NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage); - NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, - bool aCurrentFrame, - const nsIntRect *aRect); - NS_IMETHOD OnStopDecode(imgIRequest *aRequest, - nsresult aStatus, - const PRUnichar *aStatusArg); - NS_IMETHOD OnImageIsAnimated(imgIRequest *aRequest); - NS_IMETHOD FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect); - /* get list item text, without '.' */ static bool AppendCounterText(int32_t aListStyleType, int32_t aOrdinal, nsString& aResult); /* get list item text, with '.' */ bool GetListItemText(const nsStyleList& aStyleList, nsString& aResult); @@ -115,16 +94,18 @@ public: float GetFontSizeInflation() const; bool HasFontSizeInflation() const { return (GetStateBits() & BULLET_FRAME_HAS_FONT_INFLATION) != 0; } void SetFontSizeInflation(float aInflation); protected: + nsresult OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage); + void GetDesiredSize(nsPresContext* aPresContext, nsRenderingContext *aRenderingContext, nsHTMLReflowMetrics& aMetrics, float aFontSizeInflation); void GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup); nsMargin mPadding;
--- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -521,16 +521,46 @@ nsImageFrame::ShouldCreateImageFrameFor( } } } return useSizedBox; } nsresult +nsImageFrame::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData) +{ + if (aType == imgINotificationObserver::START_CONTAINER) { + nsCOMPtr<imgIContainer> image; + aRequest->GetImage(getter_AddRefs(image)); + return OnStartContainer(aRequest, image); + } + + if (aType == imgINotificationObserver::DATA_AVAILABLE) { + return OnDataAvailable(aRequest, aData); + } + + if (aType == imgINotificationObserver::STOP_DECODE) { + uint32_t imgStatus; + aRequest->GetImageStatus(&imgStatus); + nsresult status = + imgStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK; + return OnStopDecode(aRequest, status); + } + + if (aType == imgINotificationObserver::FRAME_CHANGED) { + nsCOMPtr<imgIContainer> image; + aRequest->GetImage(getter_AddRefs(image)); + return FrameChanged(aRequest, image); + } + + return NS_OK; +} + +nsresult nsImageFrame::OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage) { if (!aImage) return NS_ERROR_INVALID_ARG; /* Get requested animation policy from the pres context: * normal = 0 * one frame = 1 * one loop = 2 @@ -559,17 +589,16 @@ nsImageFrame::OnStartContainer(imgIReque } } return NS_OK; } nsresult nsImageFrame::OnDataAvailable(imgIRequest *aRequest, - bool aCurrentFrame, const nsIntRect *aRect) { // XXX do we need to make sure that the reflow from the // OnStartContainer has been processed before we start calling // invalidate? NS_ENSURE_ARG_POINTER(aRect); @@ -578,21 +607,16 @@ nsImageFrame::OnDataAvailable(imgIReques return NS_OK; } if (IsPendingLoad(aRequest)) { // We don't care return NS_OK; } - // Don't invalidate if the current visible frame isn't the one the data is - // from - if (!aCurrentFrame) - return NS_OK; - #ifdef DEBUG_decode printf("Source rect (%d,%d,%d,%d)\n", aRect->x, aRect->y, aRect->width, aRect->height); #endif if (aRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect())) { InvalidateFrame(nsDisplayItem::TYPE_IMAGE); InvalidateFrame(nsDisplayItem::TYPE_ALT_FEEDBACK); @@ -602,18 +626,17 @@ nsImageFrame::OnDataAvailable(imgIReques InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_ALT_FEEDBACK); } return NS_OK; } nsresult nsImageFrame::OnStopDecode(imgIRequest *aRequest, - nsresult aStatus, - const PRUnichar *aStatusArg) + nsresult aStatus) { // Check what request type we're dealing with nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent); NS_ASSERTION(imageLoader, "Who's notifying us??"); int32_t loadType = nsIImageLoadingContent::UNKNOWN_REQUEST; imageLoader->GetRequestType(aRequest, &loadType); if (loadType != nsIImageLoadingContent::CURRENT_REQUEST && loadType != nsIImageLoadingContent::PENDING_REQUEST) { @@ -662,18 +685,17 @@ nsImageFrame::NotifyNewCurrentRequest(im // Update border+content to account for image change InvalidateFrame(); } } } nsresult nsImageFrame::FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect) + imgIContainer *aContainer) { if (!GetStyleVisibility()->IsVisible()) { return NS_OK; } if (IsPendingLoad(aContainer)) { // We don't care about it return NS_OK; @@ -1889,17 +1911,17 @@ nsresult nsImageFrame::LoadIcons(nsPresC rv = LoadIcon(brokenSrc, aPresContext, getter_AddRefs(gIconLoad->mBrokenImage)); return rv; } NS_IMPL_ISUPPORTS2(nsImageFrame::IconLoad, nsIObserver, - imgIDecoderObserver) + imgINotificationObserver) static const char* kIconLoadPrefs[] = { "browser.display.force_inline_alttext", "browser.display.show_image_placeholders", nullptr }; nsImageFrame::IconLoad::IconLoad() @@ -1946,165 +1968,52 @@ void nsImageFrame::IconLoad::GetPrefs() { mPrefForceInlineAltText = Preferences::GetBool("browser.display.force_inline_alttext"); mPrefShowPlaceholders = Preferences::GetBool("browser.display.show_image_placeholders", true); } - - NS_IMETHODIMP -nsImageFrame::IconLoad::OnStartRequest(imgIRequest *aRequest) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsImageFrame::IconLoad::OnStartDecode(imgIRequest *aRequest) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsImageFrame::IconLoad::OnStartContainer(imgIRequest *aRequest, - imgIContainer *aContainer) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsImageFrame::IconLoad::OnStartFrame(imgIRequest *aRequest, - uint32_t aFrame) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsImageFrame::IconLoad::OnDataAvailable(imgIRequest *aRequest, - bool aCurrentFrame, - const nsIntRect * aRect) +nsImageFrame::IconLoad::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) { - return NS_OK; -} - -NS_IMETHODIMP -nsImageFrame::IconLoad::OnStopFrame(imgIRequest *aRequest, - uint32_t aFrame) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsImageFrame::IconLoad::OnStopContainer(imgIRequest *aRequest, - imgIContainer *aContainer) -{ - return NS_OK; -} + if (aType != imgINotificationObserver::STOP_REQUEST && + aType != imgINotificationObserver::FRAME_CHANGED) { + return NS_OK; + } -NS_IMETHODIMP -nsImageFrame::IconLoad::OnStopDecode(imgIRequest *aRequest, - nsresult status, - const PRUnichar *statusArg) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsImageFrame::IconLoad::OnImageIsAnimated(imgIRequest *aRequest) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsImageFrame::IconLoad::OnStopRequest(imgIRequest *aRequest, - bool aIsLastPart) -{ nsTObserverArray<nsImageFrame*>::ForwardIterator iter(mIconObservers); nsImageFrame *frame; while (iter.HasMore()) { frame = iter.GetNext(); frame->InvalidateFrame(); } return NS_OK; } -NS_IMETHODIMP -nsImageFrame::IconLoad::OnDiscard(imgIRequest *aRequest) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsImageFrame::IconLoad::FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect) -{ - nsTObserverArray<nsImageFrame*>::ForwardIterator iter(mIconObservers); - nsImageFrame *frame; - while (iter.HasMore()) { - frame = iter.GetNext(); - frame->InvalidateFrame(); - } - - return NS_OK; -} - - - -NS_IMPL_ISUPPORTS2(nsImageListener, imgIDecoderObserver, imgIContainerObserver) +NS_IMPL_ISUPPORTS1(nsImageListener, imgINotificationObserver) nsImageListener::nsImageListener(nsImageFrame *aFrame) : mFrame(aFrame) { } nsImageListener::~nsImageListener() { } -NS_IMETHODIMP nsImageListener::OnStartContainer(imgIRequest *aRequest, - imgIContainer *aImage) -{ - if (!mFrame) - return NS_ERROR_FAILURE; - - return mFrame->OnStartContainer(aRequest, aImage); -} - -NS_IMETHODIMP nsImageListener::OnDataAvailable(imgIRequest *aRequest, - bool aCurrentFrame, - const nsIntRect *aRect) +NS_IMETHODIMP +nsImageListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) { if (!mFrame) return NS_ERROR_FAILURE; - return mFrame->OnDataAvailable(aRequest, aCurrentFrame, aRect); -} - -NS_IMETHODIMP nsImageListener::OnStopDecode(imgIRequest *aRequest, - nsresult status, - const PRUnichar *statusArg) -{ - if (!mFrame) - return NS_ERROR_FAILURE; - - return mFrame->OnStopDecode(aRequest, status, statusArg); -} - -NS_IMETHODIMP nsImageListener::FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect) -{ - if (!mFrame) - return NS_ERROR_FAILURE; - - return mFrame->FrameChanged(aRequest, aContainer, aDirtyRect); + return mFrame->Notify(aRequest, aType, aData); } static bool IsInAutoWidthTableCellForQuirk(nsIFrame *aFrame) { if (eCompatibility_NavQuirks != aFrame->PresContext()->CompatibilityMode()) return false; // Check if the parent of the closest nsBlockFrame has auto width.
--- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -7,18 +7,17 @@ #ifndef nsImageFrame_h___ #define nsImageFrame_h___ #include "nsSplittableFrame.h" #include "nsIIOService.h" #include "nsIObserver.h" -#include "nsStubImageDecoderObserver.h" -#include "imgIDecoderObserver.h" +#include "imgINotificationObserver.h" #include "nsDisplayList.h" #include "imgIContainer.h" #include "mozilla/Attributes.h" class nsIFrame; class nsImageMap; class nsIURI; @@ -35,33 +34,24 @@ class nsImageLoadingContent; namespace mozilla { namespace layers { class ImageContainer; class ImageLayer; class LayerManager; } } -class nsImageListener : public nsStubImageDecoderObserver +class nsImageListener : public imgINotificationObserver { public: nsImageListener(nsImageFrame *aFrame); virtual ~nsImageListener(); NS_DECL_ISUPPORTS - // imgIDecoderObserver (override nsStubImageDecoderObserver) - NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage); - NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, bool aCurrentFrame, - const nsIntRect *aRect); - NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status, - const PRUnichar *statusArg); - // imgIContainerObserver (override nsStubImageDecoderObserver) - NS_IMETHOD FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *dirtyRect); + NS_DECL_IMGINOTIFICATIONOBSERVER void SetFrame(nsImageFrame *frame) { mFrame = frame; } private: nsImageFrame *mFrame; }; #define IMAGE_SIZECONSTRAINED NS_FRAME_STATE_BIT(20) @@ -132,16 +122,18 @@ public: static void ReleaseGlobals() { if (gIconLoad) { gIconLoad->Shutdown(); NS_RELEASE(gIconLoad); } NS_IF_RELEASE(sIOService); } + nsresult Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData); + /** * Function to test whether aContent, which has aStyleContext as its style, * should get an image frame. Note that this method is only used by the * frame constructor; it's only here because it uses gIconLoad for now. */ static bool ShouldCreateImageFrameFor(mozilla::dom::Element* aElement, nsStyleContext* aStyleContext); @@ -216,24 +208,21 @@ protected: void PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt, const nsRect& aDirtyRect, imgIContainer* aImage, uint32_t aFlags); protected: friend class nsImageListener; friend class nsImageLoadingContent; nsresult OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage); - nsresult OnDataAvailable(imgIRequest *aRequest, bool aCurrentFrame, - const nsIntRect *rect); + nsresult OnDataAvailable(imgIRequest *aRequest, const nsIntRect *rect); nsresult OnStopDecode(imgIRequest *aRequest, - nsresult aStatus, - const PRUnichar *aStatusArg); + nsresult aStatus); nsresult FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect); + imgIContainer *aContainer); /** * Notification that aRequest will now be the current request. */ void NotifyNewCurrentRequest(imgIRequest *aRequest, nsresult aStatus); private: // random helpers inline void SpecToURI(const nsAString& aSpec, nsIIOService *aIOService, @@ -283,17 +272,17 @@ private: /** * Function to convert a dirty rect in the source image to a dirty * rect for the image frame. */ nsRect SourceRectToDest(const nsIntRect & aRect); nsImageMap* mImageMap; - nsCOMPtr<imgIDecoderObserver> mListener; + nsCOMPtr<imgINotificationObserver> mListener; nsSize mComputedSize; nsIFrame::IntrinsicSize mIntrinsicSize; nsSize mIntrinsicRatio; bool mDisplayingIcon; static nsIIOService* sIOService; @@ -306,28 +295,27 @@ private: // LoadIcons: initiate the loading of the static icons used to show // loading / broken images nsresult LoadIcons(nsPresContext *aPresContext); nsresult LoadIcon(const nsAString& aSpec, nsPresContext *aPresContext, imgIRequest **aRequest); class IconLoad MOZ_FINAL : public nsIObserver, - public imgIDecoderObserver { + public imgINotificationObserver { // private class that wraps the data and logic needed for // broken image and loading image icons public: IconLoad(); void Shutdown(); NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER - NS_DECL_IMGICONTAINEROBSERVER - NS_DECL_IMGIDECODEROBSERVER + NS_DECL_IMGINOTIFICATIONOBSERVER void AddIconObserver(nsImageFrame *frame) { NS_ABORT_IF_FALSE(!mIconObservers.Contains(frame), "Observer shouldn't aleady be in array"); mIconObservers.AppendElement(frame); } void RemoveIconObserver(nsImageFrame *frame) {
--- a/layout/style/ImageLoader.cpp +++ b/layout/style/ImageLoader.cpp @@ -51,18 +51,18 @@ ImageLoader::DropDocumentReference() void ImageLoader::AssociateRequestToFrame(imgIRequest* aRequest, nsIFrame* aFrame) { MOZ_ASSERT(mRequestToFrameMap.IsInitialized() && mFrameToRequestMap.IsInitialized() && mImages.IsInitialized()); - nsCOMPtr<imgIDecoderObserver> observer; - aRequest->GetDecoderObserver(getter_AddRefs(observer)); + nsCOMPtr<imgINotificationObserver> observer; + aRequest->GetNotificationObserver(getter_AddRefs(observer)); if (!observer) { // The request has already been canceled, so ignore it. This is ok because // we're not going to get any more notifications from a canceled request. return; } MOZ_ASSERT(observer == this); @@ -152,18 +152,18 @@ ImageLoader::DisassociateRequestFromFram RequestSet* requestSet = nullptr; MOZ_ASSERT(mRequestToFrameMap.IsInitialized() && mFrameToRequestMap.IsInitialized() && mImages.IsInitialized()); #ifdef DEBUG { - nsCOMPtr<imgIDecoderObserver> observer; - aRequest->GetDecoderObserver(getter_AddRefs(observer)); + nsCOMPtr<imgINotificationObserver> observer; + aRequest->GetNotificationObserver(getter_AddRefs(observer)); MOZ_ASSERT(!observer || observer == this); } #endif mRequestToFrameMap.Get(aRequest, &frameSet); mFrameToRequestMap.Get(aFrame, &requestSet); if (frameSet) { @@ -329,35 +329,58 @@ ImageLoader::DoRedraw(FrameSet* aFrameSe } } } NS_IMPL_ADDREF(ImageLoader) NS_IMPL_RELEASE(ImageLoader) NS_INTERFACE_MAP_BEGIN(ImageLoader) - NS_INTERFACE_MAP_ENTRY(imgIDecoderObserver) - NS_INTERFACE_MAP_ENTRY(imgIContainerObserver) + NS_INTERFACE_MAP_ENTRY(imgINotificationObserver) NS_INTERFACE_MAP_ENTRY(imgIOnloadBlocker) NS_INTERFACE_MAP_END NS_IMETHODIMP +ImageLoader::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) +{ + if (aType == imgINotificationObserver::START_CONTAINER) { + nsCOMPtr<imgIContainer> image; + aRequest->GetImage(getter_AddRefs(image)); + return OnStartContainer(aRequest, image); + } + + if (aType == imgINotificationObserver::IS_ANIMATED) { + return OnImageIsAnimated(aRequest); + } + + if (aType == imgINotificationObserver::STOP_FRAME) { + return OnStopFrame(aRequest); + } + + if (aType == imgINotificationObserver::FRAME_CHANGED) { + return FrameChanged(aRequest); + } + + return NS_OK; +} + +nsresult ImageLoader::OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage) { nsPresContext* presContext = GetPresContext(); if (!presContext) { return NS_OK; } aImage->SetAnimationMode(presContext->ImageAnimationMode()); return NS_OK; } -NS_IMETHODIMP +nsresult ImageLoader::OnImageIsAnimated(imgIRequest* aRequest) { if (!mDocument) { return NS_OK; } FrameSet* frameSet = nullptr; if (!mRequestToFrameMap.Get(aRequest, &frameSet)) { @@ -371,18 +394,18 @@ ImageLoader::OnImageIsAnimated(imgIReque nsLayoutUtils::RegisterImageRequest(presContext, aRequest, nullptr); } return NS_OK; } -NS_IMETHODIMP -ImageLoader::OnStopFrame(imgIRequest *aRequest, uint32_t aFrame) +nsresult +ImageLoader::OnStopFrame(imgIRequest *aRequest) { if (!mDocument || mInClone) { return NS_OK; } FrameSet* frameSet = nullptr; if (!mRequestToFrameMap.Get(aRequest, &frameSet)) { return NS_OK; @@ -390,20 +413,18 @@ ImageLoader::OnStopFrame(imgIRequest *aR NS_ASSERTION(frameSet, "This should never be null!"); DoRedraw(frameSet); return NS_OK; } -NS_IMETHODIMP -ImageLoader::FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect) +nsresult +ImageLoader::FrameChanged(imgIRequest *aRequest) { if (!mDocument || mInClone) { return NS_OK; } FrameSet* frameSet = nullptr; if (!mRequestToFrameMap.Get(aRequest, &frameSet)) { return NS_OK;
--- a/layout/style/ImageLoader.h +++ b/layout/style/ImageLoader.h @@ -7,29 +7,29 @@ #include "nsAutoPtr.h" #include "nsClassHashtable.h" #include "nsHashKeys.h" #include "nsInterfaceHashtable.h" #include "nsCSSValue.h" #include "imgIRequest.h" #include "imgIOnloadBlocker.h" -#include "nsStubImageDecoderObserver.h" +#include "imgINotificationObserver.h" #include "mozilla/Attributes.h" class nsIFrame; class nsIDocument; class nsPresContext; class nsIURI; class nsIPrincipal; namespace mozilla { namespace css { -class ImageLoader MOZ_FINAL : public nsStubImageDecoderObserver, +class ImageLoader MOZ_FINAL : public imgINotificationObserver, public imgIOnloadBlocker { public: typedef mozilla::css::ImageValue Image; ImageLoader(nsIDocument* aDocument) : mDocument(aDocument), mInClone(false) { @@ -37,29 +37,17 @@ public: mRequestToFrameMap.Init(); mFrameToRequestMap.Init(); mImages.Init(); } NS_DECL_ISUPPORTS NS_DECL_IMGIONLOADBLOCKER - - // imgIDecoderObserver (override nsStubImageDecoderObserver) - NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage); - NS_IMETHOD OnStopFrame(imgIRequest *aRequest, uint32_t aFrame); - NS_IMETHOD OnImageIsAnimated(imgIRequest *aRequest); - // Do not override OnDataAvailable since background images are not - // displayed incrementally; they are displayed after the entire image - // has been loaded. - - // imgIContainerObserver (override nsStubImageDecoderObserver) - NS_IMETHOD FrameChanged(imgIRequest* aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect); + NS_DECL_IMGINOTIFICATIONOBSERVER void DropDocumentReference(); void MaybeRegisterCSSImage(Image* aImage); void DeregisterCSSImage(Image* aImage); void AssociateRequestToFrame(imgIRequest* aRequest, nsIFrame* aFrame); @@ -98,16 +86,24 @@ private: nsPresContext* GetPresContext(); void DoRedraw(FrameSet* aFrameSet); static PLDHashOperator SetAnimationModeEnumerator(nsISupports* aKey, FrameSet* aValue, void* aClosure); + nsresult OnStartContainer(imgIRequest *aRequest, imgIContainer* aImage); + nsresult OnStopFrame(imgIRequest *aRequest); + nsresult OnImageIsAnimated(imgIRequest *aRequest); + nsresult FrameChanged(imgIRequest* aRequest); + // Do not override OnDataAvailable since background images are not + // displayed incrementally; they are displayed after the entire image + // has been loaded. + // A map of imgIRequests to the nsIFrames that are using them. RequestToFrameMap mRequestToFrameMap; // A map of nsIFrames to the imgIRequests they use. FrameToRequestMap mFrameToRequestMap; // A weak pointer to our document. Nulled out by DropDocumentReference. nsIDocument* mDocument;
--- a/layout/svg/nsSVGImageFrame.cpp +++ b/layout/svg/nsSVGImageFrame.cpp @@ -6,44 +6,35 @@ // Keep in (case-insensitive) order: #include "gfxContext.h" #include "gfxMatrix.h" #include "gfxPlatform.h" #include "imgIContainer.h" #include "nsIDOMSVGImageElement.h" #include "nsLayoutUtils.h" #include "nsRenderingContext.h" -#include "nsStubImageDecoderObserver.h" +#include "imgINotificationObserver.h" #include "nsSVGEffects.h" #include "nsSVGImageElement.h" #include "nsSVGPathGeometryFrame.h" #include "nsSVGSVGElement.h" #include "nsSVGUtils.h" #include "SVGContentUtils.h" using namespace mozilla; class nsSVGImageFrame; -class nsSVGImageListener MOZ_FINAL : public nsStubImageDecoderObserver +class nsSVGImageListener MOZ_FINAL : public imgINotificationObserver { public: nsSVGImageListener(nsSVGImageFrame *aFrame); NS_DECL_ISUPPORTS - // imgIDecoderObserver (override nsStubImageDecoderObserver) - NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status, - const PRUnichar *statusArg); - // imgIContainerObserver (override nsStubImageDecoderObserver) - NS_IMETHOD FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect); - // imgIContainerObserver (override nsStubImageDecoderObserver) - NS_IMETHOD OnStartContainer(imgIRequest *aRequest, - imgIContainer *aContainer); + NS_DECL_IMGINOTIFICATIONOBSERVER void SetFrame(nsSVGImageFrame *frame) { mFrame = frame; } private: nsSVGImageFrame *mFrame; }; typedef nsSVGPathGeometryFrame nsSVGImageFrameBase; @@ -93,17 +84,17 @@ public: private: gfxMatrix GetRasterImageTransform(int32_t aNativeWidth, int32_t aNativeHeight, uint32_t aFor); gfxMatrix GetVectorImageTransform(uint32_t aFor); bool TransformContextForPainting(gfxContext* aGfxContext); - nsCOMPtr<imgIDecoderObserver> mListener; + nsCOMPtr<imgINotificationObserver> mListener; nsCOMPtr<imgIContainer> mImageContainer; friend class nsSVGImageListener; }; //---------------------------------------------------------------------- // Implementation @@ -555,55 +546,40 @@ nsSVGImageFrame::GetHitTestFlags() } return flags; } //---------------------------------------------------------------------- // nsSVGImageListener implementation -NS_IMPL_ISUPPORTS2(nsSVGImageListener, - imgIDecoderObserver, - imgIContainerObserver) +NS_IMPL_ISUPPORTS1(nsSVGImageListener, imgINotificationObserver) nsSVGImageListener::nsSVGImageListener(nsSVGImageFrame *aFrame) : mFrame(aFrame) { } -NS_IMETHODIMP nsSVGImageListener::OnStopDecode(imgIRequest *aRequest, - nsresult status, - const PRUnichar *statusArg) -{ - if (!mFrame) - return NS_ERROR_FAILURE; - - nsSVGUtils::InvalidateAndScheduleReflowSVG(mFrame); - return NS_OK; -} - -NS_IMETHODIMP nsSVGImageListener::FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect) +NS_IMETHODIMP +nsSVGImageListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) { if (!mFrame) return NS_ERROR_FAILURE; - // No new dimensions, so we don't need to call - // nsSVGUtils::InvalidateAndScheduleBoundsUpdate. - nsSVGEffects::InvalidateRenderingObservers(mFrame); - nsSVGUtils::InvalidateBounds(mFrame); - return NS_OK; -} + if (aType == imgINotificationObserver::STOP_DECODE) { + nsSVGUtils::InvalidateAndScheduleReflowSVG(mFrame); + } -NS_IMETHODIMP nsSVGImageListener::OnStartContainer(imgIRequest *aRequest, - imgIContainer *aContainer) -{ - // Called once the resource's dimensions have been obtained. + if (aType == imgINotificationObserver::FRAME_CHANGED) { + // No new dimensions, so we don't need to call + // nsSVGUtils::InvalidateAndScheduleBoundsUpdate. + nsSVGEffects::InvalidateRenderingObservers(mFrame); + nsSVGUtils::InvalidateBounds(mFrame); + } - if (!mFrame) - return NS_ERROR_FAILURE; - - mFrame->mImageContainer = aContainer; - nsSVGUtils::InvalidateAndScheduleReflowSVG(mFrame); + if (aType == imgINotificationObserver::START_CONTAINER) { + // Called once the resource's dimensions have been obtained. + aRequest->GetImage(getter_AddRefs(mFrame->mImageContainer)); + nsSVGUtils::InvalidateAndScheduleReflowSVG(mFrame); + } return NS_OK; }
--- a/layout/xul/base/src/nsImageBoxFrame.cpp +++ b/layout/xul/base/src/nsImageBoxFrame.cpp @@ -183,17 +183,17 @@ NS_IMETHODIMP nsImageBoxFrame::Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* aPrevInFlow) { if (!mListener) { nsImageBoxListener *listener = new nsImageBoxListener(); NS_ADDREF(listener); listener->SetFrame(this); - listener->QueryInterface(NS_GET_IID(imgIDecoderObserver), getter_AddRefs(mListener)); + listener->QueryInterface(NS_GET_IID(imgINotificationObserver), getter_AddRefs(mListener)); NS_RELEASE(listener); } mSuppressStyleCheck = true; nsresult rv = nsLeafBoxFrame::Init(aContent, aParent, aPrevInFlow); mSuppressStyleCheck = false; UpdateLoadFlags(); @@ -572,19 +572,50 @@ nsImageBoxFrame::GetType() const #ifdef DEBUG NS_IMETHODIMP nsImageBoxFrame::GetFrameName(nsAString& aResult) const { return MakeFrameName(NS_LITERAL_STRING("ImageBox"), aResult); } #endif +nsresult +nsImageBoxFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) +{ + if (aType == imgINotificationObserver::START_CONTAINER) { + nsCOMPtr<imgIContainer> image; + aRequest->GetImage(getter_AddRefs(image)); + return OnStartContainer(aRequest, image); + } -NS_IMETHODIMP nsImageBoxFrame::OnStartContainer(imgIRequest *request, - imgIContainer *image) + if (aType == imgINotificationObserver::STOP_CONTAINER) { + return OnStopContainer(aRequest); + } + + if (aType == imgINotificationObserver::STOP_DECODE) { + uint32_t imgStatus; + aRequest->GetImageStatus(&imgStatus); + nsresult status = + imgStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK; + return OnStopDecode(aRequest, status); + } + + if (aType == imgINotificationObserver::IS_ANIMATED) { + return OnImageIsAnimated(aRequest); + } + + if (aType == imgINotificationObserver::FRAME_CHANGED) { + return FrameChanged(aRequest); + } + + return NS_OK; +} + +nsresult nsImageBoxFrame::OnStartContainer(imgIRequest *request, + imgIContainer *image) { NS_ENSURE_ARG_POINTER(image); // Ensure the animation (if any) is started. Note: There is no // corresponding call to Decrement for this. This Increment will be // 'cleaned up' by the Request when it is destroyed, but only then. request->IncrementAnimationConsumers(); @@ -598,113 +629,71 @@ NS_IMETHODIMP nsImageBoxFrame::OnStartCo if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) { PresContext()->PresShell()-> FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY); } return NS_OK; } -NS_IMETHODIMP nsImageBoxFrame::OnStopContainer(imgIRequest *request, - imgIContainer *image) +nsresult nsImageBoxFrame::OnStopContainer(imgIRequest *request) { nsBoxLayoutState state(PresContext()); this->Redraw(state); return NS_OK; } -NS_IMETHODIMP nsImageBoxFrame::OnStopDecode(imgIRequest *request, - nsresult aStatus, - const PRUnichar *statusArg) +nsresult nsImageBoxFrame::OnStopDecode(imgIRequest *request, + nsresult aStatus) { if (NS_SUCCEEDED(aStatus)) // Fire an onload DOM event. FireImageDOMEvent(mContent, NS_LOAD); else { // Fire an onerror DOM event. mIntrinsicSize.SizeTo(0, 0); PresContext()->PresShell()-> FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY); FireImageDOMEvent(mContent, NS_LOAD_ERROR); } return NS_OK; } -NS_IMETHODIMP nsImageBoxFrame::OnImageIsAnimated(imgIRequest *aRequest) +nsresult nsImageBoxFrame::OnImageIsAnimated(imgIRequest *aRequest) { // Register with our refresh driver, if we're animated. nsLayoutUtils::RegisterImageRequest(PresContext(), aRequest, &mRequestRegistered); return NS_OK; } -NS_IMETHODIMP nsImageBoxFrame::FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect) +nsresult nsImageBoxFrame::FrameChanged(imgIRequest *aRequest) { if ((0 == mRect.width) || (0 == mRect.height)) { return NS_OK; } InvalidateLayer(nsDisplayItem::TYPE_XUL_IMAGE); return NS_OK; } -NS_IMPL_ISUPPORTS2(nsImageBoxListener, imgIDecoderObserver, imgIContainerObserver) +NS_IMPL_ISUPPORTS1(nsImageBoxListener, imgINotificationObserver) nsImageBoxListener::nsImageBoxListener() { } nsImageBoxListener::~nsImageBoxListener() { } -NS_IMETHODIMP nsImageBoxListener::OnStartContainer(imgIRequest *request, - imgIContainer *image) -{ - if (!mFrame) - return NS_OK; - - return mFrame->OnStartContainer(request, image); -} - -NS_IMETHODIMP nsImageBoxListener::OnStopContainer(imgIRequest *request, - imgIContainer *image) +NS_IMETHODIMP +nsImageBoxListener::Notify(imgIRequest *request, int32_t aType, const nsIntRect* aData) { if (!mFrame) return NS_OK; - return mFrame->OnStopContainer(request, image); -} - -NS_IMETHODIMP nsImageBoxListener::OnStopDecode(imgIRequest *request, - nsresult status, - const PRUnichar *statusArg) -{ - if (!mFrame) - return NS_OK; - - return mFrame->OnStopDecode(request, status, statusArg); + return mFrame->Notify(request, aType, aData); } - -NS_IMETHODIMP nsImageBoxListener::OnImageIsAnimated(imgIRequest* aRequest) -{ - if (!mFrame) - return NS_OK; - - return mFrame->OnImageIsAnimated(aRequest); -} - -NS_IMETHODIMP nsImageBoxListener::FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect) -{ - if (!mFrame) - return NS_ERROR_FAILURE; - - return mFrame->FrameChanged(aRequest, aContainer, aDirtyRect); -} -
--- a/layout/xul/base/src/nsImageBoxFrame.h +++ b/layout/xul/base/src/nsImageBoxFrame.h @@ -6,40 +6,30 @@ #define nsImageBoxFrame_h___ #include "mozilla/Attributes.h" #include "nsLeafBoxFrame.h" #include "imgILoader.h" #include "imgIRequest.h" #include "imgIContainer.h" -#include "nsStubImageDecoderObserver.h" +#include "imgINotificationObserver.h" class nsImageBoxFrame; class nsDisplayXULImage; -class nsImageBoxListener : public nsStubImageDecoderObserver +class nsImageBoxListener : public imgINotificationObserver { public: nsImageBoxListener(); virtual ~nsImageBoxListener(); NS_DECL_ISUPPORTS - // imgIDecoderObserver (override nsStubImageDecoderObserver) - NS_IMETHOD OnStartContainer(imgIRequest *request, imgIContainer *image); - NS_IMETHOD OnStopContainer(imgIRequest *request, imgIContainer *image); - NS_IMETHOD OnStopDecode(imgIRequest *request, nsresult status, - const PRUnichar *statusArg); - NS_IMETHOD OnImageIsAnimated(imgIRequest* aRequest); - - // imgIContainerObserver (override nsStubImageDecoderObserver) - NS_IMETHOD FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect); + NS_DECL_IMGINOTIFICATIONOBSERVER void SetFrame(nsImageBoxFrame *frame) { mFrame = frame; } private: nsImageBoxFrame *mFrame; }; class nsImageBoxFrame : public nsLeafBoxFrame @@ -48,16 +38,18 @@ public: friend class nsDisplayXULImage; NS_DECL_FRAMEARENA_HELPERS virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState); virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState); virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; virtual void MarkIntrinsicWidthsDirty() MOZ_OVERRIDE; + nsresult Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData); + friend nsIFrame* NS_NewImageBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); NS_IMETHOD Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* asPrevInFlow) MOZ_OVERRIDE; NS_IMETHOD AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, @@ -84,51 +76,45 @@ public: * image using the new load flags. */ void UpdateLoadFlags(); NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) MOZ_OVERRIDE; - NS_IMETHOD OnStartContainer(imgIRequest *request, imgIContainer *image); - NS_IMETHOD OnStopContainer(imgIRequest *request, imgIContainer *image); - NS_IMETHOD OnStopDecode(imgIRequest *request, - nsresult status, - const PRUnichar *statusArg); - NS_IMETHOD OnImageIsAnimated(imgIRequest* aRequest); - - NS_IMETHOD FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect); - virtual ~nsImageBoxFrame(); void PaintImage(nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsPoint aPt, uint32_t aFlags); already_AddRefed<mozilla::layers::ImageContainer> GetContainer(); protected: nsImageBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext); virtual void GetImageSize(); private: + nsresult OnStartContainer(imgIRequest *request, imgIContainer *image); + nsresult OnStopContainer(imgIRequest *request); + nsresult OnStopDecode(imgIRequest *request, nsresult status); + nsresult OnImageIsAnimated(imgIRequest* aRequest); + nsresult FrameChanged(imgIRequest *aRequest); nsRect mSubRect; ///< If set, indicates that only the portion of the image specified by the rect should be used. nsSize mIntrinsicSize; nsSize mImageSize; // Boolean variable to determine if the current image request has been // registered with the refresh driver. bool mRequestRegistered; nsCOMPtr<imgIRequest> mImageRequest; - nsCOMPtr<imgIDecoderObserver> mListener; + nsCOMPtr<imgINotificationObserver> mListener; int32_t mLoadFlags; bool mUseSrcAttr; ///< Whether or not the image src comes from an attribute. bool mSuppressStyleCheck; }; // class nsImageBoxFrame class nsDisplayXULImage : public nsDisplayImageContainer {
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp +++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp @@ -2112,18 +2112,18 @@ nsTreeBodyFrame::GetImage(int32_t aRowIn bool animated = true; // Assuming animated is the safe option // We can only call GetAnimated if we're decoded if (*aResult && (status & imgIRequest::STATUS_DECODE_COMPLETE)) (*aResult)->GetAnimated(&animated); if ((!(status & imgIRequest::STATUS_LOAD_COMPLETE)) || animated) { // We either aren't done loading, or we're animating. Add our row as a listener for invalidations. - nsCOMPtr<imgIDecoderObserver> obs; - imgReq->GetDecoderObserver(getter_AddRefs(obs)); + nsCOMPtr<imgINotificationObserver> obs; + imgReq->GetNotificationObserver(getter_AddRefs(obs)); if (obs) { static_cast<nsTreeImageListener*> (obs.get())->AddCell(aRowIndex, aCol); } return NS_OK; } } @@ -2135,21 +2135,21 @@ nsTreeBodyFrame::GetImage(int32_t aRowIn if (!listener) return NS_ERROR_OUT_OF_MEMORY; if (!mCreatedListeners.PutEntry(listener)) { return NS_ERROR_FAILURE; } listener->AddCell(aRowIndex, aCol); - nsCOMPtr<imgIDecoderObserver> imgDecoderObserver = listener; + nsCOMPtr<imgINotificationObserver> imgNotificationObserver = listener; nsCOMPtr<imgIRequest> imageRequest; if (styleRequest) { - styleRequest->Clone(imgDecoderObserver, getter_AddRefs(imageRequest)); + styleRequest->Clone(imgNotificationObserver, getter_AddRefs(imageRequest)); } else { nsIDocument* doc = mContent->GetDocument(); if (!doc) // The page is currently being torn down. Why bother. return NS_ERROR_FAILURE; nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI(); @@ -2164,17 +2164,17 @@ nsTreeBodyFrame::GetImage(int32_t aRowIn // XXXbz what's the origin principal for this stuff that comes from our // view? I guess we should assume that it's the node's principal... if (nsContentUtils::CanLoadImage(srcURI, mContent, doc, mContent->NodePrincipal())) { nsresult rv = nsContentUtils::LoadImage(srcURI, doc, mContent->NodePrincipal(), doc->GetDocumentURI(), - imgDecoderObserver, + imgNotificationObserver, nsIRequest::LOAD_NORMAL, getter_AddRefs(imageRequest)); NS_ENSURE_SUCCESS(rv, rv); } } listener->UnsuppressInvalidation(); @@ -2182,17 +2182,17 @@ nsTreeBodyFrame::GetImage(int32_t aRowIn return NS_ERROR_FAILURE; // We don't want discarding/decode-on-draw for xul images imageRequest->StartDecoding(); imageRequest->LockImage(); // In a case it was already cached. imageRequest->GetImage(aResult); - nsTreeImageCacheEntry cacheEntry(imageRequest, imgDecoderObserver); + nsTreeImageCacheEntry cacheEntry(imageRequest, imgNotificationObserver); mImageCache.Put(imageSrc, cacheEntry); } return NS_OK; } nsRect nsTreeBodyFrame::GetImageSize(int32_t aRowIndex, nsTreeColumn* aCol, bool aUseContext, nsStyleContext* aStyleContext) {
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.h +++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.h @@ -15,33 +15,33 @@ #include "nsITimer.h" #include "nsIReflowCallback.h" #include "nsTArray.h" #include "nsTreeStyleCache.h" #include "nsTreeColumns.h" #include "nsAutoPtr.h" #include "nsDataHashtable.h" #include "imgIRequest.h" -#include "imgIDecoderObserver.h" +#include "imgINotificationObserver.h" #include "nsScrollbarFrame.h" #include "nsThreadUtils.h" #include "mozilla/LookAndFeel.h" class nsOverflowChecker; class nsTreeImageListener; // An entry in the tree's image cache struct nsTreeImageCacheEntry { nsTreeImageCacheEntry() {} - nsTreeImageCacheEntry(imgIRequest *aRequest, imgIDecoderObserver *aListener) + nsTreeImageCacheEntry(imgIRequest *aRequest, imgINotificationObserver *aListener) : request(aRequest), listener(aListener) {} nsCOMPtr<imgIRequest> request; - nsCOMPtr<imgIDecoderObserver> listener; + nsCOMPtr<imgINotificationObserver> listener; }; // The actual frame that paints the cells and rows. class nsTreeBodyFrame MOZ_FINAL : public nsLeafBoxFrame , public nsICSSPseudoComparator , public nsIScrollbarMediator , public nsIReflowCallback
--- a/layout/xul/base/src/tree/src/nsTreeImageListener.cpp +++ b/layout/xul/base/src/tree/src/nsTreeImageListener.cpp @@ -3,67 +3,52 @@ * 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/. */ #include "nsTreeImageListener.h" #include "nsITreeBoxObject.h" #include "imgIRequest.h" #include "imgIContainer.h" -NS_IMPL_ISUPPORTS2(nsTreeImageListener, imgIDecoderObserver, imgIContainerObserver) +NS_IMPL_ISUPPORTS1(nsTreeImageListener, imgINotificationObserver) nsTreeImageListener::nsTreeImageListener(nsTreeBodyFrame* aTreeFrame) : mTreeFrame(aTreeFrame), mInvalidationSuppressed(true), mInvalidationArea(nullptr) { } nsTreeImageListener::~nsTreeImageListener() { delete mInvalidationArea; } NS_IMETHODIMP -nsTreeImageListener::OnImageIsAnimated(imgIRequest *aRequest) +nsTreeImageListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) { - if (!mTreeFrame) { - return NS_OK; + if (aType == imgINotificationObserver::IS_ANIMATED) { + return mTreeFrame ? mTreeFrame->OnImageIsAnimated(aRequest) : NS_OK; } - return mTreeFrame->OnImageIsAnimated(aRequest); -} + if (aType == imgINotificationObserver::START_CONTAINER) { + // Ensure the animation (if any) is started. Note: There is no + // corresponding call to Decrement for this. This Increment will be + // 'cleaned up' by the Request when it is destroyed, but only then. + aRequest->IncrementAnimationConsumers(); + } -NS_IMETHODIMP nsTreeImageListener::OnStartContainer(imgIRequest *aRequest, - imgIContainer *aImage) -{ - // Ensure the animation (if any) is started. Note: There is no - // corresponding call to Decrement for this. This Increment will be - // 'cleaned up' by the Request when it is destroyed, but only then. - aRequest->IncrementAnimationConsumers(); + if (aType == imgINotificationObserver::DATA_AVAILABLE || + aType == imgINotificationObserver::FRAME_CHANGED) { + Invalidate(); + } + return NS_OK; } -NS_IMETHODIMP nsTreeImageListener::OnDataAvailable(imgIRequest *aRequest, - bool aCurrentFrame, - const nsIntRect *aRect) -{ - Invalidate(); - return NS_OK; -} - -NS_IMETHODIMP nsTreeImageListener::FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect) -{ - Invalidate(); - return NS_OK; -} - - void nsTreeImageListener::AddCell(int32_t aIndex, nsITreeColumn* aCol) { if (!mInvalidationArea) { mInvalidationArea = new InvalidationArea(aCol); mInvalidationArea->AddRow(aIndex); } else {
--- a/layout/xul/base/src/tree/src/nsTreeImageListener.h +++ b/layout/xul/base/src/tree/src/nsTreeImageListener.h @@ -4,37 +4,28 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsTreeImageListener_h__ #define nsTreeImageListener_h__ #include "nsString.h" #include "nsCOMPtr.h" #include "nsITreeColumns.h" -#include "nsStubImageDecoderObserver.h" #include "nsTreeBodyFrame.h" #include "mozilla/Attributes.h" // This class handles image load observation. -class nsTreeImageListener MOZ_FINAL : public nsStubImageDecoderObserver +class nsTreeImageListener MOZ_FINAL : public imgINotificationObserver { public: nsTreeImageListener(nsTreeBodyFrame *aTreeFrame); ~nsTreeImageListener(); NS_DECL_ISUPPORTS - // imgIDecoderObserver (override nsStubImageDecoderObserver) - NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage); - NS_IMETHOD OnImageIsAnimated(imgIRequest* aRequest); - NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, bool aCurrentFrame, - const nsIntRect *aRect); - // imgIContainerObserver (override nsStubImageDecoderObserver) - NS_IMETHOD FrameChanged(imgIRequest *aRequest, - imgIContainer *aContainer, - const nsIntRect *aDirtyRect); + NS_DECL_IMGINOTIFICATIONOBSERVER NS_IMETHOD ClearFrame(); friend class nsTreeBodyFrame; protected: void UnsuppressInvalidation() { mInvalidationSuppressed = false; } void Invalidate();
--- a/toolkit/system/gnome/nsAlertsIconListener.cpp +++ b/toolkit/system/gnome/nsAlertsIconListener.cpp @@ -46,18 +46,18 @@ static void notify_closed_marshal(GClosu NS_ABORT_IF_FALSE(n_param_values >= 1, "No object in params"); nsAlertsIconListener* alert = static_cast<nsAlertsIconListener*>(closure->data); alert->SendClosed(); NS_RELEASE(alert); } -NS_IMPL_ISUPPORTS4(nsAlertsIconListener, imgIContainerObserver, - imgIDecoderObserver, nsIObserver, nsISupportsWeakReference) +NS_IMPL_ISUPPORTS3(nsAlertsIconListener, imgINotificationObserver, + nsIObserver, nsISupportsWeakReference) nsAlertsIconListener::nsAlertsIconListener() : mLoadedFrame(false), mNotification(NULL) { if (!libNotifyHandle && !libNotifyNotAvail) { libNotifyHandle = dlopen("libnotify.so.4", RTLD_LAZY); if (!libNotifyHandle) { @@ -85,110 +85,49 @@ nsAlertsIconListener::nsAlertsIconListen nsAlertsIconListener::~nsAlertsIconListener() { if (mIconRequest) mIconRequest->CancelAndForgetObserver(NS_BINDING_ABORTED); // Don't dlclose libnotify as it uses atexit(). } NS_IMETHODIMP -nsAlertsIconListener::OnStartRequest(imgIRequest* aRequest) +nsAlertsIconListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) { - return NS_OK; -} - -NS_IMETHODIMP -nsAlertsIconListener::OnStartDecode(imgIRequest* aRequest) -{ - return NS_OK; -} - + if (aType == imgINotificationObserver::STOP_REQUEST) { + return OnStopRequest(aRequest); + } -NS_IMETHODIMP -nsAlertsIconListener::OnStartContainer(imgIRequest* aRequest, - imgIContainer* aContainer) -{ - return NS_OK; -} + if (aType == imgINotificationObserver::STOP_FRAME) { + return OnStopFrame(aRequest); + } - -NS_IMETHODIMP -nsAlertsIconListener::OnStartFrame(imgIRequest* aRequest, - uint32_t aFrame) -{ return NS_OK; } - -NS_IMETHODIMP -nsAlertsIconListener::OnDataAvailable(imgIRequest* aRequest, - bool aCurrentFrame, - const nsIntRect* aRect) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsAlertsIconListener::OnStopContainer(imgIRequest* aRequest, - imgIContainer* aContainer) -{ - return NS_OK; -} - - -NS_IMETHODIMP -nsAlertsIconListener::OnStopDecode(imgIRequest* aRequest, - nsresult status, - const PRUnichar* statusArg) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsAlertsIconListener::FrameChanged(imgIRequest* aRequest, - imgIContainer* aContainer, - const nsIntRect* aDirtyRect) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsAlertsIconListener::OnStopRequest(imgIRequest* aRequest, - bool aIsLastPart) +nsresult +nsAlertsIconListener::OnStopRequest(imgIRequest* aRequest) { uint32_t imgStatus = imgIRequest::STATUS_ERROR; nsresult rv = aRequest->GetImageStatus(&imgStatus); NS_ENSURE_SUCCESS(rv, rv); if (imgStatus == imgIRequest::STATUS_ERROR && !mLoadedFrame) { // We have an error getting the image. Display the notification with no icon. ShowAlert(NULL); } if (mIconRequest) { mIconRequest->Cancel(NS_BINDING_ABORTED); mIconRequest = nullptr; } return NS_OK; } -NS_IMETHODIMP -nsAlertsIconListener::OnDiscard(imgIRequest *aRequest) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsAlertsIconListener::OnImageIsAnimated(imgIRequest *aRequest) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsAlertsIconListener::OnStopFrame(imgIRequest* aRequest, - uint32_t aFrame) +nsresult +nsAlertsIconListener::OnStopFrame(imgIRequest* aRequest) { if (aRequest != mIconRequest) return NS_ERROR_FAILURE; if (mLoadedFrame) return NS_OK; // only use one frame nsCOMPtr<imgIContainer> image;
--- a/toolkit/system/gnome/nsAlertsIconListener.h +++ b/toolkit/system/gnome/nsAlertsIconListener.h @@ -2,51 +2,53 @@ /* 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/. */ #ifndef nsAlertsIconListener_h__ #define nsAlertsIconListener_h__ #include "nsCOMPtr.h" -#include "imgIDecoderObserver.h" +#include "imgINotificationObserver.h" #include "nsStringAPI.h" #include "nsIObserver.h" #include "nsWeakReference.h" #include <gdk-pixbuf/gdk-pixbuf.h> class imgIRequest; struct NotifyNotification; -class nsAlertsIconListener : public imgIDecoderObserver, +class nsAlertsIconListener : public imgINotificationObserver, public nsIObserver, public nsSupportsWeakReference { public: NS_DECL_ISUPPORTS - NS_DECL_IMGICONTAINEROBSERVER - NS_DECL_IMGIDECODEROBSERVER + NS_DECL_IMGINOTIFICATIONOBSERVER NS_DECL_NSIOBSERVER nsAlertsIconListener(); virtual ~nsAlertsIconListener(); nsresult InitAlertAsync(const nsAString & aImageUrl, const nsAString & aAlertTitle, const nsAString & aAlertText, bool aAlertTextClickable, const nsAString & aAlertCookie, nsIObserver * aAlertListener); void SendCallback(); void SendClosed(); protected: + nsresult OnStopRequest(imgIRequest* aRequest); + nsresult OnStopFrame(imgIRequest* aRequest); + /** * The only difference between libnotify.so.4 and libnotify.so.1 for these symbols * is that notify_notification_new takes three arguments in libnotify.so.4 and * four in libnotify.so.1. * Passing the fourth argument as NULL is binary compatible. */ typedef void (*NotifyActionCallback)(NotifyNotification*, char*, gpointer); typedef bool (*notify_is_initted_t)(void);
--- a/widget/cocoa/nsMenuItemIconX.h +++ b/widget/cocoa/nsMenuItemIconX.h @@ -6,38 +6,37 @@ /* * Retrieves and displays icons in native menu items on Mac OS X. */ #ifndef nsMenuItemIconX_h_ #define nsMenuItemIconX_h_ #include "nsCOMPtr.h" -#include "imgIDecoderObserver.h" +#include "imgINotificationObserver.h" class nsIURI; class nsIContent; class imgIRequest; class nsMenuObjectX; #import <Cocoa/Cocoa.h> -class nsMenuItemIconX : public imgIDecoderObserver +class nsMenuItemIconX : public imgINotificationObserver { public: nsMenuItemIconX(nsMenuObjectX* aMenuItem, nsIContent* aContent, NSMenuItem* aNativeMenuItem); private: virtual ~nsMenuItemIconX(); public: NS_DECL_ISUPPORTS - NS_DECL_IMGICONTAINEROBSERVER - NS_DECL_IMGIDECODEROBSERVER + NS_DECL_IMGINOTIFICATIONOBSERVER // SetupIcon succeeds if it was able to set up the icon, or if there should // be no icon, in which case it clears any existing icon but still succeeds. nsresult SetupIcon(); // GetIconURI fails if the item should not have any icon. nsresult GetIconURI(nsIURI** aIconURI); @@ -47,16 +46,18 @@ public: // Unless we take precautions, we may outlive the object that created us // (mMenuObject, which owns our native menu item (mNativeMenuItem)). // Destroy() should be called from mMenuObject's destructor to prevent // this from happening. See bug 499600. void Destroy(); protected: + nsresult OnStopFrame(imgIRequest* aRequest); + nsCOMPtr<nsIContent> mContent; nsCOMPtr<imgIRequest> mIconRequest; nsMenuObjectX* mMenuObject; // [weak] nsIntRect mImageRegionRect; bool mLoadedIcon; bool mSetIcon; NSMenuItem* mNativeMenuItem; // [weak] };
--- a/widget/cocoa/nsMenuItemIconX.mm +++ b/widget/cocoa/nsMenuItemIconX.mm @@ -37,17 +37,17 @@ static const uint32_t kIconComponents = static const uint32_t kIconBitsPerPixel = kIconBitsPerComponent * kIconComponents; static const uint32_t kIconBytesPerRow = kIconWidth * kIconBitsPerPixel / 8; static const uint32_t kIconBytes = kIconBytesPerRow * kIconHeight; typedef NS_STDCALL_FUNCPROTO(nsresult, GetRectSideMethod, nsIDOMRect, GetBottom, (nsIDOMCSSPrimitiveValue**)); -NS_IMPL_ISUPPORTS2(nsMenuItemIconX, imgIContainerObserver, imgIDecoderObserver) +NS_IMPL_ISUPPORTS1(nsMenuItemIconX, imgINotificationObserver) nsMenuItemIconX::nsMenuItemIconX(nsMenuObjectX* aMenuItem, nsIContent* aContent, NSMenuItem* aNativeMenuItem) : mContent(aContent) , mMenuObject(aMenuItem) , mLoadedIcon(false) , mSetIcon(false) @@ -313,67 +313,38 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconU mIconRequest->StartDecoding(); return NS_OK; NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } // -// imgIContainerObserver +// imgINotificationObserver // NS_IMETHODIMP -nsMenuItemIconX::FrameChanged(imgIRequest* aRequest, - imgIContainer* aContainer, - const nsIntRect* aDirtyRect) +nsMenuItemIconX::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) { - return NS_OK; -} + if (aType == imgINotificationObserver::STOP_FRAME) { + return OnStopFrame(aRequest); + } -// -// imgIDecoderObserver -// + if (aType == imgINotificationObserver::STOP_REQUEST) { + if (mIconRequest && mIconRequest == aRequest) { + mIconRequest->Cancel(NS_BINDING_ABORTED); + mIconRequest = nullptr; + } + } -NS_IMETHODIMP -nsMenuItemIconX::OnStartRequest(imgIRequest* aRequest) -{ return NS_OK; } -NS_IMETHODIMP -nsMenuItemIconX::OnStartDecode(imgIRequest* aRequest) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMenuItemIconX::OnStartContainer(imgIRequest* aRequest, - imgIContainer* aContainer) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMenuItemIconX::OnStartFrame(imgIRequest* aRequest, uint32_t aFrame) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMenuItemIconX::OnDataAvailable(imgIRequest* aRequest, - bool aCurrentFrame, - const nsIntRect* aRect) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMenuItemIconX::OnStopFrame(imgIRequest* aRequest, - uint32_t aFrame) +nsresult +nsMenuItemIconX::OnStopFrame(imgIRequest* aRequest) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; if (aRequest != mIconRequest) return NS_ERROR_FAILURE; // Only support one frame. if (mLoadedIcon) @@ -486,46 +457,8 @@ nsMenuItemIconX::OnStopFrame(imgIRequest mLoadedIcon = true; mSetIcon = true; return NS_OK; NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } - -NS_IMETHODIMP -nsMenuItemIconX::OnStopContainer(imgIRequest* aRequest, - imgIContainer* aContainer) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMenuItemIconX::OnStopDecode(imgIRequest* aRequest, - nsresult status, - const PRUnichar* statusArg) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMenuItemIconX::OnStopRequest(imgIRequest* aRequest, - bool aIsLastPart) -{ - if (mIconRequest && mIconRequest == aRequest) { - mIconRequest->Cancel(NS_BINDING_ABORTED); - mIconRequest = nullptr; - } - return NS_OK; -} - -NS_IMETHODIMP -nsMenuItemIconX::OnDiscard(imgIRequest* aRequest) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsMenuItemIconX::OnImageIsAnimated(imgIRequest* aRequest) -{ - return NS_OK; -}