michael@0: michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * A fake content node class so that the image frame for michael@0: * content: url(foo); michael@0: * in CSS can have an nsIImageLoadingContent but use an michael@0: * imgIRequest that's already been loaded from the style system. michael@0: */ michael@0: michael@0: #include "nsContentCreatorFunctions.h" michael@0: #include "nsXMLElement.h" michael@0: #include "nsImageLoadingContent.h" michael@0: #include "imgIRequest.h" michael@0: #include "mozilla/BasicEvents.h" michael@0: #include "mozilla/EventDispatcher.h" michael@0: #include "mozilla/EventStates.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: class nsGenConImageContent MOZ_FINAL : public nsXMLElement, michael@0: public nsImageLoadingContent michael@0: { michael@0: public: michael@0: nsGenConImageContent(already_AddRefed& aNodeInfo) michael@0: : nsXMLElement(aNodeInfo) michael@0: { michael@0: // nsImageLoadingContent starts out broken, so we start out michael@0: // suppressed to match it. michael@0: AddStatesSilently(NS_EVENT_STATE_SUPPRESSED); michael@0: } michael@0: michael@0: nsresult Init(imgRequestProxy* aImageRequest) michael@0: { michael@0: // No need to notify, since we have no frame. michael@0: return UseAsPrimaryRequest(aImageRequest, false); michael@0: } michael@0: michael@0: // nsIContent overrides michael@0: virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, michael@0: nsIContent* aBindingParent, michael@0: bool aCompileEventHandlers); michael@0: virtual void UnbindFromTree(bool aDeep, bool aNullParent); michael@0: virtual EventStates IntrinsicState() const; michael@0: michael@0: virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) michael@0: { michael@0: MOZ_ASSERT(IsInNativeAnonymousSubtree()); michael@0: if (aVisitor.mEvent->message == NS_LOAD || michael@0: aVisitor.mEvent->message == NS_LOAD_ERROR) { michael@0: // Don't propagate the events to the parent. michael@0: return NS_OK; michael@0: } michael@0: return nsXMLElement::PreHandleEvent(aVisitor); michael@0: } michael@0: michael@0: private: michael@0: virtual ~nsGenConImageContent(); michael@0: michael@0: public: michael@0: NS_DECL_ISUPPORTS_INHERITED michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS_INHERITED(nsGenConImageContent, michael@0: nsXMLElement, michael@0: nsIImageLoadingContent, michael@0: imgINotificationObserver, michael@0: imgIOnloadBlocker) michael@0: michael@0: nsresult michael@0: NS_NewGenConImageContent(nsIContent** aResult, already_AddRefed&& aNodeInfo, michael@0: imgRequestProxy* aImageRequest) michael@0: { michael@0: NS_PRECONDITION(aImageRequest, "Must have request!"); michael@0: nsGenConImageContent *it = new nsGenConImageContent(aNodeInfo); michael@0: if (!it) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: NS_ADDREF(*aResult = it); michael@0: nsresult rv = it->Init(aImageRequest); michael@0: if (NS_FAILED(rv)) michael@0: NS_RELEASE(*aResult); michael@0: return rv; michael@0: } michael@0: michael@0: nsGenConImageContent::~nsGenConImageContent() michael@0: { michael@0: DestroyImageLoadingContent(); michael@0: } michael@0: michael@0: nsresult michael@0: nsGenConImageContent::BindToTree(nsIDocument* aDocument, nsIContent* aParent, michael@0: nsIContent* aBindingParent, michael@0: bool aCompileEventHandlers) michael@0: { michael@0: nsresult rv; michael@0: rv = nsXMLElement::BindToTree(aDocument, aParent, aBindingParent, michael@0: aCompileEventHandlers); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent, michael@0: aCompileEventHandlers); michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsGenConImageContent::UnbindFromTree(bool aDeep, bool aNullParent) michael@0: { michael@0: nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent); michael@0: nsXMLElement::UnbindFromTree(aDeep, aNullParent); michael@0: } michael@0: michael@0: EventStates michael@0: nsGenConImageContent::IntrinsicState() const michael@0: { michael@0: EventStates state = nsXMLElement::IntrinsicState(); michael@0: michael@0: EventStates imageState = nsImageLoadingContent::ImageState(); michael@0: if (imageState.HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED)) { michael@0: // We should never be in an error state; if the image fails to load, we michael@0: // just go to the suppressed state. michael@0: imageState |= NS_EVENT_STATE_SUPPRESSED; michael@0: imageState &= ~NS_EVENT_STATE_BROKEN; michael@0: } michael@0: imageState &= ~NS_EVENT_STATE_LOADING; michael@0: return state | imageState; michael@0: }