1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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/MediaMetadata.h"
8 #include "mozilla/dom/Document.h"
9 #include "mozilla/dom/MediaSessionBinding.h"
10 #include "mozilla/dom/ScriptSettings.h"
11 #include "mozilla/dom/ToJSValue.h"
12 #include "nsNetUtil.h"
14 namespace mozilla::dom
{
16 // Only needed for refcounted objects.
17 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaMetadata
, mParent
)
18 NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaMetadata
)
19 NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaMetadata
)
20 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaMetadata
)
21 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
22 NS_INTERFACE_MAP_ENTRY(nsISupports
)
25 MediaMetadata::MediaMetadata(nsIGlobalObject
* aParent
, const nsString
& aTitle
,
26 const nsString
& aArtist
, const nsString
& aAlbum
)
27 : MediaMetadataBase(aTitle
, aArtist
, aAlbum
), mParent(aParent
) {
31 nsIGlobalObject
* MediaMetadata::GetParentObject() const { return mParent
; }
33 JSObject
* MediaMetadata::WrapObject(JSContext
* aCx
,
34 JS::Handle
<JSObject
*> aGivenProto
) {
35 return MediaMetadata_Binding::Wrap(aCx
, this, aGivenProto
);
38 already_AddRefed
<MediaMetadata
> MediaMetadata::Constructor(
39 const GlobalObject
& aGlobal
, const MediaMetadataInit
& aInit
,
41 nsCOMPtr
<nsIGlobalObject
> global
= do_QueryInterface(aGlobal
.GetAsSupports());
43 aRv
.Throw(NS_ERROR_FAILURE
);
47 RefPtr
<MediaMetadata
> mediaMetadata
=
48 new MediaMetadata(global
, aInit
.mTitle
, aInit
.mArtist
, aInit
.mAlbum
);
49 mediaMetadata
->SetArtworkInternal(aInit
.mArtwork
, aRv
);
50 return aRv
.Failed() ? nullptr : mediaMetadata
.forget();
53 void MediaMetadata::GetTitle(nsString
& aRetVal
) const { aRetVal
= mTitle
; }
55 void MediaMetadata::SetTitle(const nsAString
& aTitle
) { mTitle
= aTitle
; }
57 void MediaMetadata::GetArtist(nsString
& aRetVal
) const { aRetVal
= mArtist
; }
59 void MediaMetadata::SetArtist(const nsAString
& aArtist
) { mArtist
= aArtist
; }
61 void MediaMetadata::GetAlbum(nsString
& aRetVal
) const { aRetVal
= mAlbum
; }
63 void MediaMetadata::SetAlbum(const nsAString
& aAlbum
) { mAlbum
= aAlbum
; }
65 void MediaMetadata::GetArtwork(JSContext
* aCx
, nsTArray
<JSObject
*>& aRetVal
,
66 ErrorResult
& aRv
) const {
67 // Convert the MediaImages to JS Objects
68 if (!aRetVal
.SetCapacity(mArtwork
.Length(), fallible
)) {
69 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
73 for (size_t i
= 0; i
< mArtwork
.Length(); ++i
) {
74 JS::Rooted
<JS::Value
> value(aCx
);
75 if (!ToJSValue(aCx
, mArtwork
[i
], &value
)) {
76 aRv
.NoteJSContextException(aCx
);
80 JS::Rooted
<JSObject
*> object(aCx
, &value
.toObject());
81 if (!JS_FreezeObject(aCx
, object
)) {
82 aRv
.NoteJSContextException(aCx
);
86 aRetVal
.AppendElement(object
);
90 void MediaMetadata::SetArtwork(JSContext
* aCx
,
91 const Sequence
<JSObject
*>& aArtwork
,
93 // Convert the JS Objects to MediaImages
94 Sequence
<MediaImage
> artwork
;
95 if (!artwork
.SetCapacity(aArtwork
.Length(), fallible
)) {
96 aRv
.Throw(NS_ERROR_OUT_OF_MEMORY
);
100 for (JSObject
* object
: aArtwork
) {
101 JS::Rooted
<JS::Value
> value(aCx
, JS::ObjectValue(*object
));
103 MediaImage
* image
= artwork
.AppendElement(fallible
);
104 MOZ_ASSERT(image
, "The capacity is preallocated");
105 if (!image
->Init(aCx
, value
)) {
106 aRv
.NoteJSContextException(aCx
);
111 SetArtworkInternal(artwork
, aRv
);
114 static nsIURI
* GetEntryBaseURL() {
115 nsCOMPtr
<Document
> doc
= GetEntryDocument();
116 return doc
? doc
->GetDocBaseURI() : nullptr;
119 // `aURL` is an inout parameter.
120 static nsresult
ResolveURL(nsString
& aURL
, nsIURI
* aBaseURI
) {
121 nsCOMPtr
<nsIURI
> uri
;
122 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aURL
,
123 /* UTF-8 for charset */ nullptr, aBaseURI
);
129 rv
= uri
->GetSpec(spec
);
134 CopyUTF8toUTF16(spec
, aURL
);
138 void MediaMetadata::SetArtworkInternal(const Sequence
<MediaImage
>& aArtwork
,
140 nsTArray
<MediaImage
> artwork
;
141 artwork
.Assign(aArtwork
);
143 nsCOMPtr
<nsIURI
> baseURI
= GetEntryBaseURL();
144 for (MediaImage
& image
: artwork
) {
145 nsresult rv
= ResolveURL(image
.mSrc
, baseURI
);
146 if (NS_WARN_IF(NS_FAILED(rv
))) {
147 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(NS_ConvertUTF16toUTF8(image
.mSrc
));
151 mArtwork
= std::move(artwork
);
154 } // namespace mozilla::dom