1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 /**
8 * A fake content node class so that the image frame for
9 * content: url(foo);
10 * in CSS can have an nsIImageLoadingContent but use an
11 * imgIRequest that's already been loaded from the style system.
12 */
13
14 #include "nsContentCreatorFunctions.h"
15 #include "nsXMLElement.h"
16 #include "nsImageLoadingContent.h"
17 #include "imgIRequest.h"
18 #include "mozilla/BasicEvents.h"
19 #include "mozilla/EventDispatcher.h"
20 #include "mozilla/EventStates.h"
21
22 using namespace mozilla;
23
24 class nsGenConImageContent final : public nsXMLElement,
25 public nsImageLoadingContent
26 {
27 public:
nsGenConImageContent(already_AddRefed<mozilla::dom::NodeInfo> & aNodeInfo)28 explicit nsGenConImageContent(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
29 : nsXMLElement(aNodeInfo)
30 {
31 // nsImageLoadingContent starts out broken, so we start out
32 // suppressed to match it.
33 AddStatesSilently(NS_EVENT_STATE_SUPPRESSED);
34 }
35
Init(imgRequestProxy * aImageRequest)36 nsresult Init(imgRequestProxy* aImageRequest)
37 {
38 // No need to notify, since we have no frame.
39 return UseAsPrimaryRequest(aImageRequest, false, eImageLoadType_Normal);
40 }
41
42 // nsIContent overrides
43 virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
44 nsIContent* aBindingParent,
45 bool aCompileEventHandlers) override;
46 virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
47 virtual EventStates IntrinsicState() const override;
48
PreHandleEvent(EventChainPreVisitor & aVisitor)49 virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override
50 {
51 MOZ_ASSERT(IsInNativeAnonymousSubtree());
52 if (aVisitor.mEvent->mMessage == eLoad ||
53 aVisitor.mEvent->mMessage == eLoadError) {
54 // Don't propagate the events to the parent.
55 return NS_OK;
56 }
57 return nsXMLElement::PreHandleEvent(aVisitor);
58 }
59
60 private:
61 virtual ~nsGenConImageContent();
62
63 public:
64 NS_DECL_ISUPPORTS_INHERITED
65 };
66
NS_IMPL_ISUPPORTS_INHERITED(nsGenConImageContent,nsXMLElement,nsIImageLoadingContent,imgINotificationObserver,imgIOnloadBlocker)67 NS_IMPL_ISUPPORTS_INHERITED(nsGenConImageContent,
68 nsXMLElement,
69 nsIImageLoadingContent,
70 imgINotificationObserver,
71 imgIOnloadBlocker)
72
73 nsresult
74 NS_NewGenConImageContent(nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
75 imgRequestProxy* aImageRequest)
76 {
77 NS_PRECONDITION(aImageRequest, "Must have request!");
78 nsGenConImageContent *it = new nsGenConImageContent(aNodeInfo);
79 NS_ADDREF(*aResult = it);
80 nsresult rv = it->Init(aImageRequest);
81 if (NS_FAILED(rv))
82 NS_RELEASE(*aResult);
83 return rv;
84 }
85
~nsGenConImageContent()86 nsGenConImageContent::~nsGenConImageContent()
87 {
88 DestroyImageLoadingContent();
89 }
90
91 nsresult
BindToTree(nsIDocument * aDocument,nsIContent * aParent,nsIContent * aBindingParent,bool aCompileEventHandlers)92 nsGenConImageContent::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
93 nsIContent* aBindingParent,
94 bool aCompileEventHandlers)
95 {
96 nsresult rv;
97 rv = nsXMLElement::BindToTree(aDocument, aParent, aBindingParent,
98 aCompileEventHandlers);
99 NS_ENSURE_SUCCESS(rv, rv);
100
101 nsImageLoadingContent::BindToTree(aDocument, aParent, aBindingParent,
102 aCompileEventHandlers);
103 return NS_OK;
104 }
105
106 void
UnbindFromTree(bool aDeep,bool aNullParent)107 nsGenConImageContent::UnbindFromTree(bool aDeep, bool aNullParent)
108 {
109 nsImageLoadingContent::UnbindFromTree(aDeep, aNullParent);
110 nsXMLElement::UnbindFromTree(aDeep, aNullParent);
111 }
112
113 EventStates
IntrinsicState() const114 nsGenConImageContent::IntrinsicState() const
115 {
116 EventStates state = nsXMLElement::IntrinsicState();
117
118 EventStates imageState = nsImageLoadingContent::ImageState();
119 if (imageState.HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN | NS_EVENT_STATE_USERDISABLED)) {
120 // We should never be in an error state; if the image fails to load, we
121 // just go to the suppressed state.
122 imageState |= NS_EVENT_STATE_SUPPRESSED;
123 imageState &= ~NS_EVENT_STATE_BROKEN;
124 }
125 imageState &= ~NS_EVENT_STATE_LOADING;
126 return state | imageState;
127 }
128