diff options
Diffstat (limited to 'layout/style/MediaList.cpp')
-rw-r--r-- | layout/style/MediaList.cpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/layout/style/MediaList.cpp b/layout/style/MediaList.cpp new file mode 100644 index 0000000000..b4e477c901 --- /dev/null +++ b/layout/style/MediaList.cpp @@ -0,0 +1,176 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* base class for representation of media lists */ + +#include "mozilla/dom/MediaList.h" + +#include "mozAutoDocUpdate.h" +#include "mozilla/dom/Document.h" +#include "mozilla/dom/MediaListBinding.h" +#include "mozilla/ServoBindings.h" +#include "mozilla/ServoStyleSet.h" +#include "mozilla/StyleSheetInlines.h" + +namespace mozilla::dom { + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaList) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaList) +NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaList) + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(MediaList) + +JSObject* MediaList::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) { + return MediaList_Binding::Wrap(aCx, this, aGivenProto); +} + +void MediaList::SetStyleSheet(StyleSheet* aSheet) { + MOZ_ASSERT(aSheet == mStyleSheet || !aSheet || !mStyleSheet, + "Multiple style sheets competing for one media list"); + mStyleSheet = aSheet; +} + +nsISupports* MediaList::GetParentObject() const { return mStyleSheet; } + +template <typename Func> +void MediaList::DoMediaChange(Func aCallback, ErrorResult& aRv) { + if (IsReadOnly()) { + return; + } + + if (mStyleSheet) { + mStyleSheet->WillDirty(); + } + + aCallback(aRv); + if (aRv.Failed()) { + return; + } + + if (mStyleSheet) { + // FIXME(emilio): We should discern between "owned by a rule" (as in @media) + // and "owned by a sheet" (as in <style media>), and then pass something + // meaningful here. + mStyleSheet->RuleChanged(nullptr, StyleRuleChangeKind::Generic); + } +} + +already_AddRefed<MediaList> MediaList::Clone() { + RefPtr<MediaList> clone = + new MediaList(Servo_MediaList_DeepClone(mRawList).Consume()); + return clone.forget(); +} + +MediaList::MediaList() : mRawList(Servo_MediaList_Create().Consume()) {} + +MediaList::MediaList(const nsACString& aMedia, CallerType aCallerType) + : MediaList() { + SetTextInternal(aMedia, aCallerType); +} + +void MediaList::GetText(nsACString& aMediaText) const { + Servo_MediaList_GetText(mRawList, &aMediaText); +} + +/* static */ +already_AddRefed<MediaList> MediaList::Create(const nsACString& aMedia, + CallerType aCallerType) { + return do_AddRef(new MediaList(aMedia, aCallerType)); +} + +void MediaList::SetText(const nsACString& aMediaText) { + if (IsReadOnly()) { + return; + } + + SetTextInternal(aMediaText, CallerType::NonSystem); +} + +void MediaList::SetTextInternal(const nsACString& aMediaText, + CallerType aCallerType) { + Servo_MediaList_SetText(mRawList, &aMediaText, aCallerType); +} + +uint32_t MediaList::Length() const { + return Servo_MediaList_GetLength(mRawList); +} + +bool MediaList::IsViewportDependent() const { + return Servo_MediaList_IsViewportDependent(mRawList); +} + +void MediaList::IndexedGetter(uint32_t aIndex, bool& aFound, + nsACString& aReturn) const { + aFound = Servo_MediaList_GetMediumAt(mRawList, aIndex, &aReturn); + if (!aFound) { + aReturn.SetIsVoid(true); + } +} + +void MediaList::Delete(const nsACString& aOldMedium, ErrorResult& aRv) { + MOZ_ASSERT(!IsReadOnly()); + if (Servo_MediaList_DeleteMedium(mRawList, &aOldMedium)) { + return; + } + aRv.ThrowNotFoundError("Medium not in list"); +} + +bool MediaList::Matches(const Document& aDocument) const { + const auto* rawData = + aDocument.StyleSetForPresShellOrMediaQueryEvaluation()->RawData(); + MOZ_ASSERT(rawData, "The per doc data should be valid!"); + return Servo_MediaList_Matches(mRawList, rawData); +} + +void MediaList::Append(const nsACString& aNewMedium, ErrorResult& aRv) { + MOZ_ASSERT(!IsReadOnly()); + if (aNewMedium.IsEmpty()) { + // XXXbz per spec there should not be an exception here, as far as + // I can tell... + aRv.ThrowNotFoundError("Empty medium"); + return; + } + Servo_MediaList_AppendMedium(mRawList, &aNewMedium); +} + +void MediaList::SetMediaText(const nsACString& aMediaText) { + DoMediaChange([&](ErrorResult& aRv) { SetText(aMediaText); }, IgnoreErrors()); +} + +void MediaList::Item(uint32_t aIndex, nsACString& aReturn) { + bool dummy; + IndexedGetter(aIndex, dummy, aReturn); +} + +void MediaList::DeleteMedium(const nsACString& aOldMedium, ErrorResult& aRv) { + DoMediaChange([&](ErrorResult& aRv) { Delete(aOldMedium, aRv); }, aRv); +} + +void MediaList::AppendMedium(const nsACString& aNewMedium, ErrorResult& aRv) { + DoMediaChange([&](ErrorResult& aRv) { Append(aNewMedium, aRv); }, aRv); +} + +MOZ_DEFINE_MALLOC_SIZE_OF(ServoMediaListMallocSizeOf) +MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoMediaListMallocEnclosingSizeOf) + +size_t MediaList::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { + size_t n = 0; + n += Servo_MediaList_SizeOfIncludingThis(ServoMediaListMallocSizeOf, + ServoMediaListMallocEnclosingSizeOf, + mRawList); + return n; +} + +bool MediaList::IsReadOnly() const { + return mStyleSheet && mStyleSheet->IsReadOnly(); +} + +} // namespace mozilla::dom |