MediaList.cpp (5357B)
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 /* base class for representation of media lists */ 8 9 #include "mozilla/dom/MediaList.h" 10 11 #include "mozAutoDocUpdate.h" 12 #include "mozilla/ServoBindings.h" 13 #include "mozilla/ServoStyleSet.h" 14 #include "mozilla/StyleSheetInlines.h" 15 #include "mozilla/dom/Document.h" 16 #include "mozilla/dom/DocumentInlines.h" 17 #include "mozilla/dom/MediaListBinding.h" 18 19 namespace mozilla::dom { 20 21 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaList) 22 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 23 NS_INTERFACE_MAP_ENTRY(nsISupports) 24 NS_INTERFACE_MAP_END 25 26 NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaList) 27 NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaList) 28 29 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(MediaList) 30 31 JSObject* MediaList::WrapObject(JSContext* aCx, 32 JS::Handle<JSObject*> aGivenProto) { 33 return MediaList_Binding::Wrap(aCx, this, aGivenProto); 34 } 35 36 void MediaList::SetStyleSheet(StyleSheet* aSheet) { 37 MOZ_ASSERT(aSheet == mStyleSheet || !aSheet || !mStyleSheet, 38 "Multiple style sheets competing for one media list"); 39 mStyleSheet = aSheet; 40 } 41 42 nsISupports* MediaList::GetParentObject() const { return mStyleSheet; } 43 44 template <typename Func> 45 void MediaList::DoMediaChange(Func aCallback, ErrorResult& aRv) { 46 if (IsReadOnly()) { 47 return; 48 } 49 50 if (mStyleSheet) { 51 mStyleSheet->WillDirty(); 52 } 53 54 aCallback(aRv); 55 if (aRv.Failed()) { 56 return; 57 } 58 59 if (mStyleSheet) { 60 // FIXME(emilio): We should discern between "owned by a rule" (as in @media) 61 // and "owned by a sheet" (as in <style media>), and then pass something 62 // meaningful here. 63 mStyleSheet->RuleChanged(nullptr, StyleRuleChangeKind::Generic); 64 } 65 } 66 67 already_AddRefed<MediaList> MediaList::Clone() { 68 return MakeAndAddRef<MediaList>( 69 Servo_MediaList_DeepClone(mRawList).Consume()); 70 } 71 72 MediaList::MediaList() : mRawList(Servo_MediaList_Create().Consume()) {} 73 74 MediaList::MediaList(const nsACString& aMedia, CallerType aCallerType) 75 : MediaList() { 76 SetTextInternal(aMedia, aCallerType); 77 } 78 79 void MediaList::GetText(nsACString& aMediaText) const { 80 Servo_MediaList_GetText(mRawList, &aMediaText); 81 } 82 83 /* static */ 84 already_AddRefed<MediaList> MediaList::Create(const nsACString& aMedia, 85 CallerType aCallerType) { 86 return do_AddRef(new MediaList(aMedia, aCallerType)); 87 } 88 89 void MediaList::SetText(const nsACString& aMediaText) { 90 if (IsReadOnly()) { 91 return; 92 } 93 94 SetTextInternal(aMediaText, CallerType::NonSystem); 95 } 96 97 void MediaList::SetTextInternal(const nsACString& aMediaText, 98 CallerType aCallerType) { 99 Servo_MediaList_SetText(mRawList, &aMediaText, aCallerType); 100 } 101 102 uint32_t MediaList::Length() const { 103 return Servo_MediaList_GetLength(mRawList); 104 } 105 106 bool MediaList::IsViewportDependent() const { 107 return Servo_MediaList_IsViewportDependent(mRawList); 108 } 109 110 void MediaList::IndexedGetter(uint32_t aIndex, bool& aFound, 111 nsACString& aReturn) const { 112 aFound = Servo_MediaList_GetMediumAt(mRawList, aIndex, &aReturn); 113 if (!aFound) { 114 aReturn.SetIsVoid(true); 115 } 116 } 117 118 void MediaList::Delete(const nsACString& aOldMedium, ErrorResult& aRv) { 119 MOZ_ASSERT(!IsReadOnly()); 120 if (Servo_MediaList_DeleteMedium(mRawList, &aOldMedium)) { 121 return; 122 } 123 aRv.ThrowNotFoundError("Medium not in list"); 124 } 125 126 bool MediaList::Matches(const Document& aDocument) const { 127 const auto* rawData = aDocument.EnsureStyleSet().RawData(); 128 MOZ_ASSERT(rawData, "The per doc data should be valid!"); 129 return Servo_MediaList_Matches(mRawList, rawData); 130 } 131 132 void MediaList::Append(const nsACString& aNewMedium, ErrorResult& aRv) { 133 MOZ_ASSERT(!IsReadOnly()); 134 if (aNewMedium.IsEmpty()) { 135 // XXXbz per spec there should not be an exception here, as far as 136 // I can tell... 137 aRv.ThrowNotFoundError("Empty medium"); 138 return; 139 } 140 Servo_MediaList_AppendMedium(mRawList, &aNewMedium); 141 } 142 143 void MediaList::SetMediaText(const nsACString& aMediaText) { 144 DoMediaChange([&](ErrorResult& aRv) { SetText(aMediaText); }, IgnoreErrors()); 145 } 146 147 void MediaList::Item(uint32_t aIndex, nsACString& aReturn) { 148 bool dummy; 149 IndexedGetter(aIndex, dummy, aReturn); 150 } 151 152 void MediaList::DeleteMedium(const nsACString& aOldMedium, ErrorResult& aRv) { 153 DoMediaChange([&](ErrorResult& aRv) { Delete(aOldMedium, aRv); }, aRv); 154 } 155 156 void MediaList::AppendMedium(const nsACString& aNewMedium, ErrorResult& aRv) { 157 DoMediaChange([&](ErrorResult& aRv) { Append(aNewMedium, aRv); }, aRv); 158 } 159 160 MOZ_DEFINE_MALLOC_SIZE_OF(ServoMediaListMallocSizeOf) 161 MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoMediaListMallocEnclosingSizeOf) 162 163 size_t MediaList::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { 164 size_t n = 0; 165 n += Servo_MediaList_SizeOfIncludingThis(ServoMediaListMallocSizeOf, 166 ServoMediaListMallocEnclosingSizeOf, 167 mRawList); 168 return n; 169 } 170 171 bool MediaList::IsReadOnly() const { 172 return mStyleSheet && mStyleSheet->IsReadOnly(); 173 } 174 175 } // namespace mozilla::dom