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/. */
7 #include "mozilla/dom/HTMLSourceElement.h"
8 #include "mozilla/dom/HTMLSourceElementBinding.h"
10 #include "mozilla/dom/HTMLImageElement.h"
11 #include "mozilla/dom/HTMLMediaElement.h"
12 #include "mozilla/dom/ResponsiveImageSelector.h"
13 #include "mozilla/dom/MediaList.h"
14 #include "mozilla/dom/MediaSource.h"
16 #include "nsGkAtoms.h"
18 #include "mozilla/dom/BlobURLProtocolHandler.h"
19 #include "mozilla/Preferences.h"
21 NS_IMPL_NS_NEW_HTML_ELEMENT(Source
)
26 HTMLSourceElement::HTMLSourceElement(already_AddRefed
<mozilla::dom::NodeInfo
>&& aNodeInfo
)
27 : nsGenericHTMLElement(std::move(aNodeInfo
))
31 HTMLSourceElement::~HTMLSourceElement()
35 NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLSourceElement
, nsGenericHTMLElement
,
38 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(HTMLSourceElement
, nsGenericHTMLElement
)
40 NS_IMPL_ELEMENT_CLONE(HTMLSourceElement
)
43 HTMLSourceElement::MatchesCurrentMedia()
46 nsPresContext
* pctx
= OwnerDoc()->GetPresContext();
47 return pctx
&& mMediaList
->Matches(pctx
);
55 HTMLSourceElement::WouldMatchMediaForDocument(const nsAString
& aMedia
,
56 const nsIDocument
*aDocument
)
58 if (aMedia
.IsEmpty()) {
62 nsPresContext
* pctx
= aDocument
->GetPresContext();
64 RefPtr
<MediaList
> mediaList
= MediaList::Create(aMedia
);
65 return pctx
&& mediaList
->Matches(pctx
);
69 HTMLSourceElement::UpdateMediaList(const nsAttrValue
* aValue
)
73 if (!aValue
|| (mediaStr
= aValue
->GetStringValue()).IsEmpty()) {
77 mMediaList
= MediaList::Create(mediaStr
);
81 HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID
, nsAtom
* aName
,
82 const nsAttrValue
* aValue
,
83 const nsAttrValue
* aOldValue
,
84 nsIPrincipal
* aMaybeScriptedPrincipal
,
87 if (aNameSpaceID
== kNameSpaceID_None
&& aName
== nsGkAtoms::srcset
) {
88 mSrcsetTriggeringPrincipal
= nsContentUtils::GetAttrTriggeringPrincipal(
89 this, aValue
? aValue
->GetStringValue() : EmptyString(),
90 aMaybeScriptedPrincipal
);
92 // If we are associated with a <picture> with a valid <img>, notify it of
93 // responsive parameter changes
94 Element
*parent
= nsINode::GetParentElement();
95 if (aNameSpaceID
== kNameSpaceID_None
&&
96 (aName
== nsGkAtoms::srcset
||
97 aName
== nsGkAtoms::sizes
||
98 aName
== nsGkAtoms::media
||
99 aName
== nsGkAtoms::type
) &&
100 parent
&& parent
->IsHTMLElement(nsGkAtoms::picture
)) {
101 nsString strVal
= aValue
? aValue
->GetStringValue() : EmptyString();
102 // Find all img siblings after this <source> and notify them of the change
103 nsCOMPtr
<nsIContent
> sibling
= AsContent();
104 while ( (sibling
= sibling
->GetNextSibling()) ) {
105 if (sibling
->IsHTMLElement(nsGkAtoms::img
)) {
106 HTMLImageElement
*img
= static_cast<HTMLImageElement
*>(sibling
.get());
107 if (aName
== nsGkAtoms::srcset
) {
108 img
->PictureSourceSrcsetChanged(AsContent(), strVal
, aNotify
);
109 } else if (aName
== nsGkAtoms::sizes
) {
110 img
->PictureSourceSizesChanged(AsContent(), strVal
, aNotify
);
111 } else if (aName
== nsGkAtoms::media
) {
112 UpdateMediaList(aValue
);
113 img
->PictureSourceMediaOrTypeChanged(AsContent(), aNotify
);
114 } else if (aName
== nsGkAtoms::type
) {
115 img
->PictureSourceMediaOrTypeChanged(AsContent(), aNotify
);
120 } else if (aNameSpaceID
== kNameSpaceID_None
&& aName
== nsGkAtoms::media
) {
121 UpdateMediaList(aValue
);
122 } else if (aNameSpaceID
== kNameSpaceID_None
&& aName
== nsGkAtoms::src
) {
123 mSrcTriggeringPrincipal
= nsContentUtils::GetAttrTriggeringPrincipal(
124 this, aValue
? aValue
->GetStringValue() : EmptyString(),
125 aMaybeScriptedPrincipal
);
126 mSrcMediaSource
= nullptr;
128 nsString srcStr
= aValue
->GetStringValue();
129 nsCOMPtr
<nsIURI
> uri
;
130 NewURIFromString(srcStr
, getter_AddRefs(uri
));
131 if (uri
&& IsMediaSourceURI(uri
)) {
132 NS_GetSourceForMediaSourceURI(uri
, getter_AddRefs(mSrcMediaSource
));
137 return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID
, aName
,
139 aMaybeScriptedPrincipal
,
144 HTMLSourceElement::BindToTree(nsIDocument
*aDocument
,
146 nsIContent
*aBindingParent
)
148 nsresult rv
= nsGenericHTMLElement::BindToTree(aDocument
,
151 NS_ENSURE_SUCCESS(rv
, rv
);
153 if (auto* media
= HTMLMediaElement::FromNodeOrNull(aParent
)) {
154 media
->NotifyAddedSource();
161 HTMLSourceElement::WrapNode(JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
)
163 return HTMLSourceElement_Binding::Wrap(aCx
, this, aGivenProto
);
167 } // namespace mozilla